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

#include "src/sksl/SkSLAnalysis.h"

#include "include/private/SkSLSampleMatrix.h"
#include "src/sksl/ir/SkSLExpression.h"
#include "src/sksl/ir/SkSLProgram.h"
#include "src/sksl/ir/SkSLProgramElement.h"
#include "src/sksl/ir/SkSLStatement.h"

// ProgramElements
#include "src/sksl/ir/SkSLEnum.h"
#include "src/sksl/ir/SkSLExtension.h"
#include "src/sksl/ir/SkSLFunctionDefinition.h"
#include "src/sksl/ir/SkSLInterfaceBlock.h"
#include "src/sksl/ir/SkSLModifiers.h"
#include "src/sksl/ir/SkSLSection.h"
#include "src/sksl/ir/SkSLVarDeclarations.h"

// Statements
#include "src/sksl/ir/SkSLBlock.h"
#include "src/sksl/ir/SkSLBreakStatement.h"
#include "src/sksl/ir/SkSLContinueStatement.h"
#include "src/sksl/ir/SkSLDiscardStatement.h"
#include "src/sksl/ir/SkSLDoStatement.h"
#include "src/sksl/ir/SkSLExpressionStatement.h"
#include "src/sksl/ir/SkSLForStatement.h"
#include "src/sksl/ir/SkSLIfStatement.h"
#include "src/sksl/ir/SkSLNop.h"
#include "src/sksl/ir/SkSLReturnStatement.h"
#include "src/sksl/ir/SkSLSwitchStatement.h"
#include "src/sksl/ir/SkSLVarDeclarationsStatement.h"
#include "src/sksl/ir/SkSLWhileStatement.h"

// Expressions
#include "src/sksl/ir/SkSLBinaryExpression.h"
#include "src/sksl/ir/SkSLBoolLiteral.h"
#include "src/sksl/ir/SkSLConstructor.h"
#include "src/sksl/ir/SkSLExternalFunctionCall.h"
#include "src/sksl/ir/SkSLExternalValueReference.h"
#include "src/sksl/ir/SkSLFieldAccess.h"
#include "src/sksl/ir/SkSLFloatLiteral.h"
#include "src/sksl/ir/SkSLFunctionCall.h"
#include "src/sksl/ir/SkSLFunctionReference.h"
#include "src/sksl/ir/SkSLIndexExpression.h"
#include "src/sksl/ir/SkSLIntLiteral.h"
#include "src/sksl/ir/SkSLNullLiteral.h"
#include "src/sksl/ir/SkSLPostfixExpression.h"
#include "src/sksl/ir/SkSLPrefixExpression.h"
#include "src/sksl/ir/SkSLSetting.h"
#include "src/sksl/ir/SkSLSwizzle.h"
#include "src/sksl/ir/SkSLTernaryExpression.h"
#include "src/sksl/ir/SkSLTypeReference.h"
#include "src/sksl/ir/SkSLVariableReference.h"

namespace SkSL {

namespace {

static bool is_sample_call_to_fp(const FunctionCall& fc, const Variable& fp) {
    const FunctionDeclaration& f = fc.fFunction;
    return f.fBuiltin && f.fName == "sample" && fc.fArguments.size() >= 1 &&
            fc.fArguments[0]->fKind == Expression::kVariableReference_Kind &&
            &((VariableReference&) *fc.fArguments[0]).fVariable == &fp;
}

// Visitor that determines the merged SampleMatrix for a given child 'fp' in the program.
class MergeSampleMatrixVisitor : public ProgramVisitor {
public:
    MergeSampleMatrixVisitor(const Variable& fp) : fFP(fp) {}

    SampleMatrix visit(const Program& program) {
        fMatrix = SampleMatrix(); // reset to none
        this->INHERITED::visit(program);
        return fMatrix;
    }

protected:
    const Variable& fFP;
    SampleMatrix fMatrix;

    bool visitExpression(const Expression& e) override {
        // Looking for sample(fp, inColor?, float3x3)
        if (e.fKind == Expression::kFunctionCall_Kind) {
            const FunctionCall& fc = (const FunctionCall&) e;
            if (is_sample_call_to_fp(fc, fFP) && fc.fArguments.size() >= 2 &&
                fc.fArguments.back()->fType == *this->program().fContext->fFloat3x3_Type) {
                // Determine the type of matrix for this call site, then merge it with the
                // previously accumulated matrix state.
                if (fc.fArguments.back()->isConstantOrUniform()) {
                    if (fc.fArguments.back()->fKind == Expression::Kind::kVariableReference_Kind ||
                        fc.fArguments.back()->fKind == Expression::Kind::kConstructor_Kind) {
                        // FIXME if this is a constant, we should parse the float3x3 constructor and
                        // determine if the resulting matrix introduces perspective.
                        fMatrix.merge(SampleMatrix::MakeConstUniform(
                                fc.fArguments.back()->description()));
                    } else {
                        // FIXME this is really to workaround a restriction of the downstream code
                        // that relies on the SampleMatrix's fExpression to identify uniform names.
                        // Once they are tracked separately, any constant/uniform expression can
                        // work, but right now this avoids issues from '0.5 * matrix' that is both
                        // a constant AND a uniform.
                        fMatrix.merge(SampleMatrix::MakeVariable());
                    }
                } else {
                    fMatrix.merge(SampleMatrix::MakeVariable());
                }
                // NOTE: we don't return true here just because we found a sample matrix usage,
                // we need to process the entire program and merge across all encountered calls.
            }
        }

        return this->INHERITED::visitExpression(e);
    }

