// Copyright 2021 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "src/transform/simplify_pointers.h"

#include "src/transform/test_helper.h"
#include "src/transform/unshadow.h"

namespace tint {
namespace transform {
namespace {

using SimplifyPointersTest = TransformTest;

TEST_F(SimplifyPointersTest, EmptyModule) {
  auto* src = "";
  auto* expect = "";

  auto got = Run<Unshadow, SimplifyPointers>(src);

  EXPECT_EQ(expect, str(got));
}

TEST_F(SimplifyPointersTest, FoldPointer) {
  auto* src = R"(
fn f() {
  var v : i32;
  let p : ptr<function, i32> = &v;
  let x : i32 = *p;
}
)";

  auto* expect = R"(
fn f() {
  var v : i32;
  let x : i32 = v;
}
)";

  auto got = Run<Unshadow, SimplifyPointers>(src);

  EXPECT_EQ(expect, str(got));
}

TEST_F(SimplifyPointersTest, AddressOfDeref) {
  auto* src = R"(
fn f() {
  var v : i32;
  let p : ptr<function, i32> = &(v);
  let x : ptr<function, i32> = &(*(p));
  let y : ptr<function, i32> = &(*(&(*(p))));
  let z : ptr<function, i32> = &(*(&(*(&(*(&(*(p))))))));
  var a = *x;
  var b = *y;
  var c = *z;
}
)";

  auto* expect = R"(
fn f() {
  var v : i32;
  var a = v;
  var b = v;
  var c = v;
}
)";

  auto got = Run<Unshadow, SimplifyPointers>(src);

  EXPECT_EQ(expect, str(got));
}

TEST_F(SimplifyPointersTest, DerefAddressOf) {
  auto* src = R"(
fn f() {
  var v : i32;
  let x : i32 = *(&(v));
  let y : i32 = *(&(*(&(v))));
  let z : i32 = *(&(*(&(*(&(*(&(v))))))));
}
)";

  auto* expect = R"(
fn f() {
  var v : i32;
  let x : i32 = v;
  let y : i32 = v;
  let z : i32 = v;
}
)";

  auto got = Run<Unshadow, SimplifyPointers>(src);

  EXPECT_EQ(expect, str(got));
}

TEST_F(SimplifyPointersTest, ComplexChain) {
  auto* src = R"(
fn f() {
  var a : array<mat4x4<f32>, 4>;
  let ap : ptr<function, array<mat4x4<f32>, 4>> = &a;
  let mp : ptr<function, mat4x4<f32>> = &(*ap)[3];
  let vp : ptr<function, vec4<f32>> = &(*mp)[2];
  let v : vec4<f32> = *vp;
}
)";

  auto* expect = R"(
fn f() {
  var a : array<mat4x4<f32>, 4>;
  let v : vec4<f32> = a[3][2];
}
)";

  auto got = Run<Unshadow, SimplifyPointers>(src);

  EXPECT_EQ(expect, str(got));
}

TEST_F(SimplifyPointersTest, SavedVars) {
  auto* src = R"(
struct S {
  i : i32;
};

fn arr() {
  var a : array<S, 2>;
  var i : i32 = 0;
  var j : i32 = 0;
  let p : ptr<function, i32> = &a[i + j].i;
  i = 2;
  *p = 4;
}

fn matrix() {
  var m : mat3x3<f32>;
  var i : i32 = 0;
  var j : i32 = 0;
  let p : ptr<function, vec3<f32>> = &m[i + j];
  i = 2;
  *p = vec3<f32>(4.0, 5.0, 6.0);
}
)";

  auto* expect = R"(
struct S {
  i : i32;
}

fn arr() {
  var a : array<S, 2>;
  var i : i32 = 0;
  var j : i32 = 0;
  let p_save = (i + j);
  i = 2;
  a[p_save].i = 4;
}

fn matrix() {
  var m : mat3x3<f32>;
  var i : i32 = 0;
  var j : i32 = 0;
  let p_save_1 = (i + j);
  i = 2;
  m[p_save_1] = vec3<f32>(4.0, 5.0, 6.0);
}
)";

  auto got = Run<Unshadow, SimplifyPointers>(src);

  EXPECT_EQ(expect, str(got));
}

