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

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

using namespace tint::number_suffixes;  // NOLINT

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;

        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, 1_u);
        } 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(u32(idx.u32));
            }
            if (!limit.expr) {
                limit.expr = b.Expr(u32(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(i32(idx.i32)))
                                     : static_cast<const ast::Expression*>(b.Expr(u32(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_i);
                auto* max = ctx.dst->Sub(num_levels, 1_i);
                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_i));
            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_i);
            auto* max = ctx.dst->Sub(num_layers, 1_i);
            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_i));
        }

        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
