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

View File

@ -343,7 +343,8 @@ TEST_F(SpvUnaryConversionTest, ConvertUToF_Scalar_BadArgType) {
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
auto fe = p->function_emitter(100);
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"));
}
@ -359,8 +360,9 @@ TEST_F(SpvUnaryConversionTest, ConvertUToF_Vector_BadArgType) {
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
auto fe = p->function_emitter(100);
EXPECT_FALSE(fe.EmitBody());
EXPECT_THAT(p->error(),
Eq("operand for conversion to floating point must be integral "
EXPECT_THAT(
p->error(),
HasSubstr("operand for conversion to floating point must be integral "
"scalar or vector"));
}
@ -484,8 +486,9 @@ TEST_F(SpvUnaryConversionTest, ConvertFToS_Scalar_BadArgType) {
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
auto fe = p->function_emitter(100);
EXPECT_FALSE(fe.EmitBody());
EXPECT_THAT(p->error(),
Eq("operand for conversion to signed integer must be floating "
EXPECT_THAT(
p->error(),
HasSubstr("operand for conversion to signed integer must be floating "
"point scalar or vector"));
}
@ -501,8 +504,9 @@ TEST_F(SpvUnaryConversionTest, ConvertFToS_Vector_BadArgType) {
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
auto fe = p->function_emitter(100);
EXPECT_FALSE(fe.EmitBody());
EXPECT_THAT(p->error(),
Eq("operand for conversion to signed integer must be floating "
EXPECT_THAT(
p->error(),
HasSubstr("operand for conversion to signed integer must be floating "
"point scalar or vector"));
}
@ -626,8 +630,9 @@ TEST_F(SpvUnaryConversionTest, ConvertFToU_Scalar_BadArgType) {
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
auto fe = p->function_emitter(100);
EXPECT_FALSE(fe.EmitBody());
EXPECT_THAT(p->error(),
Eq("operand for conversion to unsigned integer must be floating "
EXPECT_THAT(
p->error(),
HasSubstr("operand for conversion to unsigned integer must be floating "
"point scalar or vector"));
}
@ -643,8 +648,9 @@ TEST_F(SpvUnaryConversionTest, ConvertFToU_Vector_BadArgType) {
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
auto fe = p->function_emitter(100);
EXPECT_FALSE(fe.EmitBody());
EXPECT_THAT(p->error(),
Eq("operand for conversion to unsigned integer must be floating "
EXPECT_THAT(
p->error(),
HasSubstr("operand for conversion to unsigned integer must be floating "
"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): OpUConvert // only if multiple widths
// TODO(dneto): OpFConvert // only if multiple widths

View File

@ -336,6 +336,14 @@ const Type* Type::UnwrapPtr() const {
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 = this;
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
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
const Type* UnwrapAlias() const;