spirv-reader: support SSign extended instruction

Fixed: tint:1062
Change-Id: I568f4fad0e5d110d06f2515fde1a31764c65e39a
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/113320
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: David Neto <dneto@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Auto-Submit: David Neto <dneto@google.com>
diff --git a/src/tint/reader/spirv/function.cc b/src/tint/reader/spirv/function.cc
index 74d39f9..33f2bdb 100644
--- a/src/tint/reader/spirv/function.cc
+++ b/src/tint/reader/spirv/function.cc
@@ -386,6 +386,7 @@
         case GLSLstd450Pow:
             return "pow";
         case GLSLstd450FSign:
+        case GLSLstd450SSign:
             return "sign";
         case GLSLstd450Radians:
             return "radians";
@@ -427,8 +428,6 @@
             // TODO(dneto) - The following are not implemented.
             // They are grouped semantically, as in GLSL.std.450.h.
 
-        case GLSLstd450SSign:
-
         case GLSLstd450Asinh:
         case GLSLstd450Acosh:
         case GLSLstd450Atanh:
diff --git a/src/tint/reader/spirv/function_glsl_std_450_test.cc b/src/tint/reader/spirv/function_glsl_std_450_test.cc
index 584ec2a..f0e7e2a 100644
--- a/src/tint/reader/spirv/function_glsl_std_450_test.cc
+++ b/src/tint/reader/spirv/function_glsl_std_450_test.cc
@@ -175,6 +175,8 @@
 
 using SpvParserTest_GlslStd450_Inting_Inting =
     SpvParserTestBase<::testing::TestWithParam<GlslStd450Case>>;
+using SpvParserTest_GlslStd450_Inting_Inting_SignednessCoercing =
+    SpvParserTestBase<::testing::TestWithParam<GlslStd450Case>>;
 using SpvParserTest_GlslStd450_Inting_IntingInting =
     SpvParserTestBase<::testing::TestWithParam<GlslStd450Case>>;
 using SpvParserTest_GlslStd450_Inting_IntingIntingInting =
@@ -490,6 +492,42 @@
     EXPECT_THAT(body, HasSubstr("let x_1 : i32 = " + GetParam().wgsl_func + "(i1);")) << body;
 }
 
+TEST_P(SpvParserTest_GlslStd450_Inting_Inting_SignednessCoercing, Scalar_UnsignedArg) {
+    const auto assembly = Preamble() + R"(
+     %1 = OpExtInst %int %glsl )" +
+                          GetParam().opcode +
+                          R"( %u1
+     OpReturn
+     OpFunctionEnd
+  )";
+    auto p = parser(test::Assemble(assembly));
+    ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
+    auto fe = p->function_emitter(100);
+    EXPECT_TRUE(fe.EmitBody()) << p->error();
+    auto ast_body = fe.ast_body();
+    const auto body = test::ToString(p->program(), ast_body);
+    EXPECT_THAT(body, HasSubstr("let x_1 : i32 = " + GetParam().wgsl_func + "(bitcast<i32>(u1));"))
+        << body;
+}
+
+TEST_P(SpvParserTest_GlslStd450_Inting_Inting_SignednessCoercing, Scalar_UnsignedResult) {
+    const auto assembly = Preamble() + R"(
+     %1 = OpExtInst %uint %glsl )" +
+                          GetParam().opcode +
+                          R"( %i1
+     OpReturn
+     OpFunctionEnd
+  )";
+    auto p = parser(test::Assemble(assembly));
+    ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
+    auto fe = p->function_emitter(100);
+    EXPECT_TRUE(fe.EmitBody()) << p->error();
+    auto ast_body = fe.ast_body();
+    const auto body = test::ToString(p->program(), ast_body);
+    EXPECT_THAT(body, HasSubstr("let x_1 : u32 = bitcast<u32>(" + GetParam().wgsl_func + "(i1));"))
+        << body;
+}
+
 TEST_P(SpvParserTest_GlslStd450_Inting_Inting, Vector) {
     const auto assembly = Preamble() + R"(
      %1 = OpExtInst %v2int %glsl )" +
@@ -508,6 +546,44 @@
         << body;
 }
 
+TEST_P(SpvParserTest_GlslStd450_Inting_Inting_SignednessCoercing, Vector_UnsignedArg) {
+    const auto assembly = Preamble() + R"(
+     %1 = OpExtInst %v2int %glsl )" +
+                          GetParam().opcode +
+                          R"( %v2u1
+     OpReturn
+     OpFunctionEnd
+  )";
+    auto p = parser(test::Assemble(assembly));
+    ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
+    auto fe = p->function_emitter(100);
+    EXPECT_TRUE(fe.EmitBody()) << p->error();
+    auto ast_body = fe.ast_body();
+    const auto body = test::ToString(p->program(), ast_body);
+    EXPECT_THAT(body, HasSubstr("let x_1 : vec2<i32> = " + GetParam().wgsl_func +
+                                "(bitcast<vec2<i32>>(v2u1));"))
+        << body;
+}
+
+TEST_P(SpvParserTest_GlslStd450_Inting_Inting_SignednessCoercing, Vector_UnsignedResult) {
+    const auto assembly = Preamble() + R"(
+     %1 = OpExtInst %v2uint %glsl )" +
+                          GetParam().opcode +
+                          R"( %v2i1
+     OpReturn
+     OpFunctionEnd
+  )";
+    auto p = parser(test::Assemble(assembly));
+    ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
+    auto fe = p->function_emitter(100);
+    EXPECT_TRUE(fe.EmitBody()) << p->error();
+    auto ast_body = fe.ast_body();
+    const auto body = test::ToString(p->program(), ast_body);
+    EXPECT_THAT(body, HasSubstr("let x_1 : vec2<u32> = bitcast<vec2<u32>>(" + GetParam().wgsl_func +
+                                "(v2i1));"))
+        << body;
+}
+
 TEST_P(SpvParserTest_GlslStd450_Inting_IntingInting, Scalar) {
     const auto assembly = Preamble() + R"(
      %1 = OpExtInst %int %glsl )" +
@@ -584,7 +660,12 @@
                          SpvParserTest_GlslStd450_Inting_Inting,
                          ::testing::Values(GlslStd450Case{"SAbs", "abs"},
                                            GlslStd450Case{"FindILsb", "firstTrailingBit"},
-                                           GlslStd450Case{"FindSMsb", "firstLeadingBit"}));
+                                           GlslStd450Case{"FindSMsb", "firstLeadingBit"},
+                                           GlslStd450Case{"SSign", "sign"}));
+
+INSTANTIATE_TEST_SUITE_P(Samples,
+                         SpvParserTest_GlslStd450_Inting_Inting_SignednessCoercing,
+                         ::testing::Values(GlslStd450Case{"SSign", "sign"}));
 
 INSTANTIATE_TEST_SUITE_P(Samples,
                          SpvParserTest_GlslStd450_Inting_IntingInting,