spirv-reader: support OpVectorExtractDynamic

Use array-access syntax

Fixed: tint:450
Change-Id: Ida90180015cace8cfa94c0116c3e37c3c6d59212
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/39222
Auto-Submit: David Neto <dneto@google.com>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Commit-Queue: David Neto <dneto@google.com>
diff --git a/src/reader/spirv/function.cc b/src/reader/spirv/function.cc
index 44abc7b..d00da55 100644
--- a/src/reader/spirv/function.cc
+++ b/src/reader/spirv/function.cc
@@ -3129,6 +3129,12 @@
     return MakeVectorShuffle(inst);
   }
 
+  if (opcode == SpvOpVectorExtractDynamic) {
+    return {ast_type, create<ast::ArrayAccessorExpression>(
+                          Source{}, MakeOperand(inst, 0).expr,
+                          MakeOperand(inst, 1).expr)};
+  }
+
   if (opcode == SpvOpConvertSToF || opcode == SpvOpConvertUToF ||
       opcode == SpvOpConvertFToS || opcode == SpvOpConvertFToU) {
     return MakeNumericConversion(inst);
@@ -3163,7 +3169,6 @@
   //    OpGenericCastToPtrExplicit // Not in Vulkan
   //
   //    OpArrayLength
-  //    OpVectorExtractDynamic
   //    OpVectorInsertDynamic
   //    OpCompositeInsert
 
diff --git a/src/reader/spirv/function_composite_test.cc b/src/reader/spirv/function_composite_test.cc
index 5907fa4..e607076 100644
--- a/src/reader/spirv/function_composite_test.cc
+++ b/src/reader/spirv/function_composite_test.cc
@@ -44,6 +44,7 @@
   %uint_3 = OpConstant %uint 3
   %uint_4 = OpConstant %uint 4
   %uint_5 = OpConstant %uint 5
+  %int_1 = OpConstant %int 1
   %int_30 = OpConstant %int 30
   %int_40 = OpConstant %int 40
   %float_50 = OpConstant %float 50
@@ -525,7 +526,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_FALSE(fe.EmitBody());
   EXPECT_THAT(p->error(), Eq("CompositeExtract %2 index value 40 is out of "
-                             "bounds for structure %25 having 3 members"));
+                             "bounds for structure %26 having 3 members"));
 }
 
 TEST_F(SpvParserTest_CompositeExtract, Struct_Array_Matrix_Vector) {
@@ -804,6 +805,68 @@
               Eq("invalid vectorshuffle ID %10: index too large: 9"));
 }
 
+using SpvParserTest_VectorExtractDynamic = SpvParserTest;
+
+TEST_F(SpvParserTest_VectorExtractDynamic, SignedIndex) {
+  const auto assembly = Preamble() + R"(
+     %100 = OpFunction %void None %voidfn
+     %entry = OpLabel
+     %1 = OpCopyObject %v2uint %v2uint_3_4
+     %2 = OpCopyObject %int %int_1
+     %10 = OpVectorExtractDynamic %uint %1 %2
+     OpReturn
+     OpFunctionEnd
+)";
+
+  auto p = parser(test::Assemble(assembly));
+  ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
+  FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
+  EXPECT_TRUE(fe.EmitBody()) << p->error();
+  const auto got = ToString(p->builder().Symbols(), fe.ast_body());
+  EXPECT_THAT(got, HasSubstr(R"(VariableConst{
+    x_10
+    none
+    __u32
+    {
+      ArrayAccessor[not set]{
+        Identifier[not set]{x_1}
+        Identifier[not set]{x_2}
+      }
+    }
+  }
+})")) << got;
+}
+
+TEST_F(SpvParserTest_VectorExtractDynamic, UnsignedIndex) {
+  const auto assembly = Preamble() + R"(
+     %100 = OpFunction %void None %voidfn
+     %entry = OpLabel
+     %1 = OpCopyObject %v2uint %v2uint_3_4
+     %2 = OpCopyObject %uint %uint_3
+     %10 = OpVectorExtractDynamic %uint %1 %2
+     OpReturn
+     OpFunctionEnd
+)";
+
+  auto p = parser(test::Assemble(assembly));
+  ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
+  FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
+  EXPECT_TRUE(fe.EmitBody()) << p->error();
+  const auto got = ToString(p->builder().Symbols(), fe.ast_body());
+  EXPECT_THAT(got, HasSubstr(R"(VariableConst{
+    x_10
+    none
+    __u32
+    {
+      ArrayAccessor[not set]{
+        Identifier[not set]{x_1}
+        Identifier[not set]{x_2}
+      }
+    }
+  }
+})")) << got;
+}
+
 }  // namespace
 }  // namespace spirv
 }  // namespace reader