spirv-reader: dereference the base pointer for access chain, if needed
Bug: tint:737
Change-Id: I36588ee54ea014e55d3dcc9a54e8d3835c1e83bc
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/53540
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>
diff --git a/src/reader/spirv/function.cc b/src/reader/spirv/function.cc
index da4f579..4e7c4fa 100644
--- a/src/reader/spirv/function.cc
+++ b/src/reader/spirv/function.cc
@@ -3837,6 +3837,9 @@
// for the base, and then bury that inside nested indexing expressions.
if (!current_expr) {
current_expr = MakeOperand(inst, 0);
+ if (current_expr.type->Is<Pointer>()) {
+ current_expr = Dereference(current_expr);
+ }
}
const auto constants = constant_mgr_->GetOperandConstants(&inst);
diff --git a/src/reader/spirv/function_memory_test.cc b/src/reader/spirv/function_memory_test.cc
index d564ce4..1eed4e5 100644
--- a/src/reader/spirv/function_memory_test.cc
+++ b/src/reader/spirv/function_memory_test.cc
@@ -820,6 +820,81 @@
"%60: %60 = OpTypePointer Workgroup %55"));
}
+TEST_F(SpvParserMemoryTest, EmitStatement_AccessChain_DereferenceBase) {
+ // The base operand to OpAccessChain may have to be dereferenced first.
+ // crbug.com/tint/737
+ const std::string assembly = Preamble() + R"(
+ %void = OpTypeVoid
+ %voidfn = OpTypeFunction %void
+
+ %uint = OpTypeInt 32 0
+ %v2uint = OpTypeVector %uint 2
+ %elem_ty = OpTypePointer Private %uint
+ %vec_ty = OpTypePointer Private %v2uint
+
+ %ptrfn = OpTypeFunction %void %vec_ty
+
+ %uint_0 = OpConstant %uint 0
+
+ ; The shortest way to make a pointer example is as a function parameter.
+ %200 = OpFunction %void None %ptrfn
+ %1 = OpFunctionParameter %vec_ty
+ %entry = OpLabel
+ %2 = OpAccessChain %elem_ty %1 %uint_0
+ %3 = OpLoad %uint %2
+ OpReturn
+ OpFunctionEnd
+
+ %100 = OpFunction %void None %voidfn
+ %main_entry = OpLabel
+ OpReturn
+ OpFunctionEnd
+ )";
+ auto p = parser(test::Assemble(assembly));
+ std::cout << assembly << std::endl;
+ ASSERT_TRUE(p->BuildAndParseInternalModule());
+ const auto got = p->program().to_str();
+ const std::string expected = R"(Module{
+ Function x_200 -> __void
+ (
+ VariableConst{
+ x_1
+ none
+ undefined
+ __ptr_private__vec_2__u32
+ }
+ )
+ {
+ VariableDeclStatement{
+ VariableConst{
+ x_3
+ none
+ undefined
+ __u32
+ {
+ MemberAccessor[not set]{
+ UnaryOp[not set]{
+ indirection
+ Identifier[not set]{x_1}
+ }
+ Identifier[not set]{x}
+ }
+ }
+ }
+ }
+ Return{}
+ }
+ Function main -> __void
+ StageDecoration{vertex}
+ ()
+ {
+ Return{}
+ }
+}
+)";
+ EXPECT_EQ(got, expected) << got;
+}
+
std::string OldStorageBufferPreamble() {
return Preamble() + R"(
OpName %myvar "myvar"