[msl-writer] Fix output of array-of-array.

This CL fixes the output of multi-dimentional arrays in the MSL backend.

Bug: tint:7, tint:100
Change-Id: I8fe925145973555f77673e9db97f150077e2471f
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/24560
Reviewed-by: David Neto <dneto@google.com>
diff --git a/simple.spv b/simple.spv
new file mode 100644
index 0000000..d88a341
--- /dev/null
+++ b/simple.spv
Binary files differ
diff --git a/src/writer/msl/generator_impl.cc b/src/writer/msl/generator_impl.cc
index 2468a3b..2759bba 100644
--- a/src/writer/msl/generator_impl.cc
+++ b/src/writer/msl/generator_impl.cc
@@ -713,20 +713,25 @@
   } else if (type->IsArray()) {
     auto* ary = type->AsArray();
 
-    if (!EmitType(ary->type(), "")) {
+    ast::type::Type* base_type = ary;
+    std::vector<uint32_t> sizes;
+    while (base_type->IsArray()) {
+      if (base_type->AsArray()->IsRuntimeArray()) {
+        sizes.push_back(1);
+      } else {
+        sizes.push_back(base_type->AsArray()->size());
+      }
+      base_type = base_type->AsArray()->type();
+    }
+    if (!EmitType(base_type, "")) {
       return false;
     }
     if (!name.empty()) {
       out_ << " " << namer_.NameFor(name);
     }
-    out_ << "[";
-    if (ary->IsRuntimeArray()) {
-      out_ << "1";
-    } else {
-      out_ << std::to_string(ary->size());
+    for (uint32_t size : sizes) {
+      out_ << "[" << size << "]";
     }
-
-    out_ << "]";
   } else if (type->IsBool()) {
     out_ << "bool";
   } else if (type->IsF32()) {
diff --git a/src/writer/msl/generator_impl_type_test.cc b/src/writer/msl/generator_impl_type_test.cc
index 2b3eba5..fe90580 100644
--- a/src/writer/msl/generator_impl_type_test.cc
+++ b/src/writer/msl/generator_impl_type_test.cc
@@ -64,6 +64,39 @@
   EXPECT_EQ(g.result(), "bool ary[4]");
 }
 
+TEST_F(MslGeneratorImplTest, EmitType_ArrayOfArray) {
+  ast::type::BoolType b;
+  ast::type::ArrayType a(&b, 4);
+  ast::type::ArrayType c(&a, 5);
+
+  GeneratorImpl g;
+  ASSERT_TRUE(g.EmitType(&c, "ary")) << g.error();
+  EXPECT_EQ(g.result(), "bool ary[5][4]");
+}
+
+// TODO(dsinclair): Is this possible? What order should it output in?
+TEST_F(MslGeneratorImplTest, DISABLED_EmitType_ArrayOfArrayOfRuntimeArray) {
+  ast::type::BoolType b;
+  ast::type::ArrayType a(&b, 4);
+  ast::type::ArrayType c(&a, 5);
+  ast::type::ArrayType d(&c);
+
+  GeneratorImpl g;
+  ASSERT_TRUE(g.EmitType(&c, "ary")) << g.error();
+  EXPECT_EQ(g.result(), "bool ary[5][4][1]");
+}
+
+TEST_F(MslGeneratorImplTest, EmitType_ArrayOfArrayOfArray) {
+  ast::type::BoolType b;
+  ast::type::ArrayType a(&b, 4);
+  ast::type::ArrayType c(&a, 5);
+  ast::type::ArrayType d(&c, 6);
+
+  GeneratorImpl g;
+  ASSERT_TRUE(g.EmitType(&d, "ary")) << g.error();
+  EXPECT_EQ(g.result(), "bool ary[6][5][4]");
+}
+
 TEST_F(MslGeneratorImplTest, EmitType_Array_NameCollision) {
   ast::type::BoolType b;
   ast::type::ArrayType a(&b, 4);