Add arrayLength() intrinsic that accepts a pointer argument

The old non-pointer argument overload remains, but is now deprecated.

Bug: tint:806
Change-Id: Ic917ccec0f162414ce1b03df49e332ad84d8060f
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/54061
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: David Neto <dneto@google.com>
diff --git a/src/transform/calculate_array_length_test.cc b/src/transform/calculate_array_length_test.cc
index 4821c58..693a1ec 100644
--- a/src/transform/calculate_array_length_test.cc
+++ b/src/transform/calculate_array_length_test.cc
@@ -22,7 +22,8 @@
 
 using CalculateArrayLengthTest = TransformTest;
 
-TEST_F(CalculateArrayLengthTest, Basic) {
+// TODO(crbug.com/tint/806): Remove
+TEST_F(CalculateArrayLengthTest, Basic_DEPRECATED) {
   auto* src = R"(
 [[block]]
 struct SB {
@@ -64,7 +65,8 @@
   EXPECT_EQ(expect, str(got));
 }
 
-TEST_F(CalculateArrayLengthTest, InSameBlock) {
+// TODO(crbug.com/tint/806): Remove
+TEST_F(CalculateArrayLengthTest, InSameBlock_DEPRECATED) {
   auto* src = R"(
 [[block]]
 struct SB {
@@ -110,7 +112,8 @@
   EXPECT_EQ(expect, str(got));
 }
 
-TEST_F(CalculateArrayLengthTest, WithStride) {
+// TODO(crbug.com/tint/806): Remove
+TEST_F(CalculateArrayLengthTest, WithStride_DEPRECATED) {
   auto* src = R"(
 [[block]]
 struct SB {
@@ -154,7 +157,8 @@
   EXPECT_EQ(expect, str(got));
 }
 
-TEST_F(CalculateArrayLengthTest, Nested) {
+// TODO(crbug.com/tint/806): Remove
+TEST_F(CalculateArrayLengthTest, Nested_DEPRECATED) {
   auto* src = R"(
 [[block]]
 struct SB {
@@ -211,6 +215,264 @@
   EXPECT_EQ(expect, str(got));
 }
 
+// TODO(crbug.com/tint/806): Remove
+TEST_F(CalculateArrayLengthTest, MultipleStorageBuffers_DEPRECATED) {
+  auto* src = R"(
+[[block]]
+struct SB1 {
+  x : i32;
+  arr1 : array<i32>;
+};
+
+[[block]]
+struct SB2 {
+  x : i32;
+  arr2 : array<vec4<f32>>;
+};
+
+[[group(0), binding(0)]] var<storage, read> sb1 : SB1;
+
+[[group(0), binding(1)]] var<storage, read> sb2 : SB2;
+
+[[stage(compute)]]
+fn main() {
+  var len1 : u32 = arrayLength(sb1.arr1);
+  var len2 : u32 = arrayLength(sb2.arr2);
+  var x : u32 = (len1 + len2);
+}
+)";
+
+  auto* expect = R"(
+[[block]]
+struct SB1 {
+  x : i32;
+  arr1 : array<i32>;
+};
+
+[[internal(intrinsic_buffer_size)]]
+fn tint_symbol(buffer : SB1, result : ptr<function, u32>)
+
+[[block]]
+struct SB2 {
+  x : i32;
+  arr2 : array<vec4<f32>>;
+};
+
+[[internal(intrinsic_buffer_size)]]
+fn tint_symbol_3(buffer : SB2, result : ptr<function, u32>)
+
+[[group(0), binding(0)]] var<storage, read> sb1 : SB1;
+
+[[group(0), binding(1)]] var<storage, read> sb2 : SB2;
+
+[[stage(compute)]]
+fn main() {
+  var tint_symbol_1 : u32 = 0u;
+  tint_symbol(sb1, &(tint_symbol_1));
+  let tint_symbol_2 : u32 = ((tint_symbol_1 - 4u) / 4u);
+  var tint_symbol_4 : u32 = 0u;
+  tint_symbol_3(sb2, &(tint_symbol_4));
+  let tint_symbol_5 : u32 = ((tint_symbol_4 - 16u) / 16u);
+  var len1 : u32 = tint_symbol_2;
+  var len2 : u32 = tint_symbol_5;
+  var x : u32 = (len1 + len2);
+}
+)";
+
+  auto got = Run<CalculateArrayLength>(src);
+
+  EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(CalculateArrayLengthTest, Basic) {
+  auto* src = R"(
+[[block]]
+struct SB {
+  x : i32;
+  arr : array<i32>;
+};
+
+[[group(0), binding(0)]] var<storage, read> sb : SB;
+
+[[stage(compute)]]
+fn main() {
+  var len : u32 = arrayLength(&sb.arr);
+}
+)";
+
+  auto* expect = R"(
+[[block]]
+struct SB {
+  x : i32;
+  arr : array<i32>;
+};
+
+[[internal(intrinsic_buffer_size)]]
+fn tint_symbol(buffer : SB, result : ptr<function, u32>)
+
+[[group(0), binding(0)]] var<storage, read> sb : SB;
+
+[[stage(compute)]]
+fn main() {
+  var tint_symbol_1 : u32 = 0u;
+  tint_symbol(sb, &(tint_symbol_1));
+  let tint_symbol_2 : u32 = ((tint_symbol_1 - 4u) / 4u);
+  var len : u32 = tint_symbol_2;
+}
+)";
+
+  auto got = Run<CalculateArrayLength>(src);
+
+  EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(CalculateArrayLengthTest, InSameBlock) {
+  auto* src = R"(
+[[block]]
+struct SB {
+  x : i32;
+  arr : array<i32>;
+};
+
+[[group(0), binding(0)]] var<storage, read> sb : SB;
+
+[[stage(compute)]]
+fn main() {
+  var a : u32 = arrayLength(&sb.arr);
+  var b : u32 = arrayLength(&sb.arr);
+  var c : u32 = arrayLength(&sb.arr);
+}
+)";
+
+  auto* expect = R"(
+[[block]]
+struct SB {
+  x : i32;
+  arr : array<i32>;
+};
+
+[[internal(intrinsic_buffer_size)]]
+fn tint_symbol(buffer : SB, result : ptr<function, u32>)
+
+[[group(0), binding(0)]] var<storage, read> sb : SB;
+
+[[stage(compute)]]
+fn main() {
+  var tint_symbol_1 : u32 = 0u;
+  tint_symbol(sb, &(tint_symbol_1));
+  let tint_symbol_2 : u32 = ((tint_symbol_1 - 4u) / 4u);
+  var a : u32 = tint_symbol_2;
+  var b : u32 = tint_symbol_2;
+  var c : u32 = tint_symbol_2;
+}
+)";
+
+  auto got = Run<CalculateArrayLength>(src);
+
+  EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(CalculateArrayLengthTest, WithStride) {
+  auto* src = R"(
+[[block]]
+struct SB {
+  x : i32;
+  y : f32;
+  arr : [[stride(64)]] array<i32>;
+};
+
+[[group(0), binding(0)]] var<storage, read> sb : SB;
+
+[[stage(compute)]]
+fn main() {
+  var len : u32 = arrayLength(&sb.arr);
+}
+)";
+
+  auto* expect = R"(
+[[block]]
+struct SB {
+  x : i32;
+  y : f32;
+  arr : [[stride(64)]] array<i32>;
+};
+
+[[internal(intrinsic_buffer_size)]]
+fn tint_symbol(buffer : SB, result : ptr<function, u32>)
+
+[[group(0), binding(0)]] var<storage, read> sb : SB;
+
+[[stage(compute)]]
+fn main() {
+  var tint_symbol_1 : u32 = 0u;
+  tint_symbol(sb, &(tint_symbol_1));
+  let tint_symbol_2 : u32 = ((tint_symbol_1 - 8u) / 64u);
+  var len : u32 = tint_symbol_2;
+}
+)";
+
+  auto got = Run<CalculateArrayLength>(src);
+
+  EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(CalculateArrayLengthTest, Nested) {
+  auto* src = R"(
+[[block]]
+struct SB {
+  x : i32;
+  arr : array<i32>;
+};
+
+[[group(0), binding(0)]] var<storage, read> sb : SB;
+
+[[stage(compute)]]
+fn main() {
+  if (true) {
+    var len : u32 = arrayLength(&sb.arr);
+  } else {
+    if (true) {
+      var len : u32 = arrayLength(&sb.arr);
+    }
+  }
+}
+)";
+
+  auto* expect = R"(
+[[block]]
+struct SB {
+  x : i32;
+  arr : array<i32>;
+};
+
+[[internal(intrinsic_buffer_size)]]
+fn tint_symbol(buffer : SB, result : ptr<function, u32>)
+
+[[group(0), binding(0)]] var<storage, read> sb : SB;
+
+[[stage(compute)]]
+fn main() {
+  if (true) {
+    var tint_symbol_1 : u32 = 0u;
+    tint_symbol(sb, &(tint_symbol_1));
+    let tint_symbol_2 : u32 = ((tint_symbol_1 - 4u) / 4u);
+    var len : u32 = tint_symbol_2;
+  } else {
+    if (true) {
+      var tint_symbol_3 : u32 = 0u;
+      tint_symbol(sb, &(tint_symbol_3));
+      let tint_symbol_4 : u32 = ((tint_symbol_3 - 4u) / 4u);
+      var len : u32 = tint_symbol_4;
+    }
+  }
+}
+)";
+
+  auto got = Run<CalculateArrayLength>(src);
+
+  EXPECT_EQ(expect, str(got));
+}
+
 TEST_F(CalculateArrayLengthTest, MultipleStorageBuffers) {
   auto* src = R"(
 [[block]]
@@ -231,8 +493,8 @@
 
 [[stage(compute)]]
 fn main() {
-  var len1 : u32 = arrayLength(sb1.arr1);
-  var len2 : u32 = arrayLength(sb2.arr2);
+  var len1 : u32 = arrayLength(&(sb1.arr1));
+  var len2 : u32 = arrayLength(&(sb2.arr2));
   var x : u32 = (len1 + len2);
 }
 )";