// 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 {
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([&](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()->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
                     ? 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 transform
}  // namespace tint
