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

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

using namespace tint::number_suffixes;  // NOLINT

namespace tint::transform {

/// PIMPL state for the transform
struct Robustness::State {
    /// Constructor
    /// @param program the source program
    /// @param omitted the omitted address spaces
    State(const Program* program, std::unordered_set<type::AddressSpace>&& omitted)
        : src(program), omitted_address_spaces(std::move(omitted)) {}

    /// Runs the transform
    /// @returns the new program or SkipTransform if the transform is not required
    ApplyResult Run() {
        ctx.ReplaceAll([&](const ast::IndexAccessorExpression* expr) { return Transform(expr); });
        ctx.ReplaceAll([&](const ast::CallExpression* expr) { return Transform(expr); });

        ctx.Clone();
        return Program(std::move(b));
    }

  private:
    /// The source program
    const Program* const src;
    /// The target program builder
    ProgramBuilder b;
    /// The clone context
    CloneContext ctx = {&b, src, /* auto_clone_symbols */ true};

    /// Set of address spaces to not apply the transform to
    std::unordered_set<type::AddressSpace> omitted_address_spaces;

    /// 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* sem = src->Sem().Get(expr)->Unwrap()->As<sem::IndexAccessorExpression>();
        auto* ret_type = sem->Type();

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

        // idx return the cloned index expression, as a u32.
        auto idx = [&]() -> const ast::Expression* {
            auto* i = ctx.Clone(expr->index);
            if (sem->Index()->Type()->is_signed_integer_scalar()) {
                return b.Construct(b.ty.u32(), i);  // u32(idx)
            }
            return i;
        };

        auto* clamped_idx = Switch(
            sem->Object()->Type()->UnwrapRef(),  //
            [&](const type::Vector* vec) -> const ast::Expression* {
                if (sem->Index()->ConstantValue()) {
                    // Index and size is constant.
                    // Validation will have rejected any OOB accesses.
                    return nullptr;
                }

                return b.Call("min", idx(), u32(vec->Width() - 1u));
            },
            [&](const type::Matrix* mat) -> const ast::Expression* {
                if (sem->Index()->ConstantValue()) {
                    // Index and size is constant.
                    // Validation will have rejected any OOB accesses.
                    return nullptr;
                }

                return b.Call("min", idx(), u32(mat->columns() - 1u));
            },
            [&](const type::Array* arr) -> const ast::Expression* {
                const ast::Expression* max = nullptr;
                if (arr->Count()->Is<type::RuntimeArrayCount>()) {
                    // Size is unknown until runtime.
                    // Must clamp, even if the index is constant.
                    auto* arr_ptr = b.AddressOf(ctx.Clone(expr->object));
                    max = b.Sub(b.Call("arrayLength", arr_ptr), 1_u);
                } else if (auto count = arr->ConstantCount()) {
                    if (sem->Index()->ConstantValue()) {
                        // Index and size is constant.
                        // Validation will have rejected any OOB accesses.
                        return nullptr;
                    }
                    max = b.Expr(u32(count.value() - 1u));
                } else {
                    // Note: Don't be tempted to use the array override variable as an expression
                    // here, the name might be shadowed!
                    b.Diagnostics().add_error(diag::System::Transform,
                                              type::Array::kErrExpectedConstantCount);
                    return nullptr;
                }

                return b.Call("min", idx(), max);
            },
            [&](Default) {
                TINT_ICE(Transform, b.Diagnostics())
                    << "unhandled object type in robustness of array index: "
                    << src->FriendlyName(ret_type->UnwrapRef());
                return nullptr;
            });

        if (!clamped_idx) {
            return nullptr;  // Clamping not needed
        }

        auto idx_src = ctx.Clone(expr->source);
        auto* idx_obj = ctx.Clone(expr->object);
        return b.IndexAccessor(idx_src, idx_obj, clamped_idx);
    }

    /// @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 = src->Sem().Get(expr)->UnwrapMaterialize()->As<sem::Call>();
        auto* call_target = call->Target();
        auto* builtin = call_target->As<sem::Builtin>();
        if (!builtin || !TextureBuiltinNeedsClamping(builtin->Type())) {
            return nullptr;  // No transform, just clone.
        }

        // 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[static_cast<size_t>(texture_idx)];
        auto* coords_arg = expr->args[static_cast<size_t>(coords_idx)];
        auto* coords_ty = builtin->Parameters()[static_cast<size_t>(coords_idx)]->Type();

