// 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/reference_type.h"
#include "src/sem/statement.h"

TINT_INSTANTIATE_TYPEINFO(tint::transform::Robustness);
TINT_INSTANTIATE_TYPEINFO(tint::transform::Robustness::Config);

namespace tint {
namespace transform {

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

  /// Set of storage classes to not apply the transform to
  std::unordered_set<ast::StorageClass> omitted_classes;

  /// 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();

    auto* ref = ret_type->As<sem::Reference>();
    if (ref && omitted_classes.count(ref->StorageClass()) != 0) {
      return nullptr;
    }

    auto* ret_unwrapped = ret_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_unwrapped->As<sem::Vector>()) {
      size.u32 = vec->Width();

    } else if (auto* arr = ret_unwrapped->As<sem::Array>()) {
      size.u32 = arr->Count();
    } else if (auto* mat = ret_unwrapped->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_unwrapped->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->index);
    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->index);
      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& signature = intrinsic->Signature();
    auto texture_idx = signature.IndexOf(sem::ParameterUsage::kTexture);
    auto coords_idx = signature.IndexOf(sem::ParameterUsage::kCoords);
    auto array_idx = signature.IndexOf(sem::ParameterUsage::kArrayIndex);
    auto level_idx = signature.IndexOf(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::Config::Config() = default;
Robustness::Config::Config(const Config&) = default;
Robustness::Config::~Config() = default;
Robustness::Config& Robustness::Config::operator=(const Config&) = default;

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

void Robustness::Run(CloneContext& ctx, const DataMap& inputs, DataMap&) {
  Config cfg;
  if (auto* cfg_data = inputs.Get<Config>()) {
    cfg = *cfg_data;
  }

  std::unordered_set<ast::StorageClass> omitted_classes;
  for (auto sc : cfg.omitted_classes) {
    switch (sc) {
      case StorageClass::kUniform:
        omitted_classes.insert(ast::StorageClass::kUniform);
        break;
      case StorageClass::kStorage:
        omitted_classes.insert(ast::StorageClass::kStorage);
        break;
    }
  }

  State state{ctx, std::move(omitted_classes)};

  state.Transform();
  ctx.Clone();
}

}  // namespace transform
}  // namespace tint
