spirv-reader: support ldexp

Bug: tint:3
Change-Id: I6a9204b19c5b4d631634b9a585a0081eaead9c1b
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/35046
Auto-Submit: David Neto <dneto@google.com>
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/src/reader/spirv/function.cc b/src/reader/spirv/function.cc
index d35f0d9..956aec6 100644
--- a/src/reader/spirv/function.cc
+++ b/src/reader/spirv/function.cc
@@ -364,6 +364,8 @@
       return "fract";
     case GLSLstd450InverseSqrt:
       return "inverseSqrt";
+    case GLSLstd450Ldexp:
+      return "ldexp";
     case GLSLstd450Length:
       return "length";
     case GLSLstd450Log:
@@ -431,7 +433,6 @@
 
     case GLSLstd450Frexp:
     case GLSLstd450FrexpStruct:
-    case GLSLstd450Ldexp:
 
     case GLSLstd450PackSnorm4x8:
     case GLSLstd450PackUnorm4x8:
diff --git a/src/reader/spirv/function_glsl_std_450_test.cc b/src/reader/spirv/function_glsl_std_450_test.cc
index add0dac..10c16da 100644
--- a/src/reader/spirv/function_glsl_std_450_test.cc
+++ b/src/reader/spirv/function_glsl_std_450_test.cc
@@ -154,6 +154,10 @@
     SpvParserTestBase<::testing::TestWithParam<GlslStd450Case>>;
 using SpvParserTest_GlslStd450_Floating_FloatingFloatingFloating =
     SpvParserTestBase<::testing::TestWithParam<GlslStd450Case>>;
+using SpvParserTest_GlslStd450_Floating_FloatingInting =
+    SpvParserTestBase<::testing::TestWithParam<GlslStd450Case>>;
+using SpvParserTest_GlslStd450_Floating_FloatingUinting =
+    SpvParserTestBase<::testing::TestWithParam<GlslStd450Case>>;
 using SpvParserTest_GlslStd450_Float3_Float3Float3 =
     SpvParserTestBase<::testing::TestWithParam<GlslStd450Case>>;
 
@@ -461,6 +465,128 @@
       << ToString(fe.ast_body());
 }
 
+TEST_P(SpvParserTest_GlslStd450_Floating_FloatingUinting, Scalar) {
+  const auto assembly = Preamble() + R"(
+     %1 = OpExtInst %float %glsl )" +
+                        GetParam().opcode + R"( %f1 %u1
+     OpReturn
+     OpFunctionEnd
+  )";
+  auto p = parser(test::Assemble(assembly));
+  ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
+  FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
+  EXPECT_TRUE(fe.EmitBody()) << p->error();
+  EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(
+  VariableConst{
+    x_1
+    none
+    __f32
+    {
+      Call[not set]{
+        Identifier[not set]{)" + GetParam().wgsl_func +
+                                                 R"(}
+        (
+          Identifier[not set]{f1}
+          Identifier[not set]{u1}
+        )
+      }
+    }
+  })"))
+      << ToString(fe.ast_body());
+}
+
+TEST_P(SpvParserTest_GlslStd450_Floating_FloatingUinting, Vector) {
+  const auto assembly = Preamble() + R"(
+     %1 = OpExtInst %v2float %glsl )" +
+                        GetParam().opcode +
+                        R"( %v2f1 %v2u1
+     OpReturn
+     OpFunctionEnd
+  )";
+  auto p = parser(test::Assemble(assembly));
+  ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
+  FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
+  EXPECT_TRUE(fe.EmitBody()) << p->error();
+  EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(
+  VariableConst{
+    x_1
+    none
+    __vec_2__f32
+    {
+      Call[not set]{
+        Identifier[not set]{)" + GetParam().wgsl_func +
+                                                 R"(}
+        (
+          Identifier[not set]{v2f1}
+          Identifier[not set]{v2u1}
+        )
+      }
+    }
+  })"))
+      << ToString(fe.ast_body());
+}
+
+TEST_P(SpvParserTest_GlslStd450_Floating_FloatingInting, Scalar) {
+  const auto assembly = Preamble() + R"(
+     %1 = OpExtInst %float %glsl )" +
+                        GetParam().opcode + R"( %f1 %i1
+     OpReturn
+     OpFunctionEnd
+  )";
+  auto p = parser(test::Assemble(assembly));
+  ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
+  FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
+  EXPECT_TRUE(fe.EmitBody()) << p->error();
+  EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(
+  VariableConst{
+    x_1
+    none
+    __f32
+    {
+      Call[not set]{
+        Identifier[not set]{)" + GetParam().wgsl_func +
+                                                 R"(}
+        (
+          Identifier[not set]{f1}
+          Identifier[not set]{i1}
+        )
+      }
+    }
+  })"))
+      << ToString(fe.ast_body());
+}
+
+TEST_P(SpvParserTest_GlslStd450_Floating_FloatingInting, Vector) {
+  const auto assembly = Preamble() + R"(
+     %1 = OpExtInst %v2float %glsl )" +
+                        GetParam().opcode +
+                        R"( %v2f1 %v2i1
+     OpReturn
+     OpFunctionEnd
+  )";
+  auto p = parser(test::Assemble(assembly));
+  ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
+  FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
+  EXPECT_TRUE(fe.EmitBody()) << p->error();
+  EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(
+  VariableConst{
+    x_1
+    none
+    __vec_2__f32
+    {
+      Call[not set]{
+        Identifier[not set]{)" + GetParam().wgsl_func +
+                                                 R"(}
+        (
+          Identifier[not set]{v2f1}
+          Identifier[not set]{v2i1}
+        )
+      }
+    }
+  })"))
+      << ToString(fe.ast_body());
+}
+
 TEST_P(SpvParserTest_GlslStd450_Float3_Float3Float3, Samples) {
   const auto assembly = Preamble() + R"(
      %1 = OpExtInst %v3float %glsl )" +
@@ -543,6 +669,14 @@
                          }));
 
 INSTANTIATE_TEST_SUITE_P(Samples,
+                         SpvParserTest_GlslStd450_Floating_FloatingUinting,
+                         ::testing::Values(GlslStd450Case{"Ldexp", "ldexp"}));
+
+INSTANTIATE_TEST_SUITE_P(Samples,
+                         SpvParserTest_GlslStd450_Floating_FloatingInting,
+                         ::testing::Values(GlslStd450Case{"Ldexp", "ldexp"}));
+
+INSTANTIATE_TEST_SUITE_P(Samples,
                          SpvParserTest_GlslStd450_Float3_Float3Float3,
                          ::testing::Values(GlslStd450Case{"Cross", "cross"}));