// Copyright 2020 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/robustness.h"

#include <algorithm>
#include <limits>
#include <utility>

#include "src/program_builder.h"
#include "src/sem/block_statement.h"
#include "src/sem/call.h"
#include "src/sem/expression.h"
#include "src/sem/statement.h"

TINT_INSTANTIATE_TYPEINFO(tint::transform::Robustness);

namespace tint {
namespace transform {

/// State holds the current transform state
struct Robustness::State {
  /// The clone context
  CloneContext& ctx;

  /// Applies the transformation state to `ctx`.
  void Transform() {
    ctx.ReplaceAll(
        [&](ast::ArrayAccessorExpression* expr) { return Transform(expr); });
    ctx.ReplaceAll([&](ast::CallExpression* expr) { return Transform(expr); });
  }

  /// Apply bounds clamping to array, vector and matrix indexing
  /// @param expr the array, vector or matrix index expression
  /// @return the clamped replacement expression, or nullptr if `expr` should be
  /// cloned without changes.
  ast::ArrayAccessorExpression* Transform(ast::ArrayAccessorExpression* expr) {
    auto* ret_type = ctx.src->Sem().Get(expr->array())->Type()->UnwrapRef();

    ProgramBuilder& b = *ctx.dst;
    using u32 = ProgramBuilder::u32;

    struct Value {
      ast::Expression* expr = nullptr;  // If null, then is a constant
      union {
        uint32_t u32 = 0;  // use if is_signed == false
        int32_t i32;       // use if is_signed == true
      };
      bool is_signed = false;
    };

    Value size;              // size of the array, vector or matrix
    size.is_signed = false;  // size is always unsigned
    if (auto* vec = ret_type->As<sem::Vector>()) {
      size.u32 = vec->Width();

    } else if (auto* arr = ret_type->As<sem::Array>()) {
      size.u32 = arr->Count();
    } else if (auto* mat = ret_type->As<sem::Matrix>()) {
      // The row accessor would have been an embedded array accessor and already
      // handled, so we just need to do columns here.
      size.u32 = mat->columns();
    } else {
      return nullptr;
    }

    if (size.u32 == 0) {
      if (!ret_type->Is<sem::Array>()) {
        b.Diagnostics().add_error(diag::System::Transform,
                                  "invalid 0 sized non-array", expr->source());
        return nullptr;
      }
      // Runtime sized array
      auto* arr = ctx.Clone(expr->array());
      size.expr = b.Call("arrayLength", b.AddressOf(arr));
    }

    // Calculate the maximum possible index value (size-1u)
    // Size must be positive (non-zero), so we can safely subtract 1 here
    // without underflow.
    Value limit;
    limit.is_signed = false;  // Like size, limit is always unsigned.
    if (size.expr) {
      // Dynamic size
      limit.expr = b.Sub(size.expr, 1u);
    } else {
      // Constant size
      limit.u32 = size.u32 - 1u;
    }

    Value idx;  // index value

    auto* idx_sem = ctx.src->Sem().Get(expr->idx_expr());
    auto* idx_ty = idx_sem->Type()->UnwrapRef();
    if (!idx_ty->IsAnyOf<sem::I32, sem::U32>()) {
      TINT_ICE(Transform, b.Diagnostics())
          << "index must be u32 or i32, got " << idx_sem->Type()->type_name();
      return nullptr;
    }

    if (auto idx_constant = idx_sem->ConstantValue()) {
      // Constant value index
      if (idx_constant.Type()->Is<sem::I32>()) {
        idx.i32 = idx_constant.Elements()[0].i32;
        idx.is_signed = true;
      } else if (idx_constant.Type()->Is<sem::U32>()) {
        idx.u32 = idx_constant.Elements()[0].u32;
        idx.is_signed = false;
      } else {
        b.Diagnostics().add_error(diag::System::Transform,
                                  "unsupported constant value for accessor: " +
                                      idx_constant.Type()->type_name(),
                                  expr->source());
        return nullptr;
      }
    } else {
      // Dynamic value index
      idx.expr = ctx.Clone(expr->idx_expr());
      idx.is_signed = idx_ty->Is<sem::I32>();
    }

    // Clamp the index so that it cannot exceed limit.
    if (idx.expr || limit.expr) {
      // One of, or both of idx and limit are non-constant.

      // If the index is signed, cast it to a u32 (with clamping if constant).
      if (idx.is_signed) {
        if (idx.expr) {
          // We don't use a max(idx, 0) here, as that incurs a runtime
          // performance cost, and if the unsigned value will be clamped by
          // limit, resulting in a value between [0..limit)
          idx.expr = b.Construct<u32>(idx.expr);
          idx.is_signed = false;
        } else {
          idx.u32 = static_cast<uint32_t>(std::max(idx.i32, 0));
          idx.is_signed = false;
        }
      }

      // Convert idx and limit to expressions, so we can emit `min(idx, limit)`.
      if (!idx.expr) {
        idx.expr = b.Expr(idx.u32);
      }
      if (!limit.expr) {
        limit.expr = b.Expr(limit.u32);
      }

      // Perform the clamp with `min(idx, limit)`
      idx.expr = b.Call("min", idx.expr, limit.expr);
    } else {
      // Both idx and max are constant.
      if (idx.is_signed) {
        // The index is signed. Calculate limit as signed.
        int32_t signed_limit = static_cast<int32_t>(
            std::min<uint32_t>(limit.u32, std::numeric_limits<int32_t>::max()));
        idx.i32 = std::max(idx.i32, 0);
        idx.i32 = std::min(idx.i32, signed_limit);
      } else {
        // The index is unsigned.
        idx.u32 = std::min(idx.u32, limit.u32);
      }
    }

    // Convert idx to an expression, so we can emit the new accessor.
    if (!idx.expr) {
      idx.expr = idx.is_signed ? b.Expr(idx.i32) : b.Expr(idx.u32);
    }

    // Clone arguments outside of create() call to have deterministic ordering
    auto src = ctx.Clone(expr->source());
    auto* arr = ctx.Clone(expr->array());
    return b.IndexAccessor(src, arr, idx.expr);
  }

