// Copyright 2022 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/unwind_discard_functions.h"

#include <memory>
#include <string>
#include <unordered_set>
#include <utility>
#include <vector>

#include "src/tint/ast/discard_statement.h"
#include "src/tint/ast/return_statement.h"
#include "src/tint/ast/traverse_expressions.h"
#include "src/tint/sem/block_statement.h"
#include "src/tint/sem/call.h"
#include "src/tint/sem/for_loop_statement.h"
#include "src/tint/sem/function.h"
#include "src/tint/sem/if_statement.h"
#include "src/tint/transform/utils/get_insertion_point.h"

TINT_INSTANTIATE_TYPEINFO(tint::transform::UnwindDiscardFunctions);

namespace tint::transform {
namespace {

class State {
  private:
    CloneContext& ctx;
    ProgramBuilder& b;
    const sem::Info& sem;
    Symbol module_discard_var_name;   // Use ModuleDiscardVarName() to read
    Symbol module_discard_func_name;  // Use ModuleDiscardFuncName() to read

    // Returns true if `sem_expr` contains a call expression that may
    // (transitively) execute a discard statement.
    bool MayDiscard(const sem::Expression* sem_expr) {
        return sem_expr && sem_expr->Behaviors().Contains(sem::Behavior::kDiscard);
    }

    // Lazily creates and returns the name of the module bool variable for whether
    // to discard: "tint_discard".
    Symbol ModuleDiscardVarName() {
        if (!module_discard_var_name.IsValid()) {
            module_discard_var_name = b.Symbols().New("tint_discard");
            ctx.dst->GlobalVar(module_discard_var_name, b.ty.bool_(), b.Expr(false),
                               ast::StorageClass::kPrivate);
        }
        return module_discard_var_name;
    }

    // Lazily creates and returns the name of the function that contains a single
    // discard statement: "tint_discard_func".
    // We do this to avoid having multiple discard statements in a single program,
    // which causes problems in certain backends (see crbug.com/1118).
    Symbol ModuleDiscardFuncName() {
        if (!module_discard_func_name.IsValid()) {
            module_discard_func_name = b.Symbols().New("tint_discard_func");
            b.Func(module_discard_func_name, {}, b.ty.void_(), {b.Discard()});
        }
        return module_discard_func_name;
    }

    // Creates "return <default return value>;" based on the return type of
    // `stmt`'s owning function.
    const ast::ReturnStatement* Return(const ast::Statement* stmt) {
        const ast::Expression* ret_val = nullptr;
        auto* ret_type = sem.Get(stmt)->Function()->Declaration()->return_type;
        if (!ret_type->Is<ast::Void>()) {
            ret_val = b.Construct(ctx.Clone(ret_type));
        }
        return b.Return(ret_val);
    }

    // Returns true if the function `stmt` is in is an entry point
    bool IsInEntryPointFunc(const ast::Statement* stmt) {
        return sem.Get(stmt)->Function()->Declaration()->IsEntryPoint();
    }

    // Creates "tint_discard_func();"
    const ast::CallStatement* CallDiscardFunc() {
        auto func_name = ModuleDiscardFuncName();
        return b.CallStmt(b.Call(func_name));
    }

    // Creates and returns a new if-statement of the form:
    //
    //    if (tint_discard) {
    //      return <default value>;
    //    }
    //
    // or if `stmt` is in a entry point function:
    //
    //    if (tint_discard) {
    //      tint_discard_func();
    //      return <default value>;
    //    }
    //
    const ast::IfStatement* IfDiscardReturn(const ast::Statement* stmt) {
        ast::StatementList stmts;

        // For entry point functions, also emit the discard statement
        if (IsInEntryPointFunc(stmt)) {
            stmts.emplace_back(CallDiscardFunc());
        }

        stmts.emplace_back(Return(stmt));

        auto var_name = ModuleDiscardVarName();
        return b.If(var_name, b.Block(stmts));
    }

