spirv-reader: fix emission of arrayLength

Pass a pointer argument instead of a reference argument.
Also handle the case where the argument is the result of
an OpCopyObject, which will generate a let-declaration of pointer
type.

Fixed: tint:1042
Change-Id: I25b1b7b95ade1b79130e51691194f32b3240e013
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/59451
Auto-Submit: David Neto <dneto@google.com>
Commit-Queue: James Price <jrprice@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: James Price <jrprice@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
This commit is contained in:
David Neto 2021-07-26 19:29:38 +00:00 committed by Tint LUCI CQ
parent 1fd3d95dd5
commit 60d1eb6688
2 changed files with 115 additions and 12 deletions

View File

@ -5752,23 +5752,21 @@ TypedExpression FunctionEmitter::MakeArrayLength(
return {}; return {};
} }
auto* member_ident = create<ast::IdentifierExpression>(
Source{}, builder_.Symbols().Register(field_name));
auto member_expr = MakeExpression(struct_ptr_id); auto member_expr = MakeExpression(struct_ptr_id);
if (!member_expr) { if (!member_expr) {
return {}; return {};
} }
if (member_expr.type->Is<Pointer>()) {
member_expr = Dereference(member_expr);
}
auto* member_ident = create<ast::IdentifierExpression>(
Source{}, builder_.Symbols().Register(field_name));
auto* member_access = create<ast::MemberAccessorExpression>( auto* member_access = create<ast::MemberAccessorExpression>(
Source{}, member_expr.expr, member_ident); Source{}, member_expr.expr, member_ident);
// Generate the intrinsic function call. // Generate the intrinsic function call.
std::string call_ident_str = "arrayLength";
auto* call_ident = create<ast::IdentifierExpression>(
Source{}, builder_.Symbols().Register(call_ident_str));
ast::ExpressionList params{member_access};
auto* call_expr = auto* call_expr =
create<ast::CallExpression>(Source{}, call_ident, std::move(params)); builder_.Call(Source{}, "arrayLength", builder_.AddressOf(member_access));
return {parser_impl_.ConvertType(inst.type_id()), call_expr}; return {parser_impl_.ConvertType(inst.type_id()), call_expr};
} }

View File

@ -1326,7 +1326,7 @@ std::string RuntimeArrayPreamble() {
)"; )";
} }
TEST_F(SpvParserMemoryTest, ArrayLength) { TEST_F(SpvParserMemoryTest, ArrayLength_FromVar) {
const auto assembly = RuntimeArrayPreamble() + R"( const auto assembly = RuntimeArrayPreamble() + R"(
%100 = OpFunction %void None %voidfn %100 = OpFunction %void None %voidfn
@ -1351,9 +1351,114 @@ TEST_F(SpvParserMemoryTest, ArrayLength) {
Call[not set]{ Call[not set]{
Identifier[not set]{arrayLength} Identifier[not set]{arrayLength}
( (
MemberAccessor[not set]{ UnaryOp[not set]{
Identifier[not set]{myvar} address-of
Identifier[not set]{rtarr} MemberAccessor[not set]{
Identifier[not set]{myvar}
Identifier[not set]{rtarr}
}
}
)
}
}
}
}
)")) << body_str;
}
TEST_F(SpvParserMemoryTest, ArrayLength_FromCopyObject) {
const auto assembly = RuntimeArrayPreamble() + R"(
%100 = OpFunction %void None %voidfn
%entry = OpLabel
%2 = OpCopyObject %ptr_struct %myvar
%1 = OpArrayLength %uint %2 1
OpReturn
OpFunctionEnd
)";
auto p = parser(test::Assemble(assembly));
ASSERT_TRUE(p->BuildAndParseInternalModule()) << assembly << p->error();
auto fe = p->function_emitter(100);
EXPECT_TRUE(fe.EmitBody()) << p->error();
const auto body_str = ToString(p->builder(), fe.ast_body());
EXPECT_THAT(body_str, HasSubstr(R"(VariableDeclStatement{
VariableConst{
x_2
none
undefined
__ptr_storage__type_name_S
{
UnaryOp[not set]{
address-of
Identifier[not set]{myvar}
}
}
}
}
VariableDeclStatement{
VariableConst{
x_1
none
undefined
__u32
{
Call[not set]{
Identifier[not set]{arrayLength}
(
UnaryOp[not set]{
address-of
MemberAccessor[not set]{
UnaryOp[not set]{
indirection
Identifier[not set]{x_2}
}
Identifier[not set]{rtarr}
}
}
)
}
}
}
}
)")) << body_str;
p->SkipDumpingPending(
"crbug.com/tint/1041 track access mode in spirv-reader parser type");
}
TEST_F(SpvParserMemoryTest, ArrayLength_FromAccessChain) {
const auto assembly = RuntimeArrayPreamble() + R"(
%100 = OpFunction %void None %voidfn
%entry = OpLabel
%2 = OpAccessChain %ptr_struct %myvar ; no indices
%1 = OpArrayLength %uint %2 1
OpReturn
OpFunctionEnd
)";
auto p = parser(test::Assemble(assembly));
ASSERT_TRUE(p->BuildAndParseInternalModule()) << assembly << p->error();
auto fe = p->function_emitter(100);
EXPECT_TRUE(fe.EmitBody()) << p->error();
const auto body_str = ToString(p->builder(), fe.ast_body());
EXPECT_THAT(body_str, HasSubstr(R"(VariableDeclStatement{
VariableConst{
x_1
none
undefined
__u32
{
Call[not set]{
Identifier[not set]{arrayLength}
(
UnaryOp[not set]{
address-of
MemberAccessor[not set]{
Identifier[not set]{myvar}
Identifier[not set]{rtarr}
}
} }
) )
} }