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

#include "src/sksl/SkSLCFGGenerator.h"

#include "src/sksl/ir/SkSLBinaryExpression.h"
#include "src/sksl/ir/SkSLConstructor.h"
#include "src/sksl/ir/SkSLDoStatement.h"
#include "src/sksl/ir/SkSLExpressionStatement.h"
#include "src/sksl/ir/SkSLExternalFunctionCall.h"
#include "src/sksl/ir/SkSLFieldAccess.h"
#include "src/sksl/ir/SkSLForStatement.h"
#include "src/sksl/ir/SkSLFunctionCall.h"
#include "src/sksl/ir/SkSLIfStatement.h"
#include "src/sksl/ir/SkSLIndexExpression.h"
#include "src/sksl/ir/SkSLPostfixExpression.h"
#include "src/sksl/ir/SkSLPrefixExpression.h"
#include "src/sksl/ir/SkSLReturnStatement.h"
#include "src/sksl/ir/SkSLSwitchStatement.h"
#include "src/sksl/ir/SkSLSwizzle.h"
#include "src/sksl/ir/SkSLTernaryExpression.h"
#include "src/sksl/ir/SkSLVarDeclarationsStatement.h"
#include "src/sksl/ir/SkSLWhileStatement.h"

namespace SkSL {

BlockId CFG::newBlock() {
    BlockId result = fBlocks.size();
    fBlocks.emplace_back();
    if (fBlocks.size() > 1) {
        this->addExit(fCurrent, result);
    }
    fCurrent = result;
    return result;
}

BlockId CFG::newIsolatedBlock() {
    BlockId result = fBlocks.size();
    fBlocks.emplace_back();
    return result;
}

void CFG::addExit(BlockId from, BlockId to) {
    if (from == 0 || fBlocks[from].fEntrances.size()) {
        fBlocks[from].fExits.insert(to);
        fBlocks[to].fEntrances.insert(from);
    }
}

#ifdef SK_DEBUG
void CFG::dump() {
    for (size_t i = 0; i < fBlocks.size(); i++) {
        printf("Block %d\n-------\nBefore: ", (int) i);
        const char* separator = "";
        for (auto iter = fBlocks[i].fBefore.begin(); iter != fBlocks[i].fBefore.end(); iter++) {
            printf("%s%s = %s", separator, iter->first->description().c_str(),
                   iter->second ? (*iter->second)->description().c_str() : "<undefined>");
            separator = ", ";
        }
        printf("\nEntrances: ");
        separator = "";
        for (BlockId b : fBlocks[i].fEntrances) {
            printf("%s%d", separator, (int) b);
            separator = ", ";
        }
        printf("\n");
        for (size_t j = 0; j < fBlocks[i].fNodes.size(); j++) {
            BasicBlock::Node& n = fBlocks[i].fNodes[j];
            printf("Node %d (%p): %s\n", (int) j, &n, n.fKind == BasicBlock::Node::kExpression_Kind
                                                         ? (*n.expression())->description().c_str()
                                                         : (*n.statement())->description().c_str());
        }
        printf("Exits: ");
        separator = "";
        for (BlockId b : fBlocks[i].fExits) {
            printf("%s%d", separator, (int) b);
            separator = ", ";
        }
        printf("\n\n");
    }
}
#endif

bool BasicBlock::tryRemoveExpressionBefore(std::vector<BasicBlock::Node>::iterator* iter,
                                           Expression* e) {
    if (e->kind() == Expression::Kind::kTernary) {
        return false;
    }
    bool result;
    if ((*iter)->fKind == BasicBlock::Node::kExpression_Kind) {
        SkASSERT((*iter)->expression()->get() != e);
        Expression* old = (*iter)->expression()->get();
        do {
            if ((*iter) == fNodes.begin()) {
                return false;
            }
            --(*iter);
        } while ((*iter)->fKind != BasicBlock::Node::kExpression_Kind ||
                 (*iter)->expression()->get() != e);
        result = this->tryRemoveExpression(iter);
        while ((*iter)->fKind != BasicBlock::Node::kExpression_Kind ||
               (*iter)->expression()->get() != old) {
            SkASSERT(*iter != fNodes.end());
            ++(*iter);
        }
    } else {
        Statement* old = (*iter)->statement()->get();
        do {
            if ((*iter) == fNodes.begin()) {
                return false;
            }
            --(*iter);
        } while ((*iter)->fKind != BasicBlock::Node::kExpression_Kind ||
                 (*iter)->expression()->get() != e);
        result = this->tryRemoveExpression(iter);
        while ((*iter)->fKind != BasicBlock::Node::kStatement_Kind ||
               (*iter)->statement()->get() != old) {
            SkASSERT(*iter != fNodes.end());
            ++(*iter);
        }
    }
    return result;
}

bool BasicBlock::tryRemoveLValueBefore(std::vector<BasicBlock::Node>::iterator* iter,
                                       Expression* lvalue) {
    switch (lvalue->kind()) {
        case Expression::Kind::kExternalValue: // fall through
        case Expression::Kind::kVariableReference:
            return true;
        case Expression::Kind::kSwizzle:
            return this->tryRemoveLValueBefore(iter, lvalue->as<Swizzle>().fBase.get());
        case Expression::Kind::kFieldAccess:
            return this->tryRemoveLValueBefore(iter, lvalue->as<FieldAccess>().fBase.get());
        case Expression::Kind::kIndex: {
            IndexExpression& indexExpr = lvalue->as<IndexExpression>();
            if (!this->tryRemoveLValueBefore(iter, indexExpr.fBase.get())) {
                return false;
            }
            return this->tryRemoveExpressionBefore(iter, indexExpr.fIndex.get());
        }
        case Expression::Kind::kTernary: {
            TernaryExpression& ternary = lvalue->as<TernaryExpression>();
            if (!this->tryRemoveExpressionBefore(iter, ternary.fTest.get())) {
                return false;
            }
            if (!this->tryRemoveLValueBefore(iter, ternary.fIfTrue.get())) {
                return false;
            }
            return this->tryRemoveLValueBefore(iter, ternary.fIfFalse.get());
        }
        default:
#ifdef SK_DEBUG
            ABORT("invalid lvalue: %s\n", lvalue->description().c_str());
#endif
            return false;
    }
}

bool BasicBlock::tryRemoveExpression(std::vector<BasicBlock::Node>::iterator* iter) {
    Expression* expr = (*iter)->expression()->get();
    switch (expr->kind()) {
        case Expression::Kind::kBinary: {
            BinaryExpression& b = expr->as<BinaryExpression>();
            if (b.fOperator == Token::Kind::TK_EQ) {
                if (!this->tryRemoveLValueBefore(iter, b.fLeft.get())) {
                    return false;
                }
            } else if (!this->tryRemoveExpressionBefore(iter, b.fLeft.get())) {
                return false;
            }
            if (!this->tryRemoveExpressionBefore(iter, b.fRight.get())) {
                return false;
            }
            SkASSERT((*iter)->expression()->get() == expr);
            *iter = fNodes.erase(*iter);
            return true;
        }
        case Expression::Kind::kTernary: {
            // ternaries cross basic block boundaries, must regenerate the CFG to remove it
            return false;
        }
        case Expression::Kind::kFieldAccess: {
            FieldAccess& f = expr->as<FieldAccess>();
            if (!this->tryRemoveExpressionBefore(iter, f.fBase.get())) {
                return false;
            }
            *iter = fNodes.erase(*iter);
            return true;
        }
        case Expression::Kind::kSwizzle: {
            Swizzle& s = expr->as<Swizzle>();
            if (s.fBase && !this->tryRemoveExpressionBefore(iter, s.fBase.get())) {
                return false;
            }
            *iter = fNodes.erase(*iter);
            return true;
        }
        case Expression::Kind::kIndex: {
            IndexExpression& idx = expr->as<IndexExpression>();
            if (!this->tryRemoveExpressionBefore(iter, idx.fBase.get())) {
                return false;
            }
            if (!this->tryRemoveExpressionBefore(iter, idx.fIndex.get())) {
                return false;
            }
            *iter = fNodes.erase(*iter);
            return true;
        }
        case Expression::Kind::kConstructor: {
            Constructor& c = expr->as<Constructor>();
            for (auto& arg : c.fArguments) {
                if (!this->tryRemoveExpressionBefore(iter, arg.get())) {
                    return false;
                }
                SkASSERT((*iter)->expression()->get() == expr);
            }
            *iter = fNodes.erase(*iter);
            return true;
        }
        case Expression::Kind::kFunctionCall: {
            FunctionCall& f = expr->as<FunctionCall>();
            for (auto& arg : f.fArguments) {
                if (!this->tryRemoveExpressionBefore(iter, arg.get())) {
                    return false;
                }
                SkASSERT((*iter)->expression()->get() == expr);
            }
            *iter = fNodes.erase(*iter);
            return true;
        }
        case Expression::Kind::kPrefix:
            if (!this->tryRemoveExpressionBefore(iter,
                                                 expr->as<PrefixExpression>().fOperand.get())) {
                return false;
            }
            *iter = fNodes.erase(*iter);
            return true;
        case Expression::Kind::kPostfix:
            if (!this->tryRemoveExpressionBefore(iter,
                                                 expr->as<PrefixExpression>().fOperand.get())) {
                return false;
            }
            *iter = fNodes.erase(*iter);
            return true;
        case Expression::Kind::kBoolLiteral:  // fall through
        case Expression::Kind::kFloatLiteral: // fall through
        case Expression::Kind::kIntLiteral:   // fall through
        case Expression::Kind::kSetting:      // fall through
        case Expression::Kind::kVariableReference:
            *iter = fNodes.erase(*iter);
            return true;
        default:
#ifdef SK_DEBUG
            ABORT("unhandled expression: %s\n", expr->description().c_str());
#endif
            return false;
    }
}

bool BasicBlock::tryInsertExpression(std::vector<BasicBlock::Node>::iterator* iter,
                                     std::unique_ptr<Expression>* expr) {
    switch ((*expr)->kind()) {
        case Expression::Kind::kBinary: {
            BinaryExpression& b = expr->get()->as<BinaryExpression>();
            if (!this->tryInsertExpression(iter, &b.fRight)) {
                return false;
            }
            ++(*iter);
            if (!this->tryInsertExpression(iter, &b.fLeft)) {
                return false;
            }
            ++(*iter);
            BasicBlock::Node node = { BasicBlock::Node::kExpression_Kind, true, expr, nullptr };
            *iter = fNodes.insert(*iter, node);
            return true;
        }
        case Expression::Kind::kBoolLiteral:  // fall through
        case Expression::Kind::kFloatLiteral: // fall through
        case Expression::Kind::kIntLiteral:   // fall through
        case Expression::Kind::kVariableReference: {
            BasicBlock::Node node = { BasicBlock::Node::kExpression_Kind, true, expr, nullptr };
            *iter = fNodes.insert(*iter, node);
            return true;
        }
        case Expression::Kind::kConstructor: {
            Constructor& c = expr->get()->as<Constructor>();
            for (auto& arg : c.fArguments) {
                if (!this->tryInsertExpression(iter, &arg)) {
                    return false;
                }
                ++(*iter);
            }
            BasicBlock::Node node = { BasicBlock::Node::kExpression_Kind, true, expr, nullptr };
            *iter = fNodes.insert(*iter, node);
            return true;
        }
        case Expression::Kind::kSwizzle: {
            Swizzle& s = expr->get()->as<Swizzle>();
            if (!this->tryInsertExpression(iter, &s.fBase)) {
                return false;
            }
            ++(*iter);
            BasicBlock::Node node = { BasicBlock::Node::kExpression_Kind, true, expr, nullptr };
            *iter = fNodes.insert(*iter, node);
            return true;
        }
        default:
            return false;
    }
}

void CFGGenerator::addExpression(CFG& cfg, std::unique_ptr<Expression>* e, bool constantPropagate) {
    SkASSERT(e);
    switch ((*e)->kind()) {
        case Expression::Kind::kBinary: {
            BinaryExpression& b = e->get()->as<BinaryExpression>();
            switch (b.fOperator) {
                case Token::Kind::TK_LOGICALAND: // fall through
                case Token::Kind::TK_LOGICALOR: {
                    // this isn't as precise as it could be -- we don't bother to track that if we
                    // early exit from a logical and/or, we know which branch of an 'if' we're going
                    // to hit -- but it won't make much difference in practice.
                    this->addExpression(cfg, &b.fLeft, constantPropagate);
                    BlockId start = cfg.fCurrent;
                    cfg.newBlock();
                    this->addExpression(cfg, &b.fRight, constantPropagate);
                    cfg.newBlock();
                    cfg.addExit(start, cfg.fCurrent);
                    cfg.fBlocks[cfg.fCurrent].fNodes.push_back({
                        BasicBlock::Node::kExpression_Kind,
                        constantPropagate,
                        e,
                        nullptr
                    });
                    break;
                }
                case Token::Kind::TK_EQ: {
                    this->addExpression(cfg, &b.fRight, constantPropagate);
                    this->addLValue(cfg, &b.fLeft);
                    cfg.fBlocks[cfg.fCurrent].fNodes.push_back({
                        BasicBlock::Node::kExpression_Kind,
                        constantPropagate,
                        e,
                        nullptr
                    });
                    break;
                }
                default:
                    this->addExpression(cfg, &b.fLeft, !Compiler::IsAssignment(b.fOperator));
                    this->addExpression(cfg, &b.fRight, constantPropagate);
                    cfg.fBlocks[cfg.fCurrent].fNodes.push_back({
                        BasicBlock::Node::kExpression_Kind,
                        constantPropagate,
                        e,
                        nullptr
                    });
            }
            break;
        }
        case Expression::Kind::kConstructor: {
            Constructor& c = e->get()->as<Constructor>();
            for (auto& arg : c.fArguments) {
                this->addExpression(cfg, &arg, constantPropagate);
            }
            cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kExpression_Kind,
                                                         constantPropagate, e, nullptr });
            break;
        }
        case Expression::Kind::kExternalFunctionCall: {
            ExternalFunctionCall& c = e->get()->as<ExternalFunctionCall>();
            for (auto& arg : c.fArguments) {
                this->addExpression(cfg, &arg, constantPropagate);
            }
            cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kExpression_Kind,
                                                         constantPropagate, e, nullptr });
            break;
        }
        case Expression::Kind::kFunctionCall: {
            FunctionCall& c = e->get()->as<FunctionCall>();
            for (auto& arg : c.fArguments) {
                this->addExpression(cfg, &arg, constantPropagate);
            }
            cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kExpression_Kind,
                                                         constantPropagate, e, nullptr });
            break;
        }
        case Expression::Kind::kFieldAccess: {
            this->addExpression(cfg, &e->get()->as<FieldAccess>().fBase, constantPropagate);
            cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kExpression_Kind,
                                                         constantPropagate, e, nullptr });
            break;
        }
        case Expression::Kind::kIndex: {
            IndexExpression& indexExpr = e->get()->as<IndexExpression>();

            this->addExpression(cfg, &indexExpr.fBase, constantPropagate);
            this->addExpression(cfg, &indexExpr.fIndex, constantPropagate);
            cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kExpression_Kind,
                                                         constantPropagate, e, nullptr });
            break;
        }
        case Expression::Kind::kPrefix: {
            PrefixExpression& p = e->get()->as<PrefixExpression>();
            this->addExpression(cfg, &p.fOperand, constantPropagate &&
                                                  p.fOperator != Token::Kind::TK_PLUSPLUS &&
                                                  p.fOperator != Token::Kind::TK_MINUSMINUS);
            cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kExpression_Kind,
                                                         constantPropagate, e, nullptr });
            break;
        }
        case Expression::Kind::kPostfix:
            this->addExpression(cfg, &e->get()->as<PostfixExpression>().fOperand, false);
            cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kExpression_Kind,
                                                         constantPropagate, e, nullptr });
            break;
        case Expression::Kind::kSwizzle:
            this->addExpression(cfg, &e->get()->as<Swizzle>().fBase, constantPropagate);
            cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kExpression_Kind,
                                                         constantPropagate, e, nullptr });
            break;
        case Expression::Kind::kBoolLiteral:   // fall through
        case Expression::Kind::kExternalValue: // fall through
        case Expression::Kind::kFloatLiteral:  // fall through
        case Expression::Kind::kIntLiteral:    // fall through
        case Expression::Kind::kNullLiteral:   // fall through
        case Expression::Kind::kSetting:       // fall through
        case Expression::Kind::kVariableReference:
            cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kExpression_Kind,
                                                         constantPropagate, e, nullptr });
            break;
        case Expression::Kind::kTernary: {
            TernaryExpression& t = e->get()->as<TernaryExpression>();
            this->addExpression(cfg, &t.fTest, constantPropagate);
            cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kExpression_Kind,
                                                         constantPropagate, e, nullptr });
            BlockId start = cfg.fCurrent;
            cfg.newBlock();
            this->addExpression(cfg, &t.fIfTrue, constantPropagate);
            BlockId next = cfg.newBlock();
            cfg.fCurrent = start;
            cfg.newBlock();
            this->addExpression(cfg, &t.fIfFalse, constantPropagate);
            cfg.addExit(cfg.fCurrent, next);
            cfg.fCurrent = next;
            break;
        }
        case Expression::Kind::kFunctionReference: // fall through
        case Expression::Kind::kTypeReference:     // fall through
        case Expression::Kind::kDefined:
            SkASSERT(false);
            break;
    }
}

