/*
 * Copyright (C) 2019 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "WHLSLCheckDuplicateFunctions.h"

#if ENABLE(WEBGPU)

#include "WHLSLArrayReferenceType.h"
#include "WHLSLArrayType.h"
#include "WHLSLInferTypes.h"
#include "WHLSLTypeReference.h"
#include <wtf/HashSet.h>
#include <wtf/HashTraits.h>

namespace WebCore {

namespace WHLSL {

class DuplicateFunctionKey {
public:
    DuplicateFunctionKey() = default;
    DuplicateFunctionKey(WTF::HashTableDeletedValueType)
    {
        m_function = bitwise_cast<AST::FunctionDeclaration*>(static_cast<uintptr_t>(1));
    }

    DuplicateFunctionKey(const AST::FunctionDeclaration& function)
        : m_function(&function)
    { }

    bool isEmptyValue() const { return !m_function; }
    bool isHashTableDeletedValue() const { return m_function == bitwise_cast<AST::FunctionDeclaration*>(static_cast<uintptr_t>(1)); }

    unsigned hash() const
    {
        unsigned hash = IntHash<size_t>::hash(m_function->parameters().size());
        hash ^= m_function->name().hash();
        for (size_t i = 0; i < m_function->parameters().size(); ++i)
            hash ^= m_function->parameters()[i]->type().value()->hash();

        if (m_function->isCast())
            hash ^= m_function->type().hash();

        return hash;
    }

    bool operator==(const DuplicateFunctionKey& other) const
    {
        if (m_function->parameters().size() != other.m_function->parameters().size())
            return false;

        if (m_function->name() != other.m_function->name())
            return false;

        ASSERT(m_function->isCast() == other.m_function->isCast());

        for (size_t i = 0; i < m_function->parameters().size(); ++i) {
            if (!matches(*m_function->parameters()[i]->type(), *other.m_function->parameters()[i]->type()))
                return false;
        }

        if (!m_function->isCast())
            return true;

        if (matches(m_function->type(), other.m_function->type()))
            return true;

        return false;
    }

    struct Hash {
        static unsigned hash(const DuplicateFunctionKey& key)
        {
            return key.hash();
        }

        static bool equal(const DuplicateFunctionKey& a, const DuplicateFunctionKey& b)
        {
            return a == b;
        }

        static const bool safeToCompareToEmptyOrDeleted = false;
        static const bool emptyValueIsZero = true;
    };

    struct Traits : public WTF::SimpleClassHashTraits<DuplicateFunctionKey> {
        static const bool hasIsEmptyValueFunction = true;
        static bool isEmptyValue(const DuplicateFunctionKey& key) { return key.isEmptyValue(); }
    };

private:
    const AST::FunctionDeclaration* m_function { nullptr };
};

bool checkDuplicateFunctions(const Program& program)
{
    auto passesStaticChecks = [&] (const AST::FunctionDeclaration& function) {
        if (function.name() == "operator&[]" && function.parameters().size() == 2
            && is<AST::ArrayReferenceType>(static_cast<const AST::UnnamedType&>(*function.parameters()[0]->type()))) {
            auto& type = static_cast<const AST::UnnamedType&>(*function.parameters()[1]->type());
            if (is<AST::TypeReference>(type)) {
                // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198161 Shouldn't we already know whether the types have been resolved by now?
                if (auto* resolvedType = downcast<AST::TypeReference>(type).maybeResolvedType()) {
                    if (is<AST::NativeTypeDeclaration>(*resolvedType)) {
                        auto& nativeTypeDeclaration = downcast<AST::NativeTypeDeclaration>(*resolvedType);
                        if (nativeTypeDeclaration.name() == "uint")
                            return false;
                    }
                }
            }
        } else if (function.name() == "operator.length" && function.parameters().size() == 1
            && (is<AST::ArrayReferenceType>(static_cast<const AST::UnnamedType&>(*function.parameters()[0]->type()))
            || is<AST::ArrayType>(static_cast<const AST::UnnamedType&>(*function.parameters()[0]->type()))))
            return false;
        else if (function.name() == "operator=="
            && function.parameters().size() == 2
            && is<AST::ReferenceType>(static_cast<const AST::UnnamedType&>(*function.parameters()[0]->type()))
            && is<AST::ReferenceType>(static_cast<const AST::UnnamedType&>(*function.parameters()[1]->type()))
            && matches(*function.parameters()[0]->type(), *function.parameters()[1]->type()))
            return false;

        return true;
    };

    HashSet<DuplicateFunctionKey, DuplicateFunctionKey::Hash, DuplicateFunctionKey::Traits> functions;

    auto add = [&] (const AST::FunctionDeclaration& function) {
        auto addResult = functions.add(DuplicateFunctionKey { function });
        if (!addResult.isNewEntry)
            return false;
        return passesStaticChecks(function);
    };

    for (auto& functionDefinition : program.functionDefinitions()) {
        if (!add(functionDefinition.get()))
            return false;
    }

    for (auto& nativeFunctionDeclaration : program.nativeFunctionDeclarations()) {
        // We generate duplicate native function declarations in synthesize constructors.
        // FIXME: is this right?
        // https://bugs.webkit.org/show_bug.cgi?id=198580
        //
        // Since we do that, we just need to make sure no native function is a duplicate
        // of a user-defined function.
        ASSERT(passesStaticChecks(nativeFunctionDeclaration.get()));
        if (functions.contains(DuplicateFunctionKey { nativeFunctionDeclaration.get() }))
            return false;
    }

    return true;
}

} // namespace WHLSL

} // namespace WebCore

#endif // ENABLE(WEBGPU)