TEST_F(SimplifyPointersTest, DontSaveLiterals) {
  auto* src = R"(
fn f() {
  var arr : array<i32, 2>;
  let p1 : ptr<function, i32> = &arr[1];
  *p1 = 4;
}
)";

  auto* expect = R"(
fn f() {
  var arr : array<i32, 2>;
  arr[1] = 4;
}
)";

  auto got = Run<Unshadow, SimplifyPointers>(src);

  EXPECT_EQ(expect, str(got));
}

TEST_F(SimplifyPointersTest, SavedVarsChain) {
  auto* src = R"(
fn f() {
  var arr : array<array<i32, 2>, 2>;
  let i : i32 = 0;
  let j : i32 = 1;
  let p : ptr<function, array<i32, 2>> = &arr[i];
  let q : ptr<function, i32> = &(*p)[j];
  *q = 12;
}
)";

  auto* expect = R"(
fn f() {
  var arr : array<array<i32, 2>, 2>;
  let i : i32 = 0;
  let j : i32 = 1;
  let p_save = i;
  let q_save = j;
  arr[p_save][q_save] = 12;
}
)";

  auto got = Run<Unshadow, SimplifyPointers>(src);

  EXPECT_EQ(expect, str(got));
}

TEST_F(SimplifyPointersTest, ForLoopInit) {
  auto* src = R"(
fn foo() -> i32 {
  return 1;
}

@stage(fragment)
fn main() {
  var arr = array<f32, 4>();
  for (let a = &arr[foo()]; ;) {
    let x = *a;
    break;
  }
}
)";

  auto* expect = R"(
fn foo() -> i32 {
  return 1;
}

@stage(fragment)
fn main() {
  var arr = array<f32, 4>();
  let a_save = foo();
  for(; ; ) {
    let x = arr[a_save];
    break;
  }
}
)";

  auto got = Run<Unshadow, SimplifyPointers>(src);

  EXPECT_EQ(expect, str(got));
}

TEST_F(SimplifyPointersTest, MultiSavedVarsInSinglePtrLetExpr) {
  auto* src = R"(
fn x() -> i32 {
  return 1;
}

fn y() -> i32 {
  return 1;
}

fn z() -> i32 {
  return 1;
}

struct Inner {
  a : array<i32, 2>;
};

struct Outer {
  a : array<Inner, 2>;
};

fn f() {
  var arr : array<Outer, 2>;
  let p : ptr<function, i32> = &arr[x()].a[y()].a[z()];
  *p = 1;
  *p = 2;
}
)";

  auto* expect = R"(
fn x() -> i32 {
  return 1;
}

fn y() -> i32 {
  return 1;
}

fn z() -> i32 {
  return 1;
}

struct Inner {
  a : array<i32, 2>;
}

struct Outer {
  a : array<Inner, 2>;
}

fn f() {
  var arr : array<Outer, 2>;
  let p_save = x();
  let p_save_1 = y();
  let p_save_2 = z();
  arr[p_save].a[p_save_1].a[p_save_2] = 1;
  arr[p_save].a[p_save_1].a[p_save_2] = 2;
}
)";

  auto got = Run<Unshadow, SimplifyPointers>(src);

  EXPECT_EQ(expect, str(got));
}

TEST_F(SimplifyPointersTest, ShadowPointer) {
  auto* src = R"(
var<private> a : array<i32, 2>;

@stage(compute) @workgroup_size(1)
fn main() {
  let x = &a;
  var a : i32 = (*x)[0];
  {
    var a : i32 = (*x)[1];
  }
}
)";

  auto* expect = R"(
var<private> a : array<i32, 2>;

@stage(compute) @workgroup_size(1)
fn main() {
  var a_1 : i32 = a[0];
  {
    var a_2 : i32 = a[1];
  }
}
)";

  auto got = Run<Unshadow, SimplifyPointers>(src);

  EXPECT_EQ(expect, str(got));
}

}  // namespace
}  // namespace transform
}  // namespace tint