// adds expressions that are evaluated as part of resolving an lvalue
void CFGGenerator::addLValue(CFG& cfg, std::unique_ptr<Expression>* e) {
    switch ((*e)->kind()) {
        case Expression::Kind::kFieldAccess:
            this->addLValue(cfg, &e->get()->as<FieldAccess>().fBase);
            break;
        case Expression::Kind::kIndex: {
            IndexExpression& indexExpr = e->get()->as<IndexExpression>();
            this->addLValue(cfg, &indexExpr.fBase);
            this->addExpression(cfg, &indexExpr.fIndex, /*constantPropagate=*/true);
            break;
        }
        case Expression::Kind::kSwizzle:
            this->addLValue(cfg, &e->get()->as<Swizzle>().fBase);
            break;
        case Expression::Kind::kExternalValue: // fall through
        case Expression::Kind::kVariableReference:
            break;
        case Expression::Kind::kTernary: {
            TernaryExpression& ternary = e->get()->as<TernaryExpression>();
            this->addExpression(cfg, &ternary.fTest, /*constantPropagate=*/true);
            // Technically we will of course only evaluate one or the other, but if the test turns
            // out to be constant, the ternary will get collapsed down to just one branch anyway. So
            // it should be ok to pretend that we always evaluate both branches here.
            this->addLValue(cfg, &ternary.fIfTrue);
            this->addLValue(cfg, &ternary.fIfFalse);
            break;
        }
        default:
            // not an lvalue, can't happen
            SkASSERT(false);
            break;
    }
}

