[spirv-reader] Add ConvertSToF, ConvertUToF
Bug: tint:3
Change-Id: I28bcc109a207ef6f5225b9ea707bff11b1b6fd50
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/23420
Reviewed-by: dan sinclair <dsinclair@google.com>
diff --git a/src/reader/spirv/function.cc b/src/reader/spirv/function.cc
index 117dcc9..932c5ca 100644
--- a/src/reader/spirv/function.cc
+++ b/src/reader/spirv/function.cc
@@ -35,6 +35,7 @@
#include "src/ast/break_statement.h"
#include "src/ast/call_expression.h"
#include "src/ast/case_statement.h"
+#include "src/ast/cast_expression.h"
#include "src/ast/continue_statement.h"
#include "src/ast/else_statement.h"
#include "src/ast/fallthrough_statement.h"
@@ -2533,6 +2534,9 @@
if (opcode == SpvOpVectorShuffle) {
return MakeVectorShuffle(inst);
}
+ if (opcode == SpvOpConvertSToF || opcode == SpvOpConvertUToF) {
+ return MakeNumericConversion(inst);
+ }
// builtin readonly function
// glsl.std.450 readonly function
@@ -2545,8 +2549,6 @@
// OpSatConvertUToS
// OpConvertFToS
// OpConvertFToU
- // OpConvertSToF
- // OpConvertUToF
// OpUConvert // Only needed when multiple widths supported
// OpSConvert // Only needed when multiple widths supported
// OpFConvert // Only needed when multiple widths supported
@@ -2893,6 +2895,15 @@
}
}
+TypedExpression FunctionEmitter::MakeNumericConversion(
+ const spvtools::opt::Instruction& inst) {
+ auto* result_type = parser_impl_.ConvertType(inst.type_id());
+ auto arg_expr = MakeOperand(inst, 0);
+
+ return {result_type, std::make_unique<ast::CastExpression>(
+ result_type, std::move(arg_expr.expr))};
+}
+
} // namespace spirv
} // namespace reader
} // namespace tint
diff --git a/src/reader/spirv/function.h b/src/reader/spirv/function.h
index 3d16aa9..fbab63b 100644
--- a/src/reader/spirv/function.h
+++ b/src/reader/spirv/function.h
@@ -463,6 +463,11 @@
/// @returns an AST expression for the instruction, or nullptr.
TypedExpression MakeVectorShuffle(const spvtools::opt::Instruction& inst);
+ /// Creates an expression for a numeric conversion.
+ /// @param inst a numeric conversion instruction
+ /// @returns an AST expression for the instruction, or nullptr.
+ TypedExpression MakeNumericConversion(const spvtools::opt::Instruction& inst);
+
/// Gets the block info for a block ID, if any exists
/// @param id the SPIR-V ID of the OpLabel instruction starting the block
/// @returns the block info for the given ID, if it exists, or nullptr
diff --git a/src/reader/spirv/function_conversion_test.cc b/src/reader/spirv/function_conversion_test.cc
index 49aa594..92d3c6c 100644
--- a/src/reader/spirv/function_conversion_test.cc
+++ b/src/reader/spirv/function_conversion_test.cc
@@ -119,10 +119,224 @@
<< ToString(fe.ast_body());
}
+TEST_F(SpvUnaryConversionTest, ConvertSToF_Scalar_FromSigned) {
+ const auto assembly = CommonTypes() + R"(
+ %100 = OpFunction %void None %voidfn
+ %entry = OpLabel
+ %30 = OpCopyObject %int %int_30
+ %1 = OpConvertSToF %float %30
+ OpReturn
+ OpFunctionEnd
+ )";
+ auto* p = parser(test::Assemble(assembly));
+ ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
+ FunctionEmitter fe(p, *spirv_function(100));
+ EXPECT_TRUE(fe.EmitBody()) << p->error();
+ EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(Variable{
+ x_1
+ none
+ __f32
+ {
+ Cast<__f32>(
+ Identifier{x_30}
+ )
+ }
+ })"))
+ << ToString(fe.ast_body());
+}
+
+TEST_F(SpvUnaryConversionTest, ConvertSToF_Scalar_FromUnsigned) {
+ const auto assembly = CommonTypes() + R"(
+ %100 = OpFunction %void None %voidfn
+ %entry = OpLabel
+ %30 = OpCopyObject %uint %uint_10
+ %1 = OpConvertSToF %float %30
+ OpReturn
+ OpFunctionEnd
+ )";
+ auto* p = parser(test::Assemble(assembly));
+ ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
+ FunctionEmitter fe(p, *spirv_function(100));
+ EXPECT_TRUE(fe.EmitBody()) << p->error();
+ EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(Variable{
+ x_1
+ none
+ __f32
+ {
+ Cast<__f32>(
+ As<__i32>{
+ Identifier{x_30}
+ }
+ )
+ }
+ })"))
+ << ToString(fe.ast_body());
+}
+
+TEST_F(SpvUnaryConversionTest, ConvertSToF_Vector_FromSigned) {
+ const auto assembly = CommonTypes() + R"(
+ %100 = OpFunction %void None %voidfn
+ %entry = OpLabel
+ %30 = OpCopyObject %v2int %v2int_30_40
+ %1 = OpConvertSToF %v2float %30
+ OpReturn
+ OpFunctionEnd
+ )";
+ auto* p = parser(test::Assemble(assembly));
+ ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
+ FunctionEmitter fe(p, *spirv_function(100));
+ EXPECT_TRUE(fe.EmitBody()) << p->error();
+ EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(Variable{
+ x_1
+ none
+ __vec_2__f32
+ {
+ Cast<__vec_2__f32>(
+ Identifier{x_30}
+ )
+ }
+ })"))
+ << ToString(fe.ast_body());
+}
+
+TEST_F(SpvUnaryConversionTest, ConvertSToF_Vector_FromUnsigned) {
+ const auto assembly = CommonTypes() + R"(
+ %100 = OpFunction %void None %voidfn
+ %entry = OpLabel
+ %30 = OpCopyObject %v2uint %v2uint_10_20
+ %1 = OpConvertSToF %v2float %30
+ OpReturn
+ OpFunctionEnd
+ )";
+ auto* p = parser(test::Assemble(assembly));
+ ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
+ FunctionEmitter fe(p, *spirv_function(100));
+ EXPECT_TRUE(fe.EmitBody()) << p->error();
+ EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(Variable{
+ x_1
+ none
+ __vec_2__f32
+ {
+ Cast<__vec_2__f32>(
+ As<__vec_2__i32>{
+ Identifier{x_30}
+ }
+ )
+ }
+ })"))
+ << ToString(fe.ast_body());
+}
+
+TEST_F(SpvUnaryConversionTest, ConvertUToF_Scalar_FromSigned) {
+ const auto assembly = CommonTypes() + R"(
+ %100 = OpFunction %void None %voidfn
+ %entry = OpLabel
+ %30 = OpCopyObject %int %int_30
+ %1 = OpConvertUToF %float %30
+ OpReturn
+ OpFunctionEnd
+ )";
+ auto* p = parser(test::Assemble(assembly));
+ ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
+ FunctionEmitter fe(p, *spirv_function(100));
+ EXPECT_TRUE(fe.EmitBody()) << p->error();
+ EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(Variable{
+ x_1
+ none
+ __f32
+ {
+ Cast<__f32>(
+ As<__u32>{
+ Identifier{x_30}
+ }
+ )
+ }
+ })"))
+ << ToString(fe.ast_body());
+}
+
+TEST_F(SpvUnaryConversionTest, ConvertUToF_Scalar_FromUnsigned) {
+ const auto assembly = CommonTypes() + R"(
+ %100 = OpFunction %void None %voidfn
+ %entry = OpLabel
+ %30 = OpCopyObject %uint %uint_10
+ %1 = OpConvertUToF %float %30
+ OpReturn
+ OpFunctionEnd
+ )";
+ auto* p = parser(test::Assemble(assembly));
+ ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
+ FunctionEmitter fe(p, *spirv_function(100));
+ EXPECT_TRUE(fe.EmitBody()) << p->error();
+ EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(Variable{
+ x_1
+ none
+ __f32
+ {
+ Cast<__f32>(
+ Identifier{x_30}
+ )
+ }
+ })"))
+ << ToString(fe.ast_body());
+}
+
+TEST_F(SpvUnaryConversionTest, ConvertUToF_Vector_FromSigned) {
+ const auto assembly = CommonTypes() + R"(
+ %100 = OpFunction %void None %voidfn
+ %entry = OpLabel
+ %30 = OpCopyObject %v2int %v2int_30_40
+ %1 = OpConvertUToF %v2float %30
+ OpReturn
+ OpFunctionEnd
+ )";
+ auto* p = parser(test::Assemble(assembly));
+ ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
+ FunctionEmitter fe(p, *spirv_function(100));
+ EXPECT_TRUE(fe.EmitBody()) << p->error();
+ EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(Variable{
+ x_1
+ none
+ __vec_2__f32
+ {
+ Cast<__vec_2__f32>(
+ As<__vec_2__u32>{
+ Identifier{x_30}
+ }
+ )
+ }
+ })"))
+ << ToString(fe.ast_body());
+}
+
+TEST_F(SpvUnaryConversionTest, ConvertUToF_Vector_FromUnsigned) {
+ const auto assembly = CommonTypes() + R"(
+ %100 = OpFunction %void None %voidfn
+ %entry = OpLabel
+ %30 = OpCopyObject %v2uint %v2uint_10_20
+ %1 = OpConvertUToF %v2float %30
+ OpReturn
+ OpFunctionEnd
+ )";
+ auto* p = parser(test::Assemble(assembly));
+ ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
+ FunctionEmitter fe(p, *spirv_function(100));
+ EXPECT_TRUE(fe.EmitBody()) << p->error();
+ EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(Variable{
+ x_1
+ none
+ __vec_2__f32
+ {
+ Cast<__vec_2__f32>(
+ Identifier{x_30}
+ )
+ }
+ })"))
+ << ToString(fe.ast_body());
+}
+
// TODO(dneto): OpConvertFToU
// TODO(dneto): OpConvertFToS
-// TODO(dneto): OpConvertUToF
-// TODO(dneto): OpConvertSToF
// TODO(dneto): OpSConvert // only if multiple widths
// TODO(dneto): OpUConvert // only if multiple widths
// TODO(dneto): OpFConvert // only if multiple widths
diff --git a/src/reader/spirv/parser_impl.cc b/src/reader/spirv/parser_impl.cc
index c90a620c..54dcff5 100644
--- a/src/reader/spirv/parser_impl.cc
+++ b/src/reader/spirv/parser_impl.cc
@@ -133,6 +133,7 @@
case SpvOpSLessThanEqual:
case SpvOpSGreaterThan:
case SpvOpSGreaterThanEqual:
+ case SpvOpConvertSToF:
return true;
default:
break;
@@ -149,6 +150,7 @@
case SpvOpULessThanEqual:
case SpvOpUGreaterThan:
case SpvOpUGreaterThanEqual:
+ case SpvOpConvertUToF:
return true;
default:
break;