diff --git a/src/reader/spirv/function.cc b/src/reader/spirv/function.cc index 79bbd0e54d..399ed3f514 100644 --- a/src/reader/spirv/function.cc +++ b/src/reader/spirv/function.cc @@ -30,6 +30,7 @@ #include "src/ast/else_statement.h" #include "src/ast/identifier_expression.h" #include "src/ast/if_statement.h" +#include "src/ast/kill_statement.h" #include "src/ast/loop_statement.h" #include "src/ast/member_accessor_expression.h" #include "src/ast/return_statement.h" @@ -1766,6 +1767,11 @@ bool FunctionEmitter::EmitNormalTerminator(const BlockInfo& block_info) { std::make_unique(std::move(value.expr))); } return true; + case SpvOpKill: + // For now, assume SPIR-V OpKill has same semantics as WGSL kill. + // TODO(dneto): https://github.com/gpuweb/gpuweb/issues/676 + AddStatement(std::make_unique()); + return true; default: break; } diff --git a/src/reader/spirv/function_cfg_test.cc b/src/reader/spirv/function_cfg_test.cc index 58e4502ddb..1f05bbc0ef 100644 --- a/src/reader/spirv/function_cfg_test.cc +++ b/src/reader/spirv/function_cfg_test.cc @@ -7861,6 +7861,92 @@ Return{ )")) << ToString(fe.ast_body()); } +TEST_F(SpvParserTest, EmitBody_Kill_TopLevel) { + auto* p = parser(test::Assemble(CommonTypes() + R"( + %100 = OpFunction %void None %voidfn + + %10 = OpLabel + OpKill + + OpFunctionEnd + )")); + ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error(); + FunctionEmitter fe(p, *spirv_function(100)); + EXPECT_TRUE(fe.EmitBody()) << p->error(); + + EXPECT_THAT(ToString(fe.ast_body()), Eq(R"(Kill{} +)")) << ToString(fe.ast_body()); +} + +TEST_F(SpvParserTest, EmitBody_Kill_InsideIf) { + auto* p = parser(test::Assemble(CommonTypes() + R"( + %100 = OpFunction %void None %voidfn + + %10 = OpLabel + OpSelectionMerge %99 None + OpBranchConditional %cond %20 %99 + + %20 = OpLabel + OpKill + + %99 = OpLabel + OpKill + + OpFunctionEnd + )")); + ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error(); + FunctionEmitter fe(p, *spirv_function(100)); + EXPECT_TRUE(fe.EmitBody()) << p->error(); + + EXPECT_THAT(ToString(fe.ast_body()), Eq(R"(If{ + ( + ScalarConstructor{false} + ) + { + Kill{} + } +} +Else{ + { + } +} +Kill{} +)")) << ToString(fe.ast_body()); +} + +TEST_F(SpvParserTest, EmitBody_Kill_InsideLoop) { + auto* p = parser(test::Assemble(CommonTypes() + R"( + %100 = OpFunction %void None %voidfn + + %10 = OpLabel + OpBranch %20 + + %20 = OpLabel + OpLoopMerge %99 %80 None + OpBranchConditional %cond %30 %30 + + %30 = OpLabel + OpKill + + %80 = OpLabel + OpBranch %20 + + %99 = OpLabel + OpKill + + OpFunctionEnd + )")); + ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error(); + FunctionEmitter fe(p, *spirv_function(100)); + EXPECT_TRUE(fe.EmitBody()) << p->error(); + + EXPECT_THAT(ToString(fe.ast_body()), Eq(R"(Loop{ + Kill{} +} +Kill{} +)")) << ToString(fe.ast_body()); +} + } // namespace } // namespace spirv } // namespace reader