//
// Copyright 2002 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

// Analysis of the AST needed for HLSL generation

#include "compiler/translator/ASTMetadataHLSL.h"

#include "compiler/translator/CallDAG.h"
#include "compiler/translator/SymbolTable.h"
#include "compiler/translator/tree_util/IntermTraverse.h"

namespace sh
{

namespace
{

// Class used to traverse the AST of a function definition, checking if the
// function uses a gradient, and writing the set of control flow using gradients.
// It assumes that the analysis has already been made for the function's
// callees.
class PullGradient : public TIntermTraverser
{
  public:
    PullGradient(MetadataList *metadataList, size_t index, const CallDAG &dag)
        : TIntermTraverser(true, false, true),
          mMetadataList(metadataList),
          mMetadata(&(*metadataList)[index]),
          mIndex(index),
          mDag(dag)
    {
        ASSERT(index < metadataList->size());

        // ESSL 100 builtin gradient functions
        mGradientBuiltinFunctions.insert(ImmutableString("texture2D"));
        mGradientBuiltinFunctions.insert(ImmutableString("texture2DProj"));
        mGradientBuiltinFunctions.insert(ImmutableString("textureCube"));

        // ESSL 300 builtin gradient functions
        mGradientBuiltinFunctions.insert(ImmutableString("texture"));
        mGradientBuiltinFunctions.insert(ImmutableString("textureProj"));
        mGradientBuiltinFunctions.insert(ImmutableString("textureOffset"));
        mGradientBuiltinFunctions.insert(ImmutableString("textureProjOffset"));

        // ESSL 310 doesn't add builtin gradient functions
    }

    void traverse(TIntermFunctionDefinition *node)
    {
        node->traverse(this);
        ASSERT(mParents.empty());
    }

    // Called when a gradient operation or a call to a function using a gradient is found.
    void onGradient()
    {
        mMetadata->mUsesGradient = true;
        // Mark the latest control flow as using a gradient.
        if (!mParents.empty())
        {
            mMetadata->mControlFlowsContainingGradient.insert(mParents.back());
        }
    }

    void visitControlFlow(Visit visit, TIntermNode *node)
    {
        if (visit == PreVisit)
        {
            mParents.push_back(node);
        }
        else if (visit == PostVisit)
        {
            ASSERT(mParents.back() == node);
            mParents.pop_back();
            // A control flow's using a gradient means its parents are too.
            if (mMetadata->mControlFlowsContainingGradient.count(node) > 0 && !mParents.empty())
            {
                mMetadata->mControlFlowsContainingGradient.insert(mParents.back());
            }
        }
    }

    bool visitLoop(Visit visit, TIntermLoop *loop) override
    {
        visitControlFlow(visit, loop);
        return true;
    }

    bool visitIfElse(Visit visit, TIntermIfElse *ifElse) override
    {
        visitControlFlow(visit, ifElse);
        return true;
    }

    bool visitUnary(Visit visit, TIntermUnary *node) override
    {
        if (visit == PreVisit)
        {
            switch (node->getOp())
            {
                case EOpDFdx:
                case EOpDFdy:
                case EOpFwidth:
                    onGradient();
                    break;
                default:
                    break;
            }
        }

        return true;
    }

    bool visitAggregate(Visit visit, TIntermAggregate *node) override
    {
        if (visit == PreVisit)
        {
            if (node->getOp() == EOpCallFunctionInAST)
            {
                size_t calleeIndex = mDag.findIndex(node->getFunction()->uniqueId());
                ASSERT(calleeIndex != CallDAG::InvalidIndex && calleeIndex < mIndex);

                if ((*mMetadataList)[calleeIndex].mUsesGradient)
                {
                    onGradient();
                }
            }
            else if (node->getOp() == EOpCallBuiltInFunction)
            {
                if (mGradientBuiltinFunctions.find(node->getFunction()->name()) !=
                    mGradientBuiltinFunctions.end())
                {
                    onGradient();
                }
            }
        }

        return true;
    }

  private:
    MetadataList *mMetadataList;
    ASTMetadataHLSL *mMetadata;
    size_t mIndex;
    const CallDAG &mDag;

    // Contains a stack of the control flow nodes that are parents of the node being
    // currently visited. It is used to mark control flows using a gradient.
    std::vector<TIntermNode *> mParents;

    // A list of builtin functions that use gradients
    std::set<ImmutableString> mGradientBuiltinFunctions;
};

// Traverses the AST of a function definition to compute the the discontinuous loops
// and the if statements containing gradient loops. It assumes that the gradient loops
// (loops that contain a gradient) have already been computed and that it has already
// traversed the current function's callees.
class PullComputeDiscontinuousAndGradientLoops : public TIntermTraverser
{
  public:
    PullComputeDiscontinuousAndGradientLoops(MetadataList *metadataList,
                                             size_t index,
                                             const CallDAG &dag)
        : TIntermTraverser(true, false, true),
          mMetadataList(metadataList),
          mMetadata(&(*metadataList)[index]),
          mIndex(index),
          mDag(dag)
    {}

