//
// Copyright (c) 2018 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.
//
// Implementation of the function RewriteAtomicFunctionExpressions.
// See the header for more details.

#include "RewriteAtomicFunctionExpressions.h"

#include "compiler/translator/tree_util/IntermNodePatternMatcher.h"
#include "compiler/translator/tree_util/IntermNode_util.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
#include "compiler/translator/util.h"

namespace sh
{
namespace
{
// Traverser that simplifies all the atomic function expressions into the ones that can be directly
// translated into HLSL.
//
// case 1 (only for atomicExchange and atomicCompSwap):
//  original:
//      atomicExchange(counter, newValue);
//  new:
//      tempValue = atomicExchange(counter, newValue);
//
// case 2 (atomic function, temporary variable required):
//  original:
//      value = atomicAdd(counter, 1) * otherValue;
//      someArray[atomicAdd(counter, 1)] = someOtherValue;
//  new:
//      value = ((tempValue = atomicAdd(counter, 1)), tempValue) * otherValue;
//      someArray[((tempValue = atomicAdd(counter, 1)), tempValue)] = someOtherValue;
//
// case 3 (atomic function used directly initialize a variable):
//  original:
//      int value = atomicAdd(counter, 1);
//  new:
//      tempValue = atomicAdd(counter, 1);
//      int value = tempValue;
//
class RewriteAtomicFunctionExpressionsTraverser : public TIntermTraverser
{
  public:
    RewriteAtomicFunctionExpressionsTraverser(TSymbolTable *symbolTable, int shaderVersion);

    bool visitAggregate(Visit visit, TIntermAggregate *node) override;
    bool visitBlock(Visit visit, TIntermBlock *node) override;

  private:
    static bool IsAtomicExchangeOrCompSwapNoReturnValue(TIntermAggregate *node,
                                                        TIntermNode *parentNode);
    static bool IsAtomicFunctionInsideExpression(TIntermAggregate *node, TIntermNode *parentNode);

    void rewriteAtomicFunctionCallNode(TIntermAggregate *oldAtomicFunctionNode);

    const TVariable *getTempVariable(const TType *type);

    int mShaderVersion;
    TIntermSequence mTempVariables;
};

RewriteAtomicFunctionExpressionsTraverser::RewriteAtomicFunctionExpressionsTraverser(
    TSymbolTable *symbolTable,
    int shaderVersion)
    : TIntermTraverser(false, false, true, symbolTable), mShaderVersion(shaderVersion)
{}

void RewriteAtomicFunctionExpressionsTraverser::rewriteAtomicFunctionCallNode(
    TIntermAggregate *oldAtomicFunctionNode)
{
    ASSERT(oldAtomicFunctionNode);

    const TVariable *returnVariable = getTempVariable(&oldAtomicFunctionNode->getType());

    TIntermBinary *rewrittenNode = new TIntermBinary(
        TOperator::EOpAssign, CreateTempSymbolNode(returnVariable), oldAtomicFunctionNode);

    auto *parentNode = getParentNode();

    auto *parentBinary = parentNode->getAsBinaryNode();
    if (parentBinary && parentBinary->getOp() == EOpInitialize)
    {
        insertStatementInParentBlock(rewrittenNode);
        queueReplacement(CreateTempSymbolNode(returnVariable), OriginalNode::IS_DROPPED);
    }
    else
    {
        // As all atomic function assignment will be converted to the last argument of an
        // interlocked function, if we need the return value, assignment needs to be wrapped with
        // the comma operator and the temporary variables.
        if (!parentNode->getAsBlock())
        {
            rewrittenNode = TIntermBinary::CreateComma(
                rewrittenNode, new TIntermSymbol(returnVariable), mShaderVersion);
        }

        queueReplacement(rewrittenNode, OriginalNode::IS_DROPPED);
    }
}

const TVariable *RewriteAtomicFunctionExpressionsTraverser::getTempVariable(const TType *type)
{
    TIntermDeclaration *variableDeclaration;
    TVariable *returnVariable =
        DeclareTempVariable(mSymbolTable, type, EvqTemporary, &variableDeclaration);
    mTempVariables.push_back(variableDeclaration);
    return returnVariable;
}

bool RewriteAtomicFunctionExpressionsTraverser::IsAtomicExchangeOrCompSwapNoReturnValue(
    TIntermAggregate *node,
    TIntermNode *parentNode)
{
    ASSERT(node);
    return (node->getOp() == EOpAtomicExchange || node->getOp() == EOpAtomicCompSwap) &&
           parentNode && parentNode->getAsBlock();
}

bool RewriteAtomicFunctionExpressionsTraverser::IsAtomicFunctionInsideExpression(
    TIntermAggregate *node,
    TIntermNode *parentNode)
{
    ASSERT(node);
    // We only need to handle atomic functions with a parent that it is not block nodes. If the
    // parent node is block, it means that the atomic function is not inside an expression.
    if (!IsAtomicFunction(node->getOp()) || parentNode->getAsBlock())
    {
        return false;
    }

    auto *parentAsBinary = parentNode->getAsBinaryNode();
    // Assignments are handled in OutputHLSL
    return !parentAsBinary || parentAsBinary->getOp() != EOpAssign;
}

bool RewriteAtomicFunctionExpressionsTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
{
    ASSERT(visit == PostVisit);
    // Skip atomic memory functions for SSBO. They will be processed in the OutputHLSL traverser.
    if (IsAtomicFunction(node->getOp()) &&
        IsInShaderStorageBlock((*node->getSequence())[0]->getAsTyped()))
    {
        return false;
    }

    TIntermNode *parentNode = getParentNode();
    if (IsAtomicExchangeOrCompSwapNoReturnValue(node, parentNode) ||
        IsAtomicFunctionInsideExpression(node, parentNode))
    {
        rewriteAtomicFunctionCallNode(node);
    }

    return true;
}

bool RewriteAtomicFunctionExpressionsTraverser::visitBlock(Visit visit, TIntermBlock *node)
{
    ASSERT(visit == PostVisit);

    if (!mTempVariables.empty() && getParentNode()->getAsFunctionDefinition())
    {
        insertStatementsInBlockAtPosition(node, 0, mTempVariables, TIntermSequence());
        mTempVariables.clear();
    }

    return true;
}

}  // anonymous namespace

void RewriteAtomicFunctionExpressions(TIntermNode *root,
                                      TSymbolTable *symbolTable,
                                      int shaderVersion)
{
    RewriteAtomicFunctionExpressionsTraverser traverser(symbolTable, shaderVersion);
    traverser.traverse(root);
    traverser.updateTree();
}
}  // namespace sh