//
// Copyright (c) 2016 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.
//
// ShaderCompileTreeTest.cpp:
//   Test that shader validation results in the correct compile status.
//

#include "tests/test_utils/ShaderCompileTreeTest.h"

#include "compiler/translator/TranslatorESSL.h"
#include "compiler/translator/tree_util/IntermTraverse.h"

namespace sh
{

namespace
{

// Checks that the node traversed is a zero node. It can be made out of multiple constructors and
// constant union nodes as long as there's no arithmetic involved and all constants are zero.
class OnlyContainsZeroConstantsTraverser final : public TIntermTraverser
{
  public:
    OnlyContainsZeroConstantsTraverser()
        : TIntermTraverser(true, false, false), mOnlyContainsConstantZeros(true)
    {
    }

    bool visitUnary(Visit, TIntermUnary *node) override
    {
        mOnlyContainsConstantZeros = false;
        return false;
    }

    bool visitBinary(Visit, TIntermBinary *node) override
    {
        mOnlyContainsConstantZeros = false;
        return false;
    }

    bool visitTernary(Visit, TIntermTernary *node) override
    {
        mOnlyContainsConstantZeros = false;
        return false;
    }

    bool visitSwizzle(Visit, TIntermSwizzle *node) override
    {
        mOnlyContainsConstantZeros = false;
        return false;
    }

    bool visitAggregate(Visit, TIntermAggregate *node) override
    {
        if (node->getOp() != EOpConstruct)
        {
            mOnlyContainsConstantZeros = false;
            return false;
        }
        return true;
    }

    void visitSymbol(TIntermSymbol *node) override { mOnlyContainsConstantZeros = false; }

    void visitConstantUnion(TIntermConstantUnion *node) override
    {
        if (!mOnlyContainsConstantZeros)
        {
            return;
        }

        const TType &type = node->getType();
        size_t objectSize = type.getObjectSize();
        for (size_t i = 0u; i < objectSize && mOnlyContainsConstantZeros; ++i)
        {
            bool isZero = false;
            switch (type.getBasicType())
            {
                case EbtFloat:
                    isZero = (node->getFConst(i) == 0.0f);
                    break;
                case EbtInt:
                    isZero = (node->getIConst(i) == 0);
                    break;
                case EbtUInt:
                    isZero = (node->getUConst(i) == 0u);
                    break;
                case EbtBool:
                    isZero = (node->getBConst(i) == false);
                    break;
                default:
                    // Cannot handle.
                    break;
            }
            if (!isZero)
            {
                mOnlyContainsConstantZeros = false;
                return;
            }
        }
    }

    bool onlyContainsConstantZeros() const { return mOnlyContainsConstantZeros; }

  private:
    bool mOnlyContainsConstantZeros;
};

}  // anonymous namespace

void ShaderCompileTreeTest::SetUp()
{
    mAllocator.push();
    SetGlobalPoolAllocator(&mAllocator);

    ShBuiltInResources resources;
    sh::InitBuiltInResources(&resources);

    initResources(&resources);

    mTranslator = new TranslatorESSL(getShaderType(), getShaderSpec());
    ASSERT_TRUE(mTranslator->Init(resources));
}

void ShaderCompileTreeTest::TearDown()
{
    delete mTranslator;

    SetGlobalPoolAllocator(nullptr);
    mAllocator.pop();
}

bool ShaderCompileTreeTest::compile(const std::string &shaderString)
{
    const char *shaderStrings[] = {shaderString.c_str()};
    mASTRoot = mTranslator->compileTreeForTesting(shaderStrings, 1, mExtraCompileOptions);
    TInfoSink &infoSink = mTranslator->getInfoSink();
    mInfoLog            = infoSink.info.c_str();
    return mASTRoot != nullptr;
}

void ShaderCompileTreeTest::compileAssumeSuccess(const std::string &shaderString)
{
    if (!compile(shaderString))
    {
        FAIL() << "Shader compilation into ESSL failed, log:\n" << mInfoLog;
    }
}

bool ShaderCompileTreeTest::hasWarning() const
{
    return mInfoLog.find("WARNING: ") != std::string::npos;
}

const std::vector<sh::Uniform> &ShaderCompileTreeTest::getUniforms() const
{
    ASSERT(mExtraCompileOptions & SH_VARIABLES);
    return mTranslator->getUniforms();
}

const std::vector<sh::Attribute> &ShaderCompileTreeTest::getAttributes() const
{
    ASSERT(mExtraCompileOptions & SH_VARIABLES);
    return mTranslator->getAttributes();
}

bool IsZero(TIntermNode *node)
{
    if (!node->getAsTyped())
    {
        return false;
    }
    OnlyContainsZeroConstantsTraverser traverser;
    node->traverse(&traverser);
    return traverser.onlyContainsConstantZeros();
}

}  // namespace sh