    void traverse(TIntermFunctionDefinition *node)
    {
        node->traverse(this);
        ASSERT(mLoopsAndSwitches.empty());
        ASSERT(mIfs.empty());
    }

    // Called when traversing a gradient loop or a call to a function with a
    // gradient loop in its call graph.
    void onGradientLoop()
    {
        mMetadata->mHasGradientLoopInCallGraph = true;
        // Mark the latest if as using a discontinuous loop.
        if (!mIfs.empty())
        {
            mMetadata->mIfsContainingGradientLoop.insert(mIfs.back());
        }
    }

    bool visitLoop(Visit visit, TIntermLoop *loop) override
    {
        if (visit == PreVisit)
        {
            mLoopsAndSwitches.push_back(loop);

            if (mMetadata->hasGradientInCallGraph(loop))
            {
                onGradientLoop();
            }
        }
        else if (visit == PostVisit)
        {
            ASSERT(mLoopsAndSwitches.back() == loop);
            mLoopsAndSwitches.pop_back();
        }

        return true;
    }

    bool visitIfElse(Visit visit, TIntermIfElse *node) override
    {
        if (visit == PreVisit)
        {
            mIfs.push_back(node);
        }
        else if (visit == PostVisit)
        {
            ASSERT(mIfs.back() == node);
            mIfs.pop_back();
            // An if using a discontinuous loop means its parents ifs are also discontinuous.
            if (mMetadata->mIfsContainingGradientLoop.count(node) > 0 && !mIfs.empty())
            {
                mMetadata->mIfsContainingGradientLoop.insert(mIfs.back());
            }
        }

        return true;
    }

    bool visitBranch(Visit visit, TIntermBranch *node) override
    {
        if (visit == PreVisit)
        {
            switch (node->getFlowOp())
            {
                case EOpBreak:
                {
                    ASSERT(!mLoopsAndSwitches.empty());
                    TIntermLoop *loop = mLoopsAndSwitches.back()->getAsLoopNode();
                    if (loop != nullptr)
                    {
                        mMetadata->mDiscontinuousLoops.insert(loop);
                    }
                }
                break;
                case EOpContinue:
                {
                    ASSERT(!mLoopsAndSwitches.empty());
                    TIntermLoop *loop = nullptr;
                    size_t i          = mLoopsAndSwitches.size();
                    while (loop == nullptr && i > 0)
                    {
                        --i;
                        loop = mLoopsAndSwitches.at(i)->getAsLoopNode();
                    }
                    ASSERT(loop != nullptr);
                    mMetadata->mDiscontinuousLoops.insert(loop);
                }
                break;
                case EOpKill:
                case EOpReturn:
                    // A return or discard jumps out of all the enclosing loops
                    if (!mLoopsAndSwitches.empty())
                    {
                        for (TIntermNode *intermNode : mLoopsAndSwitches)
                        {
                            TIntermLoop *loop = intermNode->getAsLoopNode();
                            if (loop)
                            {
                                mMetadata->mDiscontinuousLoops.insert(loop);
                            }
                        }
                    }
                    break;
                default:
                    UNREACHABLE();
            }
        }

        return true;
    }

    bool visitAggregate(Visit visit, TIntermAggregate *node) override
    {
        if (visit == PreVisit && node->getOp() == EOpCallFunctionInAST)
        {
            size_t calleeIndex = mDag.findIndex(node->getFunction()->uniqueId());
            ASSERT(calleeIndex != CallDAG::InvalidIndex && calleeIndex < mIndex);

            if ((*mMetadataList)[calleeIndex].mHasGradientLoopInCallGraph)
            {
                onGradientLoop();
            }
        }

        return true;
    }

    bool visitSwitch(Visit visit, TIntermSwitch *node) override
    {
        if (visit == PreVisit)
        {
            mLoopsAndSwitches.push_back(node);
        }
        else if (visit == PostVisit)
        {
            ASSERT(mLoopsAndSwitches.back() == node);
            mLoopsAndSwitches.pop_back();
        }
        return true;
    }

  private:
    MetadataList *mMetadataList;
    ASTMetadataHLSL *mMetadata;
    size_t mIndex;
    const CallDAG &mDag;

