spirv-reader: unwrap references for conversions

Bug: tint:804
Change-Id: I39a4d20de17a5c2ae23e9425d85559b7bb70fd22
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/52845
Auto-Submit: David Neto <dneto@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: James Price <jrprice@google.com>
Reviewed-by: James Price <jrprice@google.com>
This commit is contained in:
David Neto 2021-06-01 19:46:31 +00:00 committed by Tint LUCI CQ
parent b29a59de6e
commit 5ed3f68eb5
4 changed files with 99 additions and 26 deletions

View File

@ -4475,6 +4475,7 @@ TypedExpression FunctionEmitter::MakeNumericConversion(
if (!arg_expr) { if (!arg_expr) {
return {}; return {};
} }
arg_expr.type = arg_expr.type->UnwrapRef();
const Type* expr_type = nullptr; const Type* expr_type = nullptr;
if ((opcode == SpvOpConvertSToF) || (opcode == SpvOpConvertUToF)) { if ((opcode == SpvOpConvertSToF) || (opcode == SpvOpConvertUToF)) {
@ -4482,21 +4483,24 @@ TypedExpression FunctionEmitter::MakeNumericConversion(
expr_type = requested_type; expr_type = requested_type;
} else { } else {
Fail() << "operand for conversion to floating point must be integral " Fail() << "operand for conversion to floating point must be integral "
"scalar or vector"; "scalar or vector: "
<< inst.PrettyPrint();
} }
} else if (inst.opcode() == SpvOpConvertFToU) { } else if (inst.opcode() == SpvOpConvertFToU) {
if (arg_expr.type->IsFloatScalarOrVector()) { if (arg_expr.type->IsFloatScalarOrVector()) {
expr_type = parser_impl_.GetUnsignedIntMatchingShape(arg_expr.type); expr_type = parser_impl_.GetUnsignedIntMatchingShape(arg_expr.type);
} else { } else {
Fail() << "operand for conversion to unsigned integer must be floating " Fail() << "operand for conversion to unsigned integer must be floating "
"point scalar or vector"; "point scalar or vector: "
<< inst.PrettyPrint();
} }
} else if (inst.opcode() == SpvOpConvertFToS) { } else if (inst.opcode() == SpvOpConvertFToS) {
if (arg_expr.type->IsFloatScalarOrVector()) { if (arg_expr.type->IsFloatScalarOrVector()) {
expr_type = parser_impl_.GetSignedIntMatchingShape(arg_expr.type); expr_type = parser_impl_.GetSignedIntMatchingShape(arg_expr.type);
} else { } else {
Fail() << "operand for conversion to signed integer must be floating " Fail() << "operand for conversion to signed integer must be floating "
"point scalar or vector"; "point scalar or vector: "
<< inst.PrettyPrint();
} }
} }
if (expr_type == nullptr) { if (expr_type == nullptr) {
@ -4506,16 +4510,17 @@ TypedExpression FunctionEmitter::MakeNumericConversion(
ast::ExpressionList params; ast::ExpressionList params;
params.push_back(arg_expr.expr); params.push_back(arg_expr.expr);
TypedExpression result{ TypedExpression result{expr_type,
expr_type, create<ast::TypeConstructorExpression>( create<ast::TypeConstructorExpression>(
Source{}, expr_type->Build(builder_), std::move(params))}; GetSourceForInst(inst), expr_type->Build(builder_),
std::move(params))};
if (requested_type == expr_type) { if (requested_type == expr_type) {
return result; return result;
} }
return {requested_type, return {requested_type, create<ast::BitcastExpression>(
create<ast::BitcastExpression>( GetSourceForInst(inst),
Source{}, requested_type->Build(builder_), result.expr)}; requested_type->Build(builder_), result.expr)};
} }
bool FunctionEmitter::EmitFunctionCall(const spvtools::opt::Instruction& inst) { bool FunctionEmitter::EmitFunctionCall(const spvtools::opt::Instruction& inst) {

View File

@ -343,7 +343,8 @@ TEST_F(SpvUnaryConversionTest, ConvertUToF_Scalar_BadArgType) {
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()); ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
auto fe = p->function_emitter(100); auto fe = p->function_emitter(100);
EXPECT_FALSE(fe.EmitBody()); EXPECT_FALSE(fe.EmitBody());
EXPECT_THAT(p->error(), Eq("operand for conversion to floating point must be " EXPECT_THAT(p->error(),
HasSubstr("operand for conversion to floating point must be "
"integral scalar or vector")); "integral scalar or vector"));
} }
@ -359,8 +360,9 @@ TEST_F(SpvUnaryConversionTest, ConvertUToF_Vector_BadArgType) {
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()); ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
auto fe = p->function_emitter(100); auto fe = p->function_emitter(100);
EXPECT_FALSE(fe.EmitBody()); EXPECT_FALSE(fe.EmitBody());
EXPECT_THAT(p->error(), EXPECT_THAT(
Eq("operand for conversion to floating point must be integral " p->error(),
HasSubstr("operand for conversion to floating point must be integral "
"scalar or vector")); "scalar or vector"));
} }
@ -484,8 +486,9 @@ TEST_F(SpvUnaryConversionTest, ConvertFToS_Scalar_BadArgType) {
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()); ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
auto fe = p->function_emitter(100); auto fe = p->function_emitter(100);
EXPECT_FALSE(fe.EmitBody()); EXPECT_FALSE(fe.EmitBody());
EXPECT_THAT(p->error(), EXPECT_THAT(
Eq("operand for conversion to signed integer must be floating " p->error(),
HasSubstr("operand for conversion to signed integer must be floating "
"point scalar or vector")); "point scalar or vector"));
} }
@ -501,8 +504,9 @@ TEST_F(SpvUnaryConversionTest, ConvertFToS_Vector_BadArgType) {
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()); ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
auto fe = p->function_emitter(100); auto fe = p->function_emitter(100);
EXPECT_FALSE(fe.EmitBody()); EXPECT_FALSE(fe.EmitBody());
EXPECT_THAT(p->error(), EXPECT_THAT(
Eq("operand for conversion to signed integer must be floating " p->error(),
HasSubstr("operand for conversion to signed integer must be floating "
"point scalar or vector")); "point scalar or vector"));
} }
@ -626,8 +630,9 @@ TEST_F(SpvUnaryConversionTest, ConvertFToU_Scalar_BadArgType) {
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()); ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
auto fe = p->function_emitter(100); auto fe = p->function_emitter(100);
EXPECT_FALSE(fe.EmitBody()); EXPECT_FALSE(fe.EmitBody());
EXPECT_THAT(p->error(), EXPECT_THAT(
Eq("operand for conversion to unsigned integer must be floating " p->error(),
HasSubstr("operand for conversion to unsigned integer must be floating "
"point scalar or vector")); "point scalar or vector"));
} }
@ -643,8 +648,9 @@ TEST_F(SpvUnaryConversionTest, ConvertFToU_Vector_BadArgType) {
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()); ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
auto fe = p->function_emitter(100); auto fe = p->function_emitter(100);
EXPECT_FALSE(fe.EmitBody()); EXPECT_FALSE(fe.EmitBody());
EXPECT_THAT(p->error(), EXPECT_THAT(
Eq("operand for conversion to unsigned integer must be floating " p->error(),
HasSubstr("operand for conversion to unsigned integer must be floating "
"point scalar or vector")); "point scalar or vector"));
} }
@ -732,6 +738,56 @@ TEST_F(SpvUnaryConversionTest, ConvertFToU_Vector_ToUnsigned) {
})")); })"));
} }
TEST_F(SpvUnaryConversionTest, ConvertFToU_HoistedValue) {
// From crbug.com/tint/804
const auto assembly = Preamble() + R"(
%100 = OpFunction %void None %voidfn
%10 = OpLabel
OpBranch %30
%30 = OpLabel
OpLoopMerge %90 %80 None
OpBranchConditional %true %90 %40
%40 = OpLabel
OpSelectionMerge %50 None
OpBranchConditional %true %45 %50
%45 = OpLabel
; This value is hoisted
%600 = OpCopyObject %float %float_50
OpBranch %50
%50 = OpLabel
OpBranch %90
%80 = OpLabel ; unreachable continue target
%82 = OpConvertFToU %uint %600
OpBranch %30 ; backedge
%90 = OpLabel
OpReturn
OpFunctionEnd
)";
auto p = parser(test::Assemble(assembly));
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
auto fe = p->function_emitter(100);
EXPECT_TRUE(fe.EmitBody()) << p->error();
EXPECT_THAT(ToString(p->builder(), fe.ast_body()), HasSubstr(R"(VariableConst{
x_82
none
__u32
{
TypeConstructor[not set]{
__u32
Identifier[not set]{x_600}
}
}
})"));
}
// TODO(dneto): OpSConvert // only if multiple widths // TODO(dneto): OpSConvert // only if multiple widths
// TODO(dneto): OpUConvert // only if multiple widths // TODO(dneto): OpUConvert // only if multiple widths
// TODO(dneto): OpFConvert // only if multiple widths // TODO(dneto): OpFConvert // only if multiple widths

View File

@ -336,6 +336,14 @@ const Type* Type::UnwrapPtr() const {
return type; return type;
} }
const Type* Type::UnwrapRef() const {
const Type* type = this;
while (auto* ptr = type->As<Reference>()) {
type = ptr->type;
}
return type;
}
const Type* Type::UnwrapAlias() const { const Type* Type::UnwrapAlias() const {
const Type* type = this; const Type* type = this;
while (auto* alias = type->As<Alias>()) { while (auto* alias = type->As<Alias>()) {

View File

@ -49,6 +49,10 @@ class Type : public Castable<Type> {
/// @returns the inner most store type if this is a pointer, `this` otherwise /// @returns the inner most store type if this is a pointer, `this` otherwise
const Type* UnwrapPtr() const; const Type* UnwrapPtr() const;
/// @returns the inner most store type if this is a reference, `this`
/// otherwise
const Type* UnwrapRef() const;
/// @returns the inner most aliased type if this is an alias, `this` otherwise /// @returns the inner most aliased type if this is an alias, `this` otherwise
const Type* UnwrapAlias() const; const Type* UnwrapAlias() const;