    // Hoists `sem_expr` to a let followed by an `IfDiscardReturn` before `stmt`.
    // For example, if `stmt` is:
    //
    //    return f();
    //
    // This function will transform this to:
    //
    //    let t1 = f();
    //    if (tint_discard) {
    //      return;
    //    }
    //    return t1;
    //
    const ast::Statement* HoistAndInsertBefore(const ast::Statement* stmt,
                                               const sem::Expression* sem_expr) {
        auto* expr = sem_expr->Declaration();

        auto ip = utils::GetInsertionPoint(ctx, stmt);
        auto var_name = b.Sym();
        auto* decl = b.Decl(b.Var(var_name, nullptr, ctx.Clone(expr)));
        ctx.InsertBefore(ip.first->Declaration()->statements, ip.second, decl);

        ctx.InsertBefore(ip.first->Declaration()->statements, ip.second, IfDiscardReturn(stmt));

        auto* var_expr = b.Expr(var_name);

        // Special handling for CallStatement as we can only replace its expression
        // with a CallExpression.
        if (stmt->Is<ast::CallStatement>()) {
            // We could replace the call statement with no statement, but we can't do
            // that with transforms (yet), so just return a phony assignment.
            return b.Assign(b.Phony(), var_expr);
        }

        ctx.Replace(expr, var_expr);
        return ctx.CloneWithoutTransform(stmt);
    }

    // Returns true if `stmt` is a for-loop initializer statement.
    bool IsForLoopInitStatement(const ast::Statement* stmt) {
        if (auto* sem_stmt = sem.Get(stmt)) {
            if (auto* sem_fl = As<sem::ForLoopStatement>(sem_stmt->Parent())) {
                return sem_fl->Declaration()->initializer == stmt;
            }
        }
        return false;
    }

    // Inserts an `IfDiscardReturn` after `stmt` if possible (i.e. `stmt` is not
    // in a for-loop init), otherwise falls back to HoistAndInsertBefore, hoisting
    // `sem_expr` to a let followed by an `IfDiscardReturn` before `stmt`.
    //
    // For example, if `stmt` is:
    //
    //    let r = f();
    //
    // This function will transform this to:
    //
    //    let r = f();
    //    if (tint_discard) {
    //      return;
    //    }
    const ast::Statement* TryInsertAfter(const ast::Statement* stmt,
                                         const sem::Expression* sem_expr) {
        // If `stmt` is the init of a for-loop, hoist and insert before instead.
        if (IsForLoopInitStatement(stmt)) {
            return HoistAndInsertBefore(stmt, sem_expr);
        }

        auto ip = utils::GetInsertionPoint(ctx, stmt);
        ctx.InsertAfter(ip.first->Declaration()->statements, ip.second, IfDiscardReturn(stmt));
        return nullptr;  // Don't replace current statement
    }

    // Replaces the input discard statement with either setting the module level
    // discard bool ("tint_discard = true"), or calling the discard function
    // ("tint_discard_func()"), followed by a default return statement.
    //
    // Replaces "discard;" with:
    //
    //    tint_discard = true;
    //    return;
    //
    // Or if `stmt` is a entry point function, replaces with:
    //
    //    tint_discard_func();
    //    return;
    //
    const ast::Statement* ReplaceDiscardStatement(const ast::DiscardStatement* stmt) {
        const ast::Statement* to_insert = nullptr;
        if (IsInEntryPointFunc(stmt)) {
            to_insert = CallDiscardFunc();
        } else {
            auto var_name = ModuleDiscardVarName();
            to_insert = b.Assign(var_name, true);
        }

        auto ip = utils::GetInsertionPoint(ctx, stmt);
        ctx.InsertBefore(ip.first->Declaration()->statements, ip.second, to_insert);
        return Return(stmt);
    }