    typedef ProgramVisitor INHERITED;
};

// Visitor that searches a program for sample() calls with the given 'fp' as the argument
// and returns true if explicit float2 coords were passed to that call site.
class ExplicitCoordsVisitor : public ProgramVisitor {
public:
    ExplicitCoordsVisitor(const Variable& fp) : fFP(fp) {}

protected:
    bool visitExpression(const Expression& e) override {
        // Looking for sample(fp, inColor?, float2)
        if (e.fKind == Expression::kFunctionCall_Kind) {
            const FunctionCall& fc = (const FunctionCall&) e;
            if (is_sample_call_to_fp(fc, fFP) && fc.fArguments.size() >= 2 &&
                fc.fArguments.back()->fType == *this->program().fContext->fFloat2_Type) {
                return true;
            }
        }
        return this->INHERITED::visitExpression(e);
    }

    const Variable& fFP;

    typedef ProgramVisitor INHERITED;
};

// Visitor that searches through a main function of the program for reference to the
// sample coordinates provided by the parent FP or main program.
class SampleCoordsVisitor : public ProgramVisitor {
protected:
    // Only bother recursing through the main function for the sample coord builtin
    bool visitProgramElement(const ProgramElement& pe) override {
        if (pe.fKind == ProgramElement::kFunction_Kind) {
            // Both kFragmentProcessor and kPipelineStage types use the first argument for
            // the main coords builtin. If that isn't in the signature, there's no need to
            // recurse deeper.
            const FunctionDeclaration& func = ((const FunctionDefinition&) pe).fDeclaration;
            if (func.fName == "main" && func.fParameters.size() >= 1 &&
                func.fParameters.front()->fType == *this->program().fContext->fFloat2_Type) {
                return this->INHERITED::visitProgramElement(pe);
            }
        }
        // No recursion, but returning false will allow visitor to continue to siblings
        return false;
    }

    bool visitExpression(const Expression& e) override {
        if (e.fKind == Expression::kVariableReference_Kind) {
            const VariableReference& var = (const VariableReference&) e;
            return var.fVariable.fModifiers.fLayout.fBuiltin == SK_MAIN_COORDS_BUILTIN;
        }
        return this->INHERITED::visitExpression(e);
    }

