/*
 * Copyright 2021 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include <memory>

#include "src/sksl/SkSLDefinitionMap.h"

#include "src/sksl/SkSLCFGGenerator.h"
#include "src/sksl/ir/SkSLBinaryExpression.h"
#include "src/sksl/ir/SkSLExpression.h"
#include "src/sksl/ir/SkSLFieldAccess.h"
#include "src/sksl/ir/SkSLFunctionCall.h"
#include "src/sksl/ir/SkSLIndexExpression.h"
#include "src/sksl/ir/SkSLPostfixExpression.h"
#include "src/sksl/ir/SkSLPrefixExpression.h"
#include "src/sksl/ir/SkSLSwizzle.h"
#include "src/sksl/ir/SkSLTernaryExpression.h"

namespace SkSL {

/**
 * Maps all local variables in the function to null, indicating that their value is initially
 * unknown.
 */
void DefinitionMap::computeStartState(const CFG& cfg) {
    fDefinitions.reset();

    for (const BasicBlock& block : cfg.fBlocks) {
        for (const BasicBlock::Node& node : block.fNodes) {
            if (node.isStatement()) {
                const Statement* s = node.statement()->get();
                if (s->is<VarDeclaration>()) {
                    fDefinitions[&s->as<VarDeclaration>().var()] = nullptr;
                }
            }
        }
    }
}

Expression* DefinitionMap::getKnownDefinition(const Variable* var) const {
    // Find this variable in the definition map.
    std::unique_ptr<Expression>** exprPtr = fDefinitions.find(var);
    if (!exprPtr || !*exprPtr) {
        return nullptr;
    }
    // Return known expressions only; return "null" for defined-but-unknown expressions.
    Expression* expr = (*exprPtr)->get();
    return (expr->kind() != Expression::Kind::kDefined) ? expr : nullptr;
}

// Add compile-time constants to the definition map. Non-compile-time constant expressions are saved
// as just "defined" since we can't guarantee that the expression will remain alive until the end of
// optimization.
void DefinitionMap::addDefinition(const Context& context, const Variable* var,
                                  std::unique_ptr<Expression>* expr) {
    fDefinitions.set(var, (*expr)->isCompileTimeConstant()
                                  ? expr
                                  : (std::unique_ptr<Expression>*)&context.fDefined_Expression);
}

// Add the definition created by assigning to the lvalue to the definition map.
void DefinitionMap::addDefinition(const Context& context, const Expression* lvalue,
                                  std::unique_ptr<Expression>* expr) {
    switch (lvalue->kind()) {
        case Expression::Kind::kVariableReference: {
            const Variable& var = *lvalue->as<VariableReference>().variable();
            if (var.storage() == Variable::Storage::kLocal) {
                this->addDefinition(context, &var, expr);
            }
            break;
        }
        case Expression::Kind::kSwizzle:
            // We consider the variable written to as long as at least some of its components have
            // been written to. This will lead to some false negatives (we won't catch it if you
            // write to foo.x and then read foo.y), but being stricter could lead to false positives
            // (we write to foo.x, and then pass foo to a function which happens to only read foo.x,
            // but since we pass foo as a whole it is flagged as an error) unless we perform a much
            // more complicated whole-program analysis. This is probably good enough.
            this->addDefinition(context, lvalue->as<Swizzle>().base().get(),
                                (std::unique_ptr<Expression>*)&context.fDefined_Expression);
            break;

        case Expression::Kind::kIndex:
            // see comments in Swizzle
            this->addDefinition(context, lvalue->as<IndexExpression>().base().get(),
                                (std::unique_ptr<Expression>*)&context.fDefined_Expression);
            break;

        case Expression::Kind::kFieldAccess:
            // see comments in Swizzle
            this->addDefinition(context, lvalue->as<FieldAccess>().base().get(),
                                (std::unique_ptr<Expression>*)&context.fDefined_Expression);
            break;

        case Expression::Kind::kTernary:
            // To simplify analysis, we just pretend that we write to both sides of the ternary.
            // This allows for false positives (meaning we fail to detect that a variable might not
            // have been assigned), but is preferable to false negatives.
            this->addDefinition(context, lvalue->as<TernaryExpression>().ifTrue().get(),
                                (std::unique_ptr<Expression>*)&context.fDefined_Expression);
            this->addDefinition(context, lvalue->as<TernaryExpression>().ifFalse().get(),
                                (std::unique_ptr<Expression>*)&context.fDefined_Expression);
            break;

        default:
            SkDEBUGFAILF("expression is not an lvalue: %s", lvalue->description().c_str());
            break;
    }
}

// Add local variables defined by this node to the map.
void DefinitionMap::addDefinitions(const Context& context, const BasicBlock::Node& node) {
    if (node.isExpression()) {
        Expression* expr = node.expression()->get();
        switch (expr->kind()) {
            case Expression::Kind::kBinary: {
                BinaryExpression* b = &expr->as<BinaryExpression>();
                if (b->getOperator().kind() == Token::Kind::TK_EQ) {
                    this->addDefinition(context, b->left().get(), &b->right());
                } else if (b->getOperator().isAssignment()) {
                    this->addDefinition(
                            context, b->left().get(),
                            (std::unique_ptr<Expression>*)&context.fDefined_Expression);
                }
                break;
            }
            case Expression::Kind::kFunctionCall: {
                const FunctionCall& c = expr->as<FunctionCall>();
                const std::vector<const Variable*>& parameters = c.function().parameters();
                for (size_t i = 0; i < parameters.size(); ++i) {
                    if (parameters[i]->modifiers().fFlags & Modifiers::kOut_Flag) {
                        this->addDefinition(
                                context, c.arguments()[i].get(),
                                (std::unique_ptr<Expression>*)&context.fDefined_Expression);
                    }
                }
                break;
            }
            case Expression::Kind::kPrefix: {
                const PrefixExpression* p = &expr->as<PrefixExpression>();
                if (p->getOperator().kind() == Token::Kind::TK_MINUSMINUS ||
                    p->getOperator().kind() == Token::Kind::TK_PLUSPLUS) {
                    this->addDefinition(
                            context, p->operand().get(),
                            (std::unique_ptr<Expression>*)&context.fDefined_Expression);
                }
                break;
            }
            case Expression::Kind::kPostfix: {
                const PostfixExpression* p = &expr->as<PostfixExpression>();
                if (p->getOperator().kind() == Token::Kind::TK_MINUSMINUS ||
                    p->getOperator().kind() == Token::Kind::TK_PLUSPLUS) {
                    this->addDefinition(
                            context, p->operand().get(),
                            (std::unique_ptr<Expression>*)&context.fDefined_Expression);
                }
                break;
            }
            case Expression::Kind::kVariableReference: {
                const VariableReference* v = &expr->as<VariableReference>();
                if (v->refKind() != VariableReference::RefKind::kRead) {
                    this->addDefinition(
                            context, v,
                            (std::unique_ptr<Expression>*)&context.fDefined_Expression);
                }
                break;
            }
            default:
                break;
        }
    } else if (node.isStatement()) {
        Statement* stmt = node.statement()->get();
        if (stmt->is<VarDeclaration>()) {
            VarDeclaration& vd = stmt->as<VarDeclaration>();
            if (vd.value()) {
                this->addDefinition(context, &vd.var(), &vd.value());
            }
        }
    }
}

}  // namespace SkSL