    // Handle statement
    const ast::Statement* Statement(const ast::Statement* stmt) {
        return Switch(
            stmt,
            [&](const ast::DiscardStatement* s) -> const ast::Statement* {
                return ReplaceDiscardStatement(s);
            },
            [&](const ast::AssignmentStatement* s) -> const ast::Statement* {
                auto* sem_lhs = sem.Get(s->lhs);
                auto* sem_rhs = sem.Get(s->rhs);
                if (MayDiscard(sem_lhs)) {
                    if (MayDiscard(sem_rhs)) {
                        TINT_ICE(Transform, b.Diagnostics())
                            << "Unexpected: both sides of assignment statement may "
                               "discard. Make sure transform::PromoteSideEffectsToDecl "
                               "was run first.";
                    }
                    return TryInsertAfter(s, sem_lhs);
                } else if (MayDiscard(sem_rhs)) {
                    return TryInsertAfter(s, sem_rhs);
                }
                return nullptr;
            },
            [&](const ast::CallStatement* s) -> const ast::Statement* {
                auto* sem_expr = sem.Get(s->expr);
                if (!MayDiscard(sem_expr)) {
                    return nullptr;
                }
                return TryInsertAfter(s, sem_expr);
            },
            [&](const ast::ForLoopStatement* s) -> const ast::Statement* {
                if (MayDiscard(sem.Get(s->condition))) {
                    TINT_ICE(Transform, b.Diagnostics())
                        << "Unexpected ForLoopStatement condition that may discard. "
                           "Make sure transform::PromoteSideEffectsToDecl was run "
                           "first.";
                }
                return nullptr;
            },
            [&](const ast::WhileStatement* s) -> const ast::Statement* {
                if (MayDiscard(sem.Get(s->condition))) {
                    TINT_ICE(Transform, b.Diagnostics())
                        << "Unexpected WhileStatement condition that may discard. "
                           "Make sure transform::PromoteSideEffectsToDecl was run "
                           "first.";
                }
                return nullptr;
            },
            [&](const ast::IfStatement* s) -> const ast::Statement* {
                auto* sem_expr = sem.Get(s->condition);
                if (!MayDiscard(sem_expr)) {
                    return nullptr;
                }
                return HoistAndInsertBefore(s, sem_expr);
            },
            [&](const ast::ReturnStatement* s) -> const ast::Statement* {
                auto* sem_expr = sem.Get(s->value);
                if (!MayDiscard(sem_expr)) {
                    return nullptr;
                }
                return HoistAndInsertBefore(s, sem_expr);
            },
            [&](const ast::SwitchStatement* s) -> const ast::Statement* {
                auto* sem_expr = sem.Get(s->condition);
                if (!MayDiscard(sem_expr)) {
                    return nullptr;
                }
                return HoistAndInsertBefore(s, sem_expr);
            },
            [&](const ast::VariableDeclStatement* s) -> const ast::Statement* {
                auto* var = s->variable;
                if (!var->constructor) {
                    return nullptr;
                }
                auto* sem_expr = sem.Get(var->constructor);
                if (!MayDiscard(sem_expr)) {
                    return nullptr;
                }
                return TryInsertAfter(s, sem_expr);
            });
    }

  public:
    /// Constructor
    /// @param ctx_in the context
    explicit State(CloneContext& ctx_in) : ctx(ctx_in), b(*ctx_in.dst), sem(ctx_in.src->Sem()) {}

    /// Runs the transform
    void Run() {
        ctx.ReplaceAll([&](const ast::BlockStatement* block) -> const ast::Statement* {
            // Iterate block statements and replace them as needed.
            for (auto* stmt : block->statements) {
                if (auto* new_stmt = Statement(stmt)) {
                    ctx.Replace(stmt, new_stmt);
                }

                // Handle for loops, as they are the only other AST node that
                // contains statements outside of BlockStatements.
                if (auto* fl = stmt->As<ast::ForLoopStatement>()) {
                    if (auto* new_stmt = Statement(fl->initializer)) {
                        ctx.Replace(fl->initializer, new_stmt);
                    }
                    if (auto* new_stmt = Statement(fl->continuing)) {
                        // NOTE: Should never reach here as we cannot discard in a
                        // continuing block.
                        ctx.Replace(fl->continuing, new_stmt);
                    }
                }
            }

            return nullptr;
        });

        ctx.Clone();
    }
};

}  // namespace

UnwindDiscardFunctions::UnwindDiscardFunctions() = default;
UnwindDiscardFunctions::~UnwindDiscardFunctions() = default;

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

bool UnwindDiscardFunctions::ShouldRun(const Program* program, const DataMap& /*data*/) const {
    auto& sem = program->Sem();
    for (auto* f : program->AST().Functions()) {
        if (sem.Get(f)->Behaviors().Contains(sem::Behavior::kDiscard)) {
            return true;
        }
    }
    return false;
}

}  // namespace tint::transform
