/*
 * Copyright (C) 2015 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. ``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
 * 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.
 */

#ifndef WASMFunctionSyntaxChecker_h
#define WASMFunctionSyntaxChecker_h

#if ENABLE(WEBASSEMBLY)

#define UNUSED 0

namespace JSC {

class WASMFunctionSyntaxChecker {
public:
    typedef int Expression;
    typedef int Statement;
    typedef int ExpressionList;
    struct MemoryAddress {
        MemoryAddress(void*) { }
        MemoryAddress(int, uint32_t) { }
    };
    typedef int JumpTarget;
    enum class JumpCondition { Zero, NonZero };

    void startFunction(const Vector<WASMType>& arguments, uint32_t numberOfI32LocalVariables, uint32_t numberOfF32LocalVariables, uint32_t numberOfF64LocalVariables)
    {
        m_numberOfLocals = arguments.size() + numberOfI32LocalVariables + numberOfF32LocalVariables + numberOfF64LocalVariables;
    }

    void endFunction()
    {
        ASSERT(!m_tempStackTop);
    }

    int buildSetLocal(WASMOpKind opKind, uint32_t, int, WASMType)
    {
        if (opKind == WASMOpKind::Statement)
            m_tempStackTop--;
        return UNUSED;
    }

    int buildSetGlobal(WASMOpKind opKind, uint32_t, int, WASMType)
    {
        if (opKind == WASMOpKind::Statement)
            m_tempStackTop--;
        return UNUSED;
    }

    void buildReturn(int, WASMExpressionType returnType)
    {
        if (returnType != WASMExpressionType::Void)
            m_tempStackTop--;
    }

    int buildImmediateI32(uint32_t)
    {
        m_tempStackTop++;
        updateTempStackHeight();
        return UNUSED;
    }

    int buildImmediateF32(float)
    {
        m_tempStackTop++;
        updateTempStackHeight();
        return UNUSED;
    }

    int buildImmediateF64(double)
    {
        m_tempStackTop++;
        updateTempStackHeight();
        return UNUSED;
    }

    int buildGetLocal(uint32_t, WASMType)
    {
        m_tempStackTop++;
        updateTempStackHeight();
        return UNUSED;
    }

    int buildGetGlobal(uint32_t, WASMType)
    {
        m_tempStackTop++;
        updateTempStackHeight();
        return UNUSED;
    }

    int buildConvertType(int, WASMExpressionType, WASMExpressionType, WASMTypeConversion)
    {
        return UNUSED;
    }

    int buildLoad(const MemoryAddress&, WASMExpressionType, WASMMemoryType, MemoryAccessConversion)
    {
        return UNUSED;
    }

    int buildStore(WASMOpKind opKind, const MemoryAddress&, WASMExpressionType, WASMMemoryType, int)
    {
        m_tempStackTop -= 2;
        if (opKind == WASMOpKind::Expression)
            m_tempStackTop++;
        return UNUSED;
    }

    int buildUnaryI32(int, WASMOpExpressionI32)
    {
        return UNUSED;
    }

    int buildUnaryF32(int, WASMOpExpressionF32)
    {
        return UNUSED;
    }

    int buildUnaryF64(int, WASMOpExpressionF64)
    {
        return UNUSED;
    }

    int buildBinaryI32(int, int, WASMOpExpressionI32)
    {
        m_tempStackTop--;
        return UNUSED;
    }

    int buildBinaryF32(int, int, WASMOpExpressionF32)
    {
        m_tempStackTop--;
        return UNUSED;
    }

    int buildBinaryF64(int, int, WASMOpExpressionF64)
    {
        m_tempStackTop--;
        return UNUSED;
    }

    int buildRelationalI32(int, int, WASMOpExpressionI32)
    {
        m_tempStackTop--;
        return UNUSED;
    }

    int buildRelationalF32(int, int, WASMOpExpressionI32)
    {
        m_tempStackTop--;
        return UNUSED;
    }

    int buildRelationalF64(int, int, WASMOpExpressionI32)
    {
        m_tempStackTop--;
        return UNUSED;
    }

    int buildMinOrMaxI32(int, int, WASMOpExpressionI32)
    {
        m_tempStackTop--;
        return UNUSED;
    }

    int buildMinOrMaxF64(int, int, WASMOpExpressionF64)
    {
        m_tempStackTop--;
        return UNUSED;
    }

    int buildCallInternal(uint32_t, int, const WASMSignature& signature, WASMExpressionType returnType)
    {
        size_t argumentCount = signature.arguments.size();
        updateTempStackHeightForCall(argumentCount);
        m_tempStackTop -= argumentCount;
        if (returnType != WASMExpressionType::Void) {
            m_tempStackTop++;
            updateTempStackHeight();
        }
        return UNUSED;
    }

    int buildCallImport(uint32_t, int, const WASMSignature& signature, WASMExpressionType returnType)
    {
        size_t argumentCount = signature.arguments.size();
        updateTempStackHeightForCall(argumentCount);
        m_tempStackTop -= argumentCount;
        if (returnType != WASMExpressionType::Void) {
            m_tempStackTop++;
            updateTempStackHeight();
        }
        return UNUSED;
    }

    int buildCallIndirect(uint32_t, int, int, const WASMSignature& signature, WASMExpressionType returnType)
    {
        size_t argumentCount = signature.arguments.size();
        updateTempStackHeightForCall(argumentCount);
        m_tempStackTop -= argumentCount + 1;
        if (returnType != WASMExpressionType::Void)
            m_tempStackTop++;
        return UNUSED;
    }

    void appendExpressionList(int&, int) { }

    void discard(int)
    {
        m_tempStackTop--;
    }

    void linkTarget(const int&) { }
    void jumpToTarget(const int&) { }
    void jumpToTargetIf(JumpCondition, int, const int&)
    {
        m_tempStackTop--;
    }

    void startLoop() { }
    void endLoop() { }
    void startSwitch() { }
    void endSwitch() { }
    void startLabel() { }
    void endLabel() { }

    int breakTarget() { return UNUSED; }
    int continueTarget() { return UNUSED; }
    int breakLabelTarget(uint32_t) { return UNUSED; }
    int continueLabelTarget(uint32_t) { return UNUSED; }

    void buildSwitch(int, const Vector<int64_t>&, const Vector<int>&, const int&)
    {
        m_tempStackTop--;
    }

    unsigned stackHeight()
    {
        return m_numberOfLocals + m_tempStackHeight;
    }

private:
    void updateTempStackHeight()
    {
        if (m_tempStackTop > m_tempStackHeight)
            m_tempStackHeight = m_tempStackTop;
    }

    void updateTempStackHeightForCall(size_t argumentCount)
    {
        // Boxed arguments + this argument + call frame header + maximum padding.
        m_tempStackTop += argumentCount + 1 + JSStack::CallFrameHeaderSize + 1;
        updateTempStackHeight();
        m_tempStackTop -= argumentCount + 1 + JSStack::CallFrameHeaderSize + 1;
    }

    unsigned m_numberOfLocals;
    unsigned m_tempStackTop { 0 };
    unsigned m_tempStackHeight { 0 };
};

} // namespace JSC

#endif // ENABLE(WEBASSEMBLY)

#endif // WASMFunctionSyntaxChecker_h