        auto width_of = [&](const type::Type* ty) {
            if (auto* vec = ty->As<type::Vector>()) {
                return vec->Width();
            }
            return 1u;
        };
        auto scalar_or_vec_ty = [&](const ast::Type* scalar, uint32_t width) -> const ast::Type* {
            if (width > 1) {
                return b.ty.vec(scalar, width);
            }
            return scalar;
        };
        auto scalar_or_vec = [&](const ast::Expression* scalar,
                                 uint32_t width) -> const ast::Expression* {
            if (width > 1) {
                return b.Construct(b.ty.vec(nullptr, width), scalar);
            }
            return scalar;
        };
        auto cast_to_signed = [&](const ast::Expression* val, uint32_t width) {
            return b.Construct(scalar_or_vec_ty(b.ty.i32(), width), val);
        };
        auto cast_to_unsigned = [&](const ast::Expression* val, uint32_t width) {
            return b.Construct(scalar_or_vec_ty(b.ty.u32(), width), val);
        };

        // 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 = [&] {
                const auto* arg = expr->args[static_cast<size_t>(level_idx)];
                const auto* target_ty =
                    builtin->Parameters()[static_cast<size_t>(level_idx)]->Type();
                const auto* num_levels = b.Call("textureNumLevels", ctx.Clone(texture_arg));

                // TODO(crbug.com/tint/1526) remove when num_levels returns u32
                num_levels = cast_to_unsigned(num_levels, 1u);

                const auto* unsigned_max = b.Sub(num_levels, 1_a);
                if (target_ty->is_signed_integer_scalar()) {
                    const auto* signed_max = cast_to_signed(unsigned_max, 1u);
                    return b.Call("clamp", ctx.Clone(arg), 0_a, signed_max);
                } else {
                    return b.Call("min", ctx.Clone(arg), unsigned_max);
                }
            };
        }

        // Clamp the coordinates argument
        {
            const auto* target_ty = coords_ty;
            const auto width = width_of(target_ty);
            const auto* texture_dims =
                level_arg ? b.Call("textureDimensions", ctx.Clone(texture_arg), level_arg())
                          : b.Call("textureDimensions", ctx.Clone(texture_arg));

            // TODO(crbug.com/tint/1526) remove when texture_dims returns u32 or vecN<u32>
            texture_dims = cast_to_unsigned(texture_dims, width);

            // texture_dims is u32 or vecN<u32>
            const auto* unsigned_max = b.Sub(texture_dims, scalar_or_vec(b.Expr(1_a), width));
            if (target_ty->is_signed_integer_scalar_or_vector()) {
                const auto* zero = scalar_or_vec(b.Expr(0_a), width);
                const auto* signed_max = cast_to_signed(unsigned_max, width);
                ctx.Replace(coords_arg, b.Call("clamp", ctx.Clone(coords_arg), zero, signed_max));
            } else {
                ctx.Replace(coords_arg, b.Call("min", ctx.Clone(coords_arg), unsigned_max));
            }
        }

        // Clamp the array_index argument, if provided
        if (array_idx >= 0) {
            auto* target_ty = builtin->Parameters()[static_cast<size_t>(array_idx)]->Type();
            auto* arg = expr->args[static_cast<size_t>(array_idx)];
            auto* num_layers = b.Call("textureNumLayers", ctx.Clone(texture_arg));

            // TODO(crbug.com/tint/1526) remove when num_layers returns u32
            num_layers = cast_to_unsigned(num_layers, 1u);

            const auto* unsigned_max = b.Sub(num_layers, 1_a);
            if (target_ty->is_signed_integer_scalar()) {
                const auto* signed_max = cast_to_signed(unsigned_max, 1u);
                ctx.Replace(arg, b.Call("clamp", ctx.Clone(arg), 0_a, signed_max));
            } else {
                ctx.Replace(arg, b.Call("min", ctx.Clone(arg), unsigned_max));
            }
        }

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

        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;

Transform::ApplyResult Robustness::Apply(const Program* src,
                                         const DataMap& inputs,
                                         DataMap&) const {
    Config cfg;
    if (auto* cfg_data = inputs.Get<Config>()) {
        cfg = *cfg_data;
    }

    std::unordered_set<type::AddressSpace> omitted_address_spaces;
    for (auto sc : cfg.omitted_address_spaces) {
        switch (sc) {
            case AddressSpace::kUniform:
                omitted_address_spaces.insert(type::AddressSpace::kUniform);
                break;
            case AddressSpace::kStorage:
                omitted_address_spaces.insert(type::AddressSpace::kStorage);
                break;
        }
    }

    return State{src, std::move(omitted_address_spaces)}.Run();
}

}  // namespace tint::transform