static bool is_true(Expression& expr) {
    return expr.kind() == Expression::Kind::kBoolLiteral && expr.as<BoolLiteral>().fValue;
}

void CFGGenerator::addStatement(CFG& cfg, std::unique_ptr<Statement>* s) {
    switch ((*s)->kind()) {
        case Statement::Kind::kBlock:
            for (auto& child : (*s)->as<Block>().fStatements) {
                addStatement(cfg, &child);
            }
            break;
        case Statement::Kind::kIf: {
            IfStatement& ifs = (*s)->as<IfStatement>();
            this->addExpression(cfg, &ifs.fTest, /*constantPropagate=*/true);
            cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kStatement_Kind, false,
                                                         nullptr, s });
            BlockId start = cfg.fCurrent;
            cfg.newBlock();
            this->addStatement(cfg, &ifs.fIfTrue);
            BlockId next = cfg.newBlock();
            if (ifs.fIfFalse) {
                cfg.fCurrent = start;
                cfg.newBlock();
                this->addStatement(cfg, &ifs.fIfFalse);
                cfg.addExit(cfg.fCurrent, next);
                cfg.fCurrent = next;
            } else {
                cfg.addExit(start, next);
            }
            break;
        }
        case Statement::Kind::kExpression: {
            this->addExpression(cfg, &(*s)->as<ExpressionStatement>().fExpression,
                                /*constantPropagate=*/true);
            cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kStatement_Kind, false,
                                                         nullptr, s });
            break;
        }
        case Statement::Kind::kVarDeclarations: {
            VarDeclarationsStatement& decls = (*s)->as<VarDeclarationsStatement>();
            for (auto& stmt : decls.fDeclaration->fVars) {
                if (stmt->kind() == Statement::Kind::kNop) {
                    continue;
                }
                VarDeclaration& vd = stmt->as<VarDeclaration>();
                if (vd.fValue) {
                    this->addExpression(cfg, &vd.fValue, /*constantPropagate=*/true);
                }
                cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kStatement_Kind,
                                                             false, nullptr, &stmt });
            }
            cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kStatement_Kind, false,
                                                         nullptr, s });
            break;
        }
        case Statement::Kind::kDiscard:
            cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kStatement_Kind, false,
                                                         nullptr, s });
            cfg.fCurrent = cfg.newIsolatedBlock();
            break;
        case Statement::Kind::kReturn: {
            ReturnStatement& r = (*s)->as<ReturnStatement>();
            if (r.fExpression) {
                this->addExpression(cfg, &r.fExpression, /*constantPropagate=*/true);
            }
            cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kStatement_Kind, false,
                                                         nullptr, s });
            cfg.fCurrent = cfg.newIsolatedBlock();
            break;
        }
        case Statement::Kind::kBreak:
            cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kStatement_Kind, false,
                                                         nullptr, s });
            cfg.addExit(cfg.fCurrent, fLoopExits.top());
            cfg.fCurrent = cfg.newIsolatedBlock();
            break;
        case Statement::Kind::kContinue:
            cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kStatement_Kind, false,
                                                         nullptr, s });
            cfg.addExit(cfg.fCurrent, fLoopContinues.top());
            cfg.fCurrent = cfg.newIsolatedBlock();
            break;
        case Statement::Kind::kWhile: {
            WhileStatement& w = (*s)->as<WhileStatement>();
            BlockId loopStart = cfg.newBlock();
            fLoopContinues.push(loopStart);
            BlockId loopExit = cfg.newIsolatedBlock();
            fLoopExits.push(loopExit);
            this->addExpression(cfg, &w.fTest, /*constantPropagate=*/true);
            BlockId test = cfg.fCurrent;
            if (!is_true(*w.fTest)) {
                cfg.addExit(test, loopExit);
            }
            cfg.newBlock();
            this->addStatement(cfg, &w.fStatement);
            cfg.addExit(cfg.fCurrent, loopStart);
            fLoopContinues.pop();
            fLoopExits.pop();
            cfg.fCurrent = loopExit;
            break;
        }
        case Statement::Kind::kDo: {
            DoStatement& d = (*s)->as<DoStatement>();
            BlockId loopStart = cfg.newBlock();
            fLoopContinues.push(loopStart);
            BlockId loopExit = cfg.newIsolatedBlock();
            fLoopExits.push(loopExit);
            this->addStatement(cfg, &d.fStatement);
            this->addExpression(cfg, &d.fTest, /*constantPropagate=*/true);
            cfg.addExit(cfg.fCurrent, loopExit);
            cfg.addExit(cfg.fCurrent, loopStart);
            fLoopContinues.pop();
            fLoopExits.pop();
            cfg.fCurrent = loopExit;
            break;
        }
        case Statement::Kind::kFor: {
            ForStatement& f = (*s)->as<ForStatement>();
            if (f.fInitializer) {
                this->addStatement(cfg, &f.fInitializer);
            }
            BlockId loopStart = cfg.newBlock();
            BlockId next = cfg.newIsolatedBlock();
            fLoopContinues.push(next);
            BlockId loopExit = cfg.newIsolatedBlock();
            fLoopExits.push(loopExit);
            if (f.fTest) {
                this->addExpression(cfg, &f.fTest, /*constantPropagate=*/true);
                // this isn't quite right; we should have an exit from here to the loop exit, and
                // remove the exit from the loop body to the loop exit. Structuring it like this
                // forces the optimizer to believe that the loop body is always executed at least
                // once. While not strictly correct, this avoids incorrect "variable not assigned"
                // errors on variables which are assigned within the loop. The correct solution to
                // this is to analyze the loop to see whether or not at least one iteration is
                // guaranteed to happen, but for the time being we take the easy way out.
            }
            cfg.newBlock();
            this->addStatement(cfg, &f.fStatement);
            cfg.addExit(cfg.fCurrent, next);
            cfg.fCurrent = next;
            if (f.fNext) {
                this->addExpression(cfg, &f.fNext, /*constantPropagate=*/true);
            }
            cfg.addExit(cfg.fCurrent, loopStart);
            cfg.addExit(cfg.fCurrent, loopExit);
            fLoopContinues.pop();
            fLoopExits.pop();
            cfg.fCurrent = loopExit;
            break;
        }
        case Statement::Kind::kSwitch: {
            SwitchStatement& ss = (*s)->as<SwitchStatement>();
            this->addExpression(cfg, &ss.fValue, /*constantPropagate=*/true);
            cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kStatement_Kind, false,
                                                         nullptr, s });
            BlockId start = cfg.fCurrent;
            BlockId switchExit = cfg.newIsolatedBlock();
            fLoopExits.push(switchExit);
            for (const auto& c : ss.fCases) {
                cfg.newBlock();
                cfg.addExit(start, cfg.fCurrent);
                if (c->fValue) {
                    // technically this should go in the start block, but it doesn't actually matter
                    // because it must be constant. Not worth running two loops for.
                    this->addExpression(cfg, &c->fValue, /*constantPropagate=*/true);
                }
                for (auto& caseStatement : c->fStatements) {
                    this->addStatement(cfg, &caseStatement);
                }
            }
            cfg.addExit(cfg.fCurrent, switchExit);
            // note that unlike GLSL, our grammar requires the default case to be last
            if (0 == ss.fCases.size() || ss.fCases[ss.fCases.size() - 1]->fValue) {
                // switch does not have a default clause, mark that it can skip straight to the end
                cfg.addExit(start, switchExit);
            }
            fLoopExits.pop();
            cfg.fCurrent = switchExit;
            break;
        }
        case Statement::Kind::kInlineMarker:
        case Statement::Kind::kNop:
            break;
        default:
#ifdef SK_DEBUG
            ABORT("unsupported statement: %s\n", (*s)->description().c_str());
#endif
            break;
    }
}

CFG CFGGenerator::getCFG(FunctionDefinition& f) {
    CFG result;
    result.fStart = result.newBlock();
    result.fCurrent = result.fStart;
    this->addStatement(result, &f.fBody);
    result.newBlock();
    result.fExit = result.fCurrent;
    return result;
}

}  // namespace SkSL
