// Copyright 2021 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/localize_struct_array_assignment.h"

#include <unordered_map>
#include <utility>

#include "src/tint/ast/assignment_statement.h"
#include "src/tint/ast/traverse_expressions.h"
#include "src/tint/program_builder.h"
#include "src/tint/sem/expression.h"
#include "src/tint/sem/member_accessor_expression.h"
#include "src/tint/sem/reference.h"
#include "src/tint/sem/statement.h"
#include "src/tint/sem/variable.h"
#include "src/tint/transform/simplify_pointers.h"
#include "src/tint/utils/scoped_assignment.h"

TINT_INSTANTIATE_TYPEINFO(tint::transform::LocalizeStructArrayAssignment);

namespace tint::transform {

/// Private implementation of LocalizeStructArrayAssignment transform
class LocalizeStructArrayAssignment::State {
  private:
    CloneContext& ctx;
    ProgramBuilder& b;

    /// Returns true if `expr` contains an index accessor expression to a
    /// structure member of array type.
    bool ContainsStructArrayIndex(const ast::Expression* expr) {
        bool result = false;
        ast::TraverseExpressions(
            expr, b.Diagnostics(), [&](const ast::IndexAccessorExpression* ia) {
                // Indexing using a runtime value?
                auto* idx_sem = ctx.src->Sem().Get(ia->index);
                if (!idx_sem->ConstantValue().IsValid()) {
                    // Indexing a member access expr?
                    if (auto* ma = ia->object->As<ast::MemberAccessorExpression>()) {
                        // That accesses an array?
                        if (ctx.src->TypeOf(ma)->UnwrapRef()->Is<sem::Array>()) {
                            result = true;
                            return ast::TraverseAction::Stop;
                        }
                    }
                }
                return ast::TraverseAction::Descend;
            });

        return result;
    }

    // Returns the type and storage class of the originating variable of the lhs
    // of the assignment statement.
    // See https://www.w3.org/TR/WGSL/#originating-variable-section
    std::pair<const sem::Type*, ast::StorageClass> GetOriginatingTypeAndStorageClass(
        const ast::AssignmentStatement* assign_stmt) {
        auto* source_var = ctx.src->Sem().Get(assign_stmt->lhs)->SourceVariable();
        if (!source_var) {
            TINT_ICE(Transform, b.Diagnostics())
                << "Unable to determine originating variable for lhs of assignment "
                   "statement";
            return {};
        }

        auto* type = source_var->Type();
        if (auto* ref = type->As<sem::Reference>()) {
            return {ref->StoreType(), ref->StorageClass()};
        } else if (auto* ptr = type->As<sem::Pointer>()) {
            return {ptr->StoreType(), ptr->StorageClass()};
        }

        TINT_ICE(Transform, b.Diagnostics())
            << "Expecting to find variable of type pointer or reference on lhs "
               "of assignment statement";
        return {};
    }

  public:
    /// Constructor
    /// @param ctx_in the CloneContext primed with the input program and
    /// ProgramBuilder
    explicit State(CloneContext& ctx_in) : ctx(ctx_in), b(*ctx_in.dst) {}

    /// Runs the transform
    void Run() {
        struct Shared {
            bool process_nested_nodes = false;
            ast::StatementList insert_before_stmts;
            ast::StatementList insert_after_stmts;
        } s;

        ctx.ReplaceAll([&](const ast::AssignmentStatement* assign_stmt) -> const ast::Statement* {
            // Process if it's an assignment statement to a dynamically indexed array
            // within a struct on a function or private storage variable. This
            // specific use-case is what FXC fails to compile with:
            // error X3500: array reference cannot be used as an l-value; not natively
            // addressable
            if (!ContainsStructArrayIndex(assign_stmt->lhs)) {
                return nullptr;
            }
            auto og = GetOriginatingTypeAndStorageClass(assign_stmt);
            if (!(og.first->Is<sem::Struct>() && (og.second == ast::StorageClass::kFunction ||
                                                  og.second == ast::StorageClass::kPrivate))) {
                return nullptr;
            }

            // Reset shared state for this assignment statement
            s = Shared{};

            const ast::Expression* new_lhs = nullptr;
            {
                TINT_SCOPED_ASSIGNMENT(s.process_nested_nodes, true);
                new_lhs = ctx.Clone(assign_stmt->lhs);
            }

            auto* new_assign_stmt = b.Assign(new_lhs, ctx.Clone(assign_stmt->rhs));

            // Combine insert_before_stmts + new_assign_stmt + insert_after_stmts into
            // a block and return it
            ast::StatementList stmts = std::move(s.insert_before_stmts);
            stmts.reserve(1 + s.insert_after_stmts.size());
            stmts.emplace_back(new_assign_stmt);
            stmts.insert(stmts.end(), s.insert_after_stmts.begin(), s.insert_after_stmts.end());

            return b.Block(std::move(stmts));
        });

        ctx.ReplaceAll(
            [&](const ast::IndexAccessorExpression* index_access) -> const ast::Expression* {
                if (!s.process_nested_nodes) {
                    return nullptr;
                }

                // Indexing a member access expr?
                auto* mem_access = index_access->object->As<ast::MemberAccessorExpression>();
                if (!mem_access) {
                    return nullptr;
                }

                // Process any nested IndexAccessorExpressions
                mem_access = ctx.Clone(mem_access);

                // Store the address of the member access into a let as we need to read
                // the value twice e.g. let tint_symbol = &(s.a1);
                auto mem_access_ptr = b.Sym();
                s.insert_before_stmts.push_back(
                    b.Decl(b.Let(mem_access_ptr, nullptr, b.AddressOf(mem_access))));

                // Disable further transforms when cloning
                TINT_SCOPED_ASSIGNMENT(s.process_nested_nodes, false);

                // Copy entire array out of struct into local temp var
                // e.g. var tint_symbol_1 = *(tint_symbol);
                auto tmp_var = b.Sym();
                s.insert_before_stmts.push_back(
                    b.Decl(b.Var(tmp_var, nullptr, b.Deref(mem_access_ptr))));

                // Replace input index_access with a clone of itself, but with its
                // .object replaced by the new temp var. This is returned from this
                // function to modify the original assignment statement. e.g.
                // tint_symbol_1[uniforms.i]
                auto* new_index_access = b.IndexAccessor(tmp_var, ctx.Clone(index_access->index));

                // Assign temp var back to array
                // e.g. *(tint_symbol) = tint_symbol_1;
                auto* assign_rhs_to_temp = b.Assign(b.Deref(mem_access_ptr), tmp_var);
                s.insert_after_stmts.insert(s.insert_after_stmts.begin(),
                                            assign_rhs_to_temp);  // push_front

                return new_index_access;
            });

        ctx.Clone();
    }
};

LocalizeStructArrayAssignment::LocalizeStructArrayAssignment() = default;

LocalizeStructArrayAssignment::~LocalizeStructArrayAssignment() = default;

void LocalizeStructArrayAssignment::Run(CloneContext& ctx, const DataMap&, DataMap&) const {
    State state(ctx);
    state.Run();
}

}  // namespace tint::transform
