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>
diff --git a/src/reader/spirv/function.cc b/src/reader/spirv/function.cc
index 40332d6..f48940b 100644
--- a/src/reader/spirv/function.cc
+++ b/src/reader/spirv/function.cc
@@ -5752,23 +5752,21 @@
return {};
}
- auto* member_ident = create<ast::IdentifierExpression>(
- Source{}, builder_.Symbols().Register(field_name));
auto member_expr = MakeExpression(struct_ptr_id);
if (!member_expr) {
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>(
Source{}, member_expr.expr, member_ident);
// 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 =
- 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};
}
diff --git a/src/reader/spirv/function_memory_test.cc b/src/reader/spirv/function_memory_test.cc
index e1c6dab..e8af52b 100644
--- a/src/reader/spirv/function_memory_test.cc
+++ b/src/reader/spirv/function_memory_test.cc
@@ -1326,7 +1326,7 @@
)";
}
-TEST_F(SpvParserMemoryTest, ArrayLength) {
+TEST_F(SpvParserMemoryTest, ArrayLength_FromVar) {
const auto assembly = RuntimeArrayPreamble() + R"(
%100 = OpFunction %void None %voidfn
@@ -1351,9 +1351,114 @@
Call[not set]{
Identifier[not set]{arrayLength}
(
- MemberAccessor[not set]{
- Identifier[not set]{myvar}
- Identifier[not set]{rtarr}
+ UnaryOp[not set]{
+ address-of
+ 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}
+ }
}
)
}