  /// @param type intrinsic type
  /// @returns true if the given intrinsic is a texture function that requires
  /// argument clamping,
  bool TextureIntrinsicNeedsClamping(sem::IntrinsicType type) {
    return type == sem::IntrinsicType::kTextureLoad ||
           type == sem::IntrinsicType::kTextureStore;
  }

  /// Apply bounds clamping to the coordinates, array index and level arguments
  /// of the `textureLoad()` and `textureStore()` intrinsics.
  /// @param expr the intrinsic call expression
  /// @return the clamped replacement call expression, or nullptr if `expr`
  /// should be cloned without changes.
  ast::CallExpression* Transform(ast::CallExpression* expr) {
    auto* call = ctx.src->Sem().Get(expr);
    auto* call_target = call->Target();
    auto* intrinsic = call_target->As<sem::Intrinsic>();
    if (!intrinsic || !TextureIntrinsicNeedsClamping(intrinsic->Type())) {
      return nullptr;  // No transform, just clone.
    }

    ProgramBuilder& b = *ctx.dst;

    // Indices of the mandatory texture and coords parameters, and the optional
    // array and level parameters.
    auto texture_idx =
        sem::IndexOf(intrinsic->Parameters(), sem::ParameterUsage::kTexture);
    auto coords_idx =
        sem::IndexOf(intrinsic->Parameters(), sem::ParameterUsage::kCoords);
    auto array_idx =
        sem::IndexOf(intrinsic->Parameters(), sem::ParameterUsage::kArrayIndex);
    auto level_idx =
        sem::IndexOf(intrinsic->Parameters(), sem::ParameterUsage::kLevel);

    auto* texture_arg = expr->args()[texture_idx];
    auto* coords_arg = expr->args()[coords_idx];
    auto* coords_ty = intrinsic->Parameters()[coords_idx]->Type();

    // If the level is provided, then we need to clamp this. As the level is
    // used by textureDimensions() and the texture[Load|Store]() calls, we need
    // to clamp both usages.
    // TODO(bclayton): We probably want to place this into a let so that the
    // calculation can be reused. This is fiddly to get right.
    std::function<ast::Expression*()> level_arg;
    if (level_idx >= 0) {
      level_arg = [&] {
        auto* arg = expr->args()[level_idx];
        auto* num_levels = b.Call("textureNumLevels", ctx.Clone(texture_arg));
        auto* zero = b.Expr(0);
        auto* max = ctx.dst->Sub(num_levels, 1);
        auto* clamped = b.Call("clamp", ctx.Clone(arg), zero, max);
        return clamped;
      };
    }

    // Clamp the coordinates argument
    {
      auto* texture_dims =
          level_arg
              ? b.Call("textureDimensions", ctx.Clone(texture_arg), level_arg())
              : b.Call("textureDimensions", ctx.Clone(texture_arg));
      auto* zero = b.Construct(CreateASTTypeFor(ctx, coords_ty));
      auto* max = ctx.dst->Sub(
          texture_dims, b.Construct(CreateASTTypeFor(ctx, coords_ty), 1));
      auto* clamped_coords = b.Call("clamp", ctx.Clone(coords_arg), zero, max);
      ctx.Replace(coords_arg, clamped_coords);
    }

    // Clamp the array_index argument, if provided
    if (array_idx >= 0) {
      auto* arg = expr->args()[array_idx];
      auto* num_layers = b.Call("textureNumLayers", ctx.Clone(texture_arg));
      auto* zero = b.Expr(0);
      auto* max = ctx.dst->Sub(num_layers, 1);
      auto* clamped = b.Call("clamp", ctx.Clone(arg), zero, max);
      ctx.Replace(arg, clamped);
    }

    // Clamp the level argument, if provided
    if (level_idx >= 0) {
      auto* arg = expr->args()[level_idx];
      ctx.Replace(arg, level_arg ? level_arg() : ctx.dst->Expr(0));
    }

    return nullptr;  // Clone, which will use the argument replacements above.
  }
};

Robustness::Robustness() = default;
Robustness::~Robustness() = default;

void Robustness::Run(CloneContext& ctx, const DataMap&, DataMap&) {
  State state{ctx};
  state.Transform();
  ctx.Clone();
}

}  // namespace transform
}  // namespace tint
