//
// Copyright 2019 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.
//
// NameNamelessUniformBuffers: Gives nameless uniform buffer variables internal names.
//

#include "compiler/translator/tree_ops/NameNamelessUniformBuffers.h"

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

namespace sh
{
namespace
{
// Traverse uniform buffer declarations and give name to nameless declarations.  Keeps track of
// the interface fields which will be used in the source without the interface block variable name
// and replaces them with name.field.
class NameUniformBufferVariablesTraverser : public TIntermTraverser
{
  public:
    explicit NameUniformBufferVariablesTraverser(TSymbolTable *symbolTable)
        : TIntermTraverser(true, false, false, symbolTable)
    {}

    bool visitDeclaration(Visit visit, TIntermDeclaration *decl) override
    {
        ASSERT(visit == PreVisit);

        const TIntermSequence &sequence = *(decl->getSequence());

        TIntermTyped *variableNode = sequence.front()->getAsTyped();
        const TType &type          = variableNode->getType();

        // If it's an interface block, it may have to be converted if it contains any row-major
        // fields.
        if (!type.isInterfaceBlock())
        {
            return true;
        }

        // Multi declaration statements are already separated, so there can only be one variable
        // here.
        ASSERT(sequence.size() == 1);
        const TVariable *variable = &variableNode->getAsSymbolNode()->variable();
        if (variable->symbolType() != SymbolType::Empty)
        {
            return false;
        }

        TIntermDeclaration *newDeclaration = new TIntermDeclaration;
        TVariable *newVariable = new TVariable(mSymbolTable, kEmptyImmutableString, &type,
                                               SymbolType::AngleInternal, variable->extension());
        newDeclaration->appendDeclarator(new TIntermSymbol(newVariable));

        queueReplacement(newDeclaration, OriginalNode::IS_DROPPED);

        // It's safe to key the map with the interface block, as there couldn't have been multiple
        // declarations with this interface block (as the variable is nameless), so for nameless
        // uniform buffers, the interface block is unique.
        mNamelessUniformBuffersMap[type.getInterfaceBlock()] = newVariable;

        return false;
    }

    void visitSymbol(TIntermSymbol *symbol) override
    {
        const TType &type = symbol->getType();

        // The symbols we are looking for have the interface block pointer set, but are not
        // interface blocks.  These are references to fields of nameless uniform buffers.
        if (type.isInterfaceBlock() || type.getInterfaceBlock() == nullptr)
        {
            return;
        }

        const TInterfaceBlock *block = type.getInterfaceBlock();

        // If block variable is not nameless, there's nothing to do.
        if (mNamelessUniformBuffersMap.count(block) == 0)
        {
            return;
        }

        const ImmutableString symbolName = symbol->getName();

        // Find which field it is
        const TVector<TField *> fields = block->fields();
        for (size_t fieldIndex = 0; fieldIndex < fields.size(); ++fieldIndex)
        {
            const TField *field = fields[fieldIndex];
            if (field->name() != symbolName)
            {
                continue;
            }

            // Replace this node with a binary node that indexes the named uniform buffer.
            TIntermSymbol *namedUniformBuffer =
                new TIntermSymbol(mNamelessUniformBuffersMap[block]);
            TIntermBinary *replacement =
                new TIntermBinary(EOpIndexDirectInterfaceBlock, namedUniformBuffer,
                                  CreateIndexNode(static_cast<uint32_t>(fieldIndex)));

            queueReplacement(replacement, OriginalNode::IS_DROPPED);

            return;
        }

        UNREACHABLE();
    }

  private:
    // A map from nameless uniform buffers to their named replacements.
    std::unordered_map<const TInterfaceBlock *, const TVariable *> mNamelessUniformBuffersMap;
};
}  // anonymous namespace

bool NameNamelessUniformBuffers(TCompiler *compiler, TIntermBlock *root, TSymbolTable *symbolTable)
{
    NameUniformBufferVariablesTraverser nameUniformBufferVariables(symbolTable);
    root->traverse(&nameUniformBufferVariables);
    return nameUniformBufferVariables.updateTree(compiler, root);
}
}  // namespace sh