    typedef ProgramVisitor INHERITED;
};

}

////////////////////////////////////////////////////////////////////////////////
// Analysis

SampleMatrix Analysis::GetSampleMatrix(const Program& program, const Variable& fp) {
    MergeSampleMatrixVisitor visitor(fp);
    return visitor.visit(program);
}

bool Analysis::IsExplicitlySampled(const Program& program, const Variable& fp) {
    ExplicitCoordsVisitor visitor(fp);
    return visitor.visit(program);
}

bool Analysis::ReferencesSampleCoords(const Program& program) {
    SampleCoordsVisitor visitor;
    return visitor.visit(program);
}

////////////////////////////////////////////////////////////////////////////////
// ProgramVisitor

bool ProgramVisitor::visit(const Program& program) {
    fProgram = &program;
    bool result = false;
    for (const auto& pe : program) {
        if (this->visitProgramElement(pe)) {
            result = true;
            break;
        }
    }
    fProgram = nullptr;
    return result;
}

bool ProgramVisitor::visitExpression(const Expression& e) {
    switch(e.fKind) {
        case Expression::kBoolLiteral_Kind:
        case Expression::kDefined_Kind:
        case Expression::kExternalValue_Kind:
        case Expression::kFieldAccess_Kind:
        case Expression::kFloatLiteral_Kind:
        case Expression::kFunctionReference_Kind:
        case Expression::kIntLiteral_Kind:
        case Expression::kNullLiteral_Kind:
        case Expression::kSetting_Kind:
        case Expression::kTypeReference_Kind:
        case Expression::kVariableReference_Kind:
            // Leaf expressions return false
            return false;
        case Expression::kBinary_Kind: {
            const BinaryExpression& b = (const BinaryExpression&) e;
            return this->visitExpression(*b.fLeft) || this->visitExpression(*b.fRight); }
        case Expression::kConstructor_Kind: {
            const Constructor& c = (const Constructor&) e;
            for (const auto& arg : c.fArguments) {
                if (this->visitExpression(*arg)) { return true; }
            }
            return false; }
        case Expression::kExternalFunctionCall_Kind: {
            const ExternalFunctionCall& c = (const ExternalFunctionCall&) e;
            for (const auto& arg : c.fArguments) {
                if (this->visitExpression(*arg)) { return true; }
            }
            return false; }
        case Expression::kFunctionCall_Kind: {
            const FunctionCall& c = (const FunctionCall&) e;
            for (const auto& arg : c.fArguments) {
                if (this->visitExpression(*arg)) { return true; }
            }
            return false; }
        case Expression::kIndex_Kind:{
            const IndexExpression& i = (const IndexExpression&) e;
            return this->visitExpression(*i.fBase) || this->visitExpression(*i.fIndex); }
        case Expression::kPostfix_Kind:
            return this->visitExpression(*((const PostfixExpression&) e).fOperand);
        case Expression::kPrefix_Kind:
            return this->visitExpression(*((const PrefixExpression&) e).fOperand);
        case Expression::kSwizzle_Kind:
            return this->visitExpression(*((const Swizzle&) e).fBase);
        case Expression::kTernary_Kind: {
            const TernaryExpression& t = (const TernaryExpression&) e;
            return this->visitExpression(*t.fTest) ||
                   this->visitExpression(*t.fIfTrue) ||
                   this->visitExpression(*t.fIfFalse); }
        default:
            SkUNREACHABLE;
    }
}

bool ProgramVisitor::visitStatement(const Statement& s) {
    switch(s.fKind) {
        case Statement::kBreak_Kind:
        case Statement::kContinue_Kind:
        case Statement::kDiscard_Kind:
        case Statement::kNop_Kind:
            // Leaf statements just return false
            return false;
        case Statement::kBlock_Kind:
            for (const auto& s : ((const Block&) s).fStatements) {
                if (this->visitStatement(*s)) { return true; }
            }
            return false;
        case Statement::kDo_Kind: {
            const DoStatement& d = (const DoStatement&) s;
            return this->visitExpression(*d.fTest) || this->visitStatement(*d.fStatement); }
        case Statement::kExpression_Kind:
            return this->visitExpression(*((const ExpressionStatement&) s).fExpression);
        case Statement::kFor_Kind: {
            const ForStatement& f = (const ForStatement&) s;
            return (f.fInitializer && this->visitStatement(*f.fInitializer)) ||
                   (f.fInitializer && this->visitExpression(*f.fTest)) ||
                   (f.fNext && this->visitExpression(*f.fNext)) ||
                   this->visitStatement(*f.fStatement); }
        case Statement::kIf_Kind: {
            const IfStatement& i = (const IfStatement&) s;
            return this->visitExpression(*i.fTest) ||
                   this->visitStatement(*i.fIfTrue) ||
                   (i.fIfFalse && this->visitStatement(*i.fIfFalse)); }
        case Statement::kReturn_Kind: {
            const ReturnStatement& r = (const ReturnStatement&) s;
            return r.fExpression && this->visitExpression(*r.fExpression); }
        case Statement::kSwitch_Kind: {
            const SwitchStatement& sw = (const SwitchStatement&) s;
            if (this->visitExpression(*sw.fValue)) { return true; }
            for (const auto& c : sw.fCases) {
                if (c->fValue && this->visitExpression(*c->fValue)) { return true; }
                for (const auto& st : c->fStatements) {
                    if (this->visitStatement(*st)) { return true; }
                }
            }
            return false; }
        case Statement::kVarDeclaration_Kind: {
            const VarDeclaration& v = (const VarDeclaration&) s;
            for (const auto& s : v.fSizes) {
                if (this->visitExpression(*s)) { return true; }
            }
            return v.fValue && this->visitExpression(*v.fValue); }
        case Statement::kVarDeclarations_Kind: {
            // Technically this statement points to a program element, but it's convenient
            // to have program element > statement > expression, so visit the declaration elements
            // directly without going up to visitProgramElement.
            const VarDeclarations& vars = *((const VarDeclarationsStatement&) s).fDeclaration;
            for (const auto& v : vars.fVars) {
                if (this->visitStatement(*v)) { return true; }
            }
            return false;
        }
        case Statement::kWhile_Kind: {
            const WhileStatement& w = (const WhileStatement&) s;
            return this->visitExpression(*w.fTest) || this->visitStatement(*w.fStatement); }
        default:
            SkUNREACHABLE;
    }
}

bool ProgramVisitor::visitProgramElement(const ProgramElement& pe) {
    switch(pe.fKind) {
        case ProgramElement::kEnum_Kind:
        case ProgramElement::kExtension_Kind:
        case ProgramElement::kModifiers_Kind:
        case ProgramElement::kSection_Kind:
            // Leaf program elements just return false by default
            return false;
        case ProgramElement::kFunction_Kind:
            return this->visitStatement(*((const FunctionDefinition&) pe).fBody);
        case ProgramElement::kInterfaceBlock_Kind:
            for (const auto& e : ((const InterfaceBlock&) pe).fSizes) {
                if (this->visitExpression(*e)) { return true; }
            }
            return false;
        case ProgramElement::kVar_Kind:
            for (const auto& v : ((const VarDeclarations&) pe).fVars) {
                if (this->visitStatement(*v)) { return true; }
            }
            return false;
        default:
            SkUNREACHABLE;
    }
}

}
