//
// 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.
//

#ifdef UNSAFE_BUFFERS_BUILD
#    pragma allow_unsafe_buffers
#endif

#include "compiler/translator/BuiltInFunctionEmulator.h"
#include "angle_gl.h"
#include "compiler/translator/Symbol.h"
#include "compiler/translator/tree_util/IntermTraverse.h"

namespace sh
{

class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTraverser
{
  public:
    BuiltInFunctionEmulationMarker(BuiltInFunctionEmulator &emulator)
        : TIntermTraverser(true, false, false), mEmulator(emulator)
    {}

    bool visitUnary(Visit visit, TIntermUnary *node) override
    {
        if (node->getFunction())
        {
            bool needToEmulate = mEmulator.setFunctionCalled(node->getFunction());
            if (needToEmulate)
                node->setUseEmulatedFunction();
        }
        return true;
    }

    bool visitAggregate(Visit visit, TIntermAggregate *node) override
    {
        // Here we handle all the math built-in functions, not just the ones that are currently
        // identified as problematic.
        if (!BuiltInGroup::IsMath(node->getOp()))
        {
            return true;
        }
        bool needToEmulate = mEmulator.setFunctionCalled(node->getFunction());
        if (needToEmulate)
            node->setUseEmulatedFunction();
        return true;
    }

  private:
    BuiltInFunctionEmulator &mEmulator;
};

BuiltInFunctionEmulator::BuiltInFunctionEmulator() {}

void BuiltInFunctionEmulator::addEmulatedFunction(const TSymbolUniqueId &uniqueId,
                                                  const char *emulatedFunctionDefinition)
{
    mEmulatedFunctions[uniqueId.get()] = std::string(emulatedFunctionDefinition);
}

void BuiltInFunctionEmulator::addEmulatedFunctionWithDependency(
    const TSymbolUniqueId &dependency,
    const TSymbolUniqueId &uniqueId,
    const char *emulatedFunctionDefinition)
{
    mEmulatedFunctions[uniqueId.get()]    = std::string(emulatedFunctionDefinition);
    mFunctionDependencies[uniqueId.get()] = dependency.get();
}

bool BuiltInFunctionEmulator::isOutputEmpty() const
{
    return (mFunctions.size() == 0);
}

void BuiltInFunctionEmulator::outputEmulatedFunctions(TInfoSinkBase &out) const
{
    for (const auto &function : mFunctions)
    {
        const char *body = findEmulatedFunction(function);
        ASSERT(body);
        out << body;
        out << "\n\n";
    }
}

const char *BuiltInFunctionEmulator::findEmulatedFunction(int uniqueId) const
{
    for (const auto &queryFunction : mQueryFunctions)
    {
        const char *result = queryFunction(uniqueId);
        if (result)
        {
            return result;
        }
    }

    const auto &result = mEmulatedFunctions.find(uniqueId);
    if (result != mEmulatedFunctions.end())
    {
        return result->second.c_str();
    }

    return nullptr;
}

bool BuiltInFunctionEmulator::setFunctionCalled(const TFunction *function)
{
    ASSERT(function != nullptr);
    return setFunctionCalled(function->uniqueId().get());
}

bool BuiltInFunctionEmulator::setFunctionCalled(int uniqueId)
{
    if (!findEmulatedFunction(uniqueId))
    {
        return false;
    }

    for (size_t i = 0; i < mFunctions.size(); ++i)
    {
        if (mFunctions[i] == uniqueId)
            return true;
    }
    // If the function depends on another, mark the dependency as called.
    auto dependency = mFunctionDependencies.find(uniqueId);
    if (dependency != mFunctionDependencies.end())
    {
        setFunctionCalled((*dependency).second);
    }
    mFunctions.push_back(uniqueId);
    return true;
}

void BuiltInFunctionEmulator::markBuiltInFunctionsForEmulation(TIntermNode *root)
{
    ASSERT(root);

    if (mEmulatedFunctions.empty() && mQueryFunctions.empty())
        return;

    BuiltInFunctionEmulationMarker marker(*this);
    root->traverse(&marker);
}

void BuiltInFunctionEmulator::cleanup()
{
    mFunctions.clear();
    mFunctionDependencies.clear();
}

void BuiltInFunctionEmulator::addFunctionMap(BuiltinQueryFunc queryFunc)
{
    mQueryFunctions.push_back(queryFunc);
}

// static
void BuiltInFunctionEmulator::WriteEmulatedFunctionName(TInfoSinkBase &out, const char *name)
{
    ASSERT(name[strlen(name) - 1] != '(');
    out << name << "_emu";
}

}  // namespace sh
