spirv builder: allow unsigned int cases for switch statements Change-Id: If7a8955961b56925cae538249d4e17495d3f8e1b Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/42901 Reviewed-by: David Neto <dneto@google.com> Commit-Queue: David Neto <dneto@google.com>
diff --git a/src/writer/spirv/builder.cc b/src/writer/spirv/builder.cc index 26b2c8e..0d673f7 100644 --- a/src/writer/spirv/builder.cc +++ b/src/writer/spirv/builder.cc
@@ -2618,12 +2618,13 @@ case_ids.push_back(block_id); for (auto* selector : item->selectors()) { - if (!selector->Is<ast::SintLiteral>()) { + auto* int_literal = selector->As<ast::IntLiteral>(); + if (!int_literal) { error_ = "expected integer literal for switch case label"; return false; } - params.push_back(Operand::Int(selector->As<ast::SintLiteral>()->value())); + params.push_back(Operand::Int(int_literal->value_as_u32())); params.push_back(Operand::Int(block_id)); } }
diff --git a/src/writer/spirv/builder_switch_test.cc b/src/writer/spirv/builder_switch_test.cc index c0ee18f..9dcf3da 100644 --- a/src/writer/spirv/builder_switch_test.cc +++ b/src/writer/spirv/builder_switch_test.cc
@@ -136,6 +136,81 @@ )"); } +TEST_F(BuilderTest, Switch_WithCase_Unsigned) { + // switch(a) { + // case 1u: + // v = 1; + // case 2u: + // v = 2; + // } + + auto* v = Global("v", ty.i32(), ast::StorageClass::kPrivate); + auto* a = Global("a", ty.u32(), ast::StorageClass::kPrivate); + + auto* case_1_body = create<ast::BlockStatement>( + ast::StatementList{create<ast::AssignmentStatement>(Expr("v"), Expr(1))}); + + auto* case_2_body = create<ast::BlockStatement>( + ast::StatementList{create<ast::AssignmentStatement>(Expr("v"), Expr(2))}); + + ast::CaseSelectorList selector_1; + selector_1.push_back(Literal(1u)); + + ast::CaseSelectorList selector_2; + selector_2.push_back(Literal(2u)); + + ast::CaseStatementList cases; + cases.push_back(create<ast::CaseStatement>(selector_1, case_1_body)); + cases.push_back(create<ast::CaseStatement>(selector_2, case_2_body)); + + auto* expr = create<ast::SwitchStatement>(Expr("a"), cases); + + WrapInFunction(expr); + + auto* func = Func("a_func", {}, ty.i32(), ast::StatementList{}, + ast::FunctionDecorationList{}); + + spirv::Builder& b = Build(); + + ASSERT_TRUE(b.GenerateGlobalVariable(v)) << b.error(); + ASSERT_TRUE(b.GenerateGlobalVariable(a)) << b.error(); + ASSERT_TRUE(b.GenerateFunction(func)) << b.error(); + + EXPECT_TRUE(b.GenerateSwitchStatement(expr)) << b.error(); + + EXPECT_EQ(DumpBuilder(b), R"(OpName %1 "v" +OpName %5 "a" +OpName %10 "a_func" +%3 = OpTypeInt 32 1 +%2 = OpTypePointer Private %3 +%4 = OpConstantNull %3 +%1 = OpVariable %2 Private %4 +%7 = OpTypeInt 32 0 +%6 = OpTypePointer Private %7 +%8 = OpConstantNull %7 +%5 = OpVariable %6 Private %8 +%9 = OpTypeFunction %3 +%17 = OpConstant %3 1 +%18 = OpConstant %3 2 +%10 = OpFunction %3 None %9 +%11 = OpLabel +%13 = OpLoad %7 %5 +OpSelectionMerge %12 None +OpSwitch %13 %14 1 %15 2 %16 +%15 = OpLabel +OpStore %1 %17 +OpBranch %12 +%16 = OpLabel +OpStore %1 %18 +OpBranch %12 +%14 = OpLabel +OpBranch %12 +%12 = OpLabel +OpReturn +OpFunctionEnd +)"); +} + TEST_F(BuilderTest, Switch_WithDefault) { // switch(true) { // default: