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

#ifndef SKSL_CFGGENERATOR
#define SKSL_CFGGENERATOR

#include "ir/SkSLExpression.h"
#include "ir/SkSLFunctionDefinition.h"

#include <set>
#include <stack>

namespace SkSL {

// index of a block within CFG.fBlocks
typedef size_t BlockId;

struct BasicBlock {
    struct Node {
        enum Kind {
            kStatement_Kind,
            kExpression_Kind
        };

        Node(Kind kind, bool constantPropagation, std::unique_ptr<Expression>* expression,
             std::unique_ptr<Statement>* statement)
        : fKind(kind)
        , fConstantPropagation(constantPropagation)
        , fExpression(expression)
        , fStatement(statement) {}

        std::unique_ptr<Expression>* expression() const {
            ASSERT(fKind == kExpression_Kind);
            return fExpression;
        }

        void setExpression(std::unique_ptr<Expression> expr) {
            ASSERT(fKind == kExpression_Kind);
            *fExpression = std::move(expr);
        }

        std::unique_ptr<Statement>* statement() const {
            ASSERT(fKind == kStatement_Kind);
            return fStatement;
        }

        void setStatement(std::unique_ptr<Statement> stmt) {
            ASSERT(fKind == kStatement_Kind);
            *fStatement = std::move(stmt);
        }

        String description() const {
            if (fKind == kStatement_Kind) {
                return (*fStatement)->description();
            } else {
                ASSERT(fKind == kExpression_Kind);
                return (*fExpression)->description();
            }
        }

        Kind fKind;
        // if false, this node should not be subject to constant propagation. This happens with
        // compound assignment (i.e. x *= 2), in which the value x is used as an rvalue for
        // multiplication by 2 and then as an lvalue for assignment purposes. Since there is only
        // one "x" node, replacing it with a constant would break the assignment and we suppress
        // it. Down the road, we should handle this more elegantly by substituting a regular
        // assignment if the target is constant (i.e. x = 1; x *= 2; should become x = 1; x = 1 * 2;
        // and then collapse down to a simple x = 2;).
        bool fConstantPropagation;

    private:
        // we store pointers to the unique_ptrs so that we can replace expressions or statements
        // during optimization without having to regenerate the entire tree
        std::unique_ptr<Expression>* fExpression;
        std::unique_ptr<Statement>* fStatement;
    };

    /**
     * Attempts to remove the expression (and its subexpressions) pointed to by the iterator. If the
     * expression can be cleanly removed, returns true and updates the iterator to point to the
     * expression after the deleted expression. Otherwise returns false (and the CFG will need to be
     * regenerated).
     */
    bool tryRemoveExpression(std::vector<BasicBlock::Node>::iterator* iter);

    /**
     * Locates and attempts remove an expression occurring before the expression pointed to by iter.
     * If the expression can be cleanly removed, returns true and resets iter to a valid iterator
     * pointing to the same expression it did initially. Otherwise returns false (and the CFG will
     * need to be regenerated).
     */
    bool tryRemoveExpressionBefore(std::vector<BasicBlock::Node>::iterator* iter, Expression* e);

    /**
     * As tryRemoveExpressionBefore, but for lvalues. As lvalues are at most partially evaluated
     * (for instance, x[i] = 0 evaluates i but not x) this will only look for the parts of the
     * lvalue that are actually evaluated.
     */
    bool tryRemoveLValueBefore(std::vector<BasicBlock::Node>::iterator* iter, Expression* lvalue);

    /**
     * Attempts to inserts a new expression before the node pointed to by iter. If the
     * expression can be cleanly inserted, returns true and updates the iterator to point to the
     * newly inserted expression. Otherwise returns false (and the CFG will need to be regenerated).
     */
    bool tryInsertExpression(std::vector<BasicBlock::Node>::iterator* iter,
                             std::unique_ptr<Expression>* expr);

    std::vector<Node> fNodes;
    std::set<BlockId> fEntrances;
    std::set<BlockId> fExits;
    // variable definitions upon entering this basic block (null expression = undefined)
    DefinitionMap fBefore;
};

struct CFG {
    BlockId fStart;
    BlockId fExit;
    std::vector<BasicBlock> fBlocks;

    void dump();

private:
    BlockId fCurrent;

    // Adds a new block, adds an exit* from the current block to the new block, then marks the new
    // block as the current block
    // *see note in addExit()
    BlockId newBlock();

    // Adds a new block, but does not mark it current or add an exit from the current block
    BlockId newIsolatedBlock();

    // Adds an exit from the 'from' block to the 'to' block
    // Note that we skip adding the exit if the 'from' block is itself unreachable; this means that
    // we don't actually have to trace the tree to see if a particular block is unreachable, we can
    // just check to see if it has any entrances. This does require a bit of care in the order in
    // which we set the CFG up.
    void addExit(BlockId from, BlockId to);

    friend class CFGGenerator;
};

/**
 * Converts functions into control flow graphs.
 */
class CFGGenerator {
public:
    CFGGenerator() {}

    CFG getCFG(FunctionDefinition& f);

private:
    void addStatement(CFG& cfg, std::unique_ptr<Statement>* s);

    void addExpression(CFG& cfg, std::unique_ptr<Expression>* e, bool constantPropagate);

    void addLValue(CFG& cfg, std::unique_ptr<Expression>* e);

    std::stack<BlockId> fLoopContinues;
    std::stack<BlockId> fLoopExits;
};

}

#endif