    std::vector<TIntermNode *> mLoopsAndSwitches;
    std::vector<TIntermIfElse *> mIfs;
};

// Tags all the functions called in a discontinuous loop
class PushDiscontinuousLoops : public TIntermTraverser
{
  public:
    PushDiscontinuousLoops(MetadataList *metadataList, size_t index, const CallDAG &dag)
        : TIntermTraverser(true, true, true),
          mMetadataList(metadataList),
          mMetadata(&(*metadataList)[index]),
          mIndex(index),
          mDag(dag),
          mNestedDiscont(mMetadata->mCalledInDiscontinuousLoop ? 1 : 0)
    {}

    void traverse(TIntermFunctionDefinition *node)
    {
        node->traverse(this);
        ASSERT(mNestedDiscont == (mMetadata->mCalledInDiscontinuousLoop ? 1 : 0));
    }

    bool visitLoop(Visit visit, TIntermLoop *loop) override
    {
        bool isDiscontinuous = mMetadata->mDiscontinuousLoops.count(loop) > 0;

        if (visit == PreVisit && isDiscontinuous)
        {
            mNestedDiscont++;
        }
        else if (visit == PostVisit && isDiscontinuous)
        {
            mNestedDiscont--;
        }

        return true;
    }

    bool visitAggregate(Visit visit, TIntermAggregate *node) override
    {
        switch (node->getOp())
        {
            case EOpCallFunctionInAST:
                if (visit == PreVisit && mNestedDiscont > 0)
                {
                    size_t calleeIndex = mDag.findIndex(node->getFunction()->uniqueId());
                    ASSERT(calleeIndex != CallDAG::InvalidIndex && calleeIndex < mIndex);

                    (*mMetadataList)[calleeIndex].mCalledInDiscontinuousLoop = true;
                }
                break;
            default:
                break;
        }
        return true;
    }

  private:
    MetadataList *mMetadataList;
    ASTMetadataHLSL *mMetadata;
    size_t mIndex;
    const CallDAG &mDag;

    int mNestedDiscont;
};
}  // namespace

bool ASTMetadataHLSL::hasGradientInCallGraph(TIntermLoop *node)
{
    return mControlFlowsContainingGradient.count(node) > 0;
}

bool ASTMetadataHLSL::hasGradientLoop(TIntermIfElse *node)
{
    return mIfsContainingGradientLoop.count(node) > 0;
}

MetadataList CreateASTMetadataHLSL(TIntermNode *root, const CallDAG &callDag)
{
    MetadataList metadataList(callDag.size());

    // Compute all the information related to when gradient operations are used.
    // We want to know for each function and control flow operation if they have
    // a gradient operation in their call graph (shortened to "using a gradient"
    // in the rest of the file).
    //
    // This computation is logically split in three steps:
    //  1 - For each function compute if it uses a gradient in its body, ignoring
    // calls to other user-defined functions.
    //  2 - For each function determine if it uses a gradient in its call graph,
    // using the result of step 1 and the CallDAG to know its callees.
    //  3 - For each control flow statement of each function, check if it uses a
    // gradient in the function's body, or if it calls a user-defined function that
    // uses a gradient.
    //
    // We take advantage of the call graph being a DAG and instead compute 1, 2 and 3
    // for leaves first, then going down the tree. This is correct because 1 doesn't
    // depend on other functions, and 2 and 3 depend only on callees.
    for (size_t i = 0; i < callDag.size(); i++)
    {
        PullGradient pull(&metadataList, i, callDag);
        pull.traverse(callDag.getRecordFromIndex(i).node);
    }

    // Compute which loops are discontinuous and which function are called in
    // these loops. The same way computing gradient usage is a "pull" process,
    // computing "bing used in a discont. loop" is a push process. However we also
    // need to know what ifs have a discontinuous loop inside so we do the same type
    // of callgraph analysis as for the gradient.

    // First compute which loops are discontinuous (no specific order) and pull
    // the ifs and functions using a gradient loop.
    for (size_t i = 0; i < callDag.size(); i++)
    {
        PullComputeDiscontinuousAndGradientLoops pull(&metadataList, i, callDag);
        pull.traverse(callDag.getRecordFromIndex(i).node);
    }

    // Then push the information to callees, either from the a local discontinuous
    // loop or from the caller being called in a discontinuous loop already
    for (size_t i = callDag.size(); i-- > 0;)
    {
        PushDiscontinuousLoops push(&metadataList, i, callDag);
        push.traverse(callDag.getRecordFromIndex(i).node);
    }

    // We create "Lod0" version of functions with the gradient operations replaced
    // by non-gradient operations so that the D3D compiler is happier with discont
    // loops.
    for (auto &metadata : metadataList)
    {
        metadata.mNeedsLod0 = metadata.mCalledInDiscontinuousLoop && metadata.mUsesGradient;
    }

    return metadataList;
}

}  // namespace sh
