// 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/tint/transform/robustness.h"

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

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

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

namespace tint::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([&](const ast::IndexAccessorExpression* expr) {
      return Transform(expr);
    });
    ctx.ReplaceAll(
        [&](const 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.
  const ast::IndexAccessorExpression* Transform(
      const ast::IndexAccessorExpression* expr) {
    auto* ret_type = ctx.src->Sem().Get(expr->object)->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 {
      const 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 index 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->object);
      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()->TypeInfo().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 {
        TINT_ICE(Transform, b.Diagnostics())
            << "unsupported constant value for accessor "
            << idx_constant.Type()->TypeInfo().name;
        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
                     ? static_cast<const ast::Expression*>(b.Expr(idx.i32))
                     : static_cast<const ast::Expression*>(b.Expr(idx.u32));
    }

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

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

  /// Apply bounds clamping to the coordinates, array index and level arguments
  /// of the `textureLoad()` and `textureStore()` builtins.
  /// @param expr the builtin call expression
  /// @return the clamped replacement call expression, or nullptr if `expr`
  /// should be cloned without changes.
  const ast::CallExpression* Transform(const ast::CallExpression* expr) {
    auto* call = ctx.src->Sem().Get(expr);
    auto* call_target = call->Target();
    auto* builtin = call_target->As<sem::Builtin>();
    if (!builtin || !TextureBuiltinNeedsClamping(builtin->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 = builtin->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 = builtin->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<const 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&) const {
  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 tint::transform
