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

#include "config.h"
#include "WASMFunctionParser.h"

#if ENABLE(WEBASSEMBLY)

#include "JSCJSValueInlines.h"
#include "JSWASMModule.h"
#include "WASMFunctionCompiler.h"
#include "WASMFunctionLLVMIRGenerator.h"
#include "WASMFunctionSyntaxChecker.h"

#define PROPAGATE_ERROR() do { if (!m_errorMessage.isNull()) return 0; } while (0)
#define FAIL_WITH_MESSAGE(errorMessage) do {  m_errorMessage = errorMessage; return 0; } while (0)
#define READ_FLOAT_OR_FAIL(result, errorMessage) do { if (!m_reader.readFloat(result)) FAIL_WITH_MESSAGE(errorMessage); } while (0)
#define READ_DOUBLE_OR_FAIL(result, errorMessage) do { if (!m_reader.readDouble(result)) FAIL_WITH_MESSAGE(errorMessage); } while (0)
#define READ_COMPACT_INT32_OR_FAIL(result, errorMessage) do { if (!m_reader.readCompactInt32(result)) FAIL_WITH_MESSAGE(errorMessage); } while (0)
#define READ_COMPACT_UINT32_OR_FAIL(result, errorMessage) do { if (!m_reader.readCompactUInt32(result)) FAIL_WITH_MESSAGE(errorMessage); } while (0)
#define READ_EXPRESSION_TYPE_OR_FAIL(result, errorMessage) do { if (!m_reader.readExpressionType(result)) FAIL_WITH_MESSAGE(errorMessage); } while (0)
#define READ_OP_STATEMENT_OR_FAIL(hasImmediate, op, opWithImmediate, immediate, errorMessage) do { if (!m_reader.readOpStatement(hasImmediate, op, opWithImmediate, immediate)) FAIL_WITH_MESSAGE(errorMessage); } while (0)
#define READ_OP_EXPRESSION_I32_OR_FAIL(hasImmediate, op, opWithImmediate, immediate, errorMessage) do { if (!m_reader.readOpExpressionI32(hasImmediate, op, opWithImmediate, immediate)) FAIL_WITH_MESSAGE(errorMessage); } while (0)
#define READ_OP_EXPRESSION_F32_OR_FAIL(hasImmediate, op, opWithImmediate, immediate, errorMessage) do { if (!m_reader.readOpExpressionF32(hasImmediate, op, opWithImmediate, immediate)) FAIL_WITH_MESSAGE(errorMessage); } while (0)
#define READ_OP_EXPRESSION_F64_OR_FAIL(hasImmediate, op, opWithImmediate, immediate, errorMessage) do { if (!m_reader.readOpExpressionF64(hasImmediate, op, opWithImmediate, immediate)) FAIL_WITH_MESSAGE(errorMessage); } while (0)
#define READ_OP_EXPRESSION_VOID_OR_FAIL(op, errorMessage) do { if (!m_reader.readOpExpressionVoid(op)) FAIL_WITH_MESSAGE(errorMessage); } while (0)
#define READ_VARIABLE_TYPES_OR_FAIL(hasImmediate, variableTypes, variableTypesWithImmediate, immediate, errorMessage) do { if (!m_reader.readVariableTypes(hasImmediate, variableTypes, variableTypesWithImmediate, immediate)) FAIL_WITH_MESSAGE(errorMessage); } while (0)
#define READ_SWITCH_CASE_OR_FAIL(result, errorMessage) do { if (!m_reader.readSwitchCase(result)) FAIL_WITH_MESSAGE(errorMessage); } while (0)
#define FAIL_IF_FALSE(condition, errorMessage) do { if (!(condition)) FAIL_WITH_MESSAGE(errorMessage); } while (0)

#define UNUSED 0

namespace JSC {

static String nameOfType(WASMType type)
{
    switch (type) {
    case WASMType::I32:
        return "int32";
    case WASMType::F32:
        return "float32";
    case WASMType::F64:
        return "float64";
    default:
        RELEASE_ASSERT_NOT_REACHED();
    }
}

bool WASMFunctionParser::checkSyntax(JSWASMModule* module, const SourceCode& source, size_t functionIndex, unsigned startOffsetInSource, unsigned& endOffsetInSource, unsigned& stackHeight, String& errorMessage)
{
    WASMFunctionParser parser(module, source, functionIndex);
    WASMFunctionSyntaxChecker syntaxChecker;
    parser.m_reader.setOffset(startOffsetInSource);
    parser.parseFunction(syntaxChecker);
    if (!parser.m_errorMessage.isNull()) {
        errorMessage = parser.m_errorMessage;
        return false;
    }
    endOffsetInSource = parser.m_reader.offset();
    stackHeight = syntaxChecker.stackHeight();
    return true;
}

void WASMFunctionParser::compile(VM& vm, CodeBlock* codeBlock, JSWASMModule* module, const SourceCode& source, size_t functionIndex)
{
    WASMFunctionParser parser(module, source, functionIndex);
    WASMFunctionCompiler compiler(vm, codeBlock, module, module->functionStackHeights()[functionIndex]);
    parser.m_reader.setOffset(module->functionStartOffsetsInSource()[functionIndex]);
    parser.parseFunction(compiler);
    ASSERT(parser.m_errorMessage.isNull());
}

template <class Context>
bool WASMFunctionParser::parseFunction(Context& context)
{
    const WASMSignature& signature = m_module->signatures()[m_module->functionDeclarations()[m_functionIndex].signatureIndex];

    m_returnType = signature.returnType;

    parseLocalVariables();
    PROPAGATE_ERROR();

    const Vector<WASMType>& arguments = signature.arguments;
    for (size_t i = 0; i < arguments.size(); ++i)
        m_localTypes.append(arguments[i]);
    for (uint32_t i = 0; i < m_numberOfI32LocalVariables; ++i)
        m_localTypes.append(WASMType::I32);
    for (uint32_t i = 0; i < m_numberOfF32LocalVariables; ++i)
        m_localTypes.append(WASMType::F32);
    for (uint32_t i = 0; i < m_numberOfF64LocalVariables; ++i)
        m_localTypes.append(WASMType::F64);

    context.startFunction(arguments, m_numberOfI32LocalVariables, m_numberOfF32LocalVariables, m_numberOfF64LocalVariables);

    parseBlockStatement(context);
    PROPAGATE_ERROR();

    context.endFunction();
    return true;
}

bool WASMFunctionParser::parseLocalVariables()
{
    m_numberOfI32LocalVariables = 0;
    m_numberOfF32LocalVariables = 0;
    m_numberOfF64LocalVariables = 0;

    bool hasImmediate;
    WASMVariableTypes variableTypes;
    WASMVariableTypesWithImmediate variableTypesWithImmediate;
    uint8_t immediate;
    READ_VARIABLE_TYPES_OR_FAIL(hasImmediate, variableTypes, variableTypesWithImmediate, immediate, "Cannot read the types of local variables.");
    if (!hasImmediate) {
        if (static_cast<uint8_t>(variableTypes) & static_cast<uint8_t>(WASMVariableTypes::I32))
            READ_COMPACT_UINT32_OR_FAIL(m_numberOfI32LocalVariables, "Cannot read the number of int32 local variables.");
        if (static_cast<uint8_t>(variableTypes) & static_cast<uint8_t>(WASMVariableTypes::F32))
            READ_COMPACT_UINT32_OR_FAIL(m_numberOfF32LocalVariables, "Cannot read the number of float32 local variables.");
        if (static_cast<uint8_t>(variableTypes) & static_cast<uint8_t>(WASMVariableTypes::F64))
            READ_COMPACT_UINT32_OR_FAIL(m_numberOfF64LocalVariables, "Cannot read the number of float64 local variables.");
    } else
        m_numberOfI32LocalVariables = immediate;
    return true;
}

template <class Context>
ContextStatement WASMFunctionParser::parseStatement(Context& context)
{
    bool hasImmediate;
    WASMOpStatement op;
    WASMOpStatementWithImmediate opWithImmediate;
    uint8_t immediate;
    READ_OP_STATEMENT_OR_FAIL(hasImmediate, op, opWithImmediate, immediate, "Cannot read the statement opcode.");
    if (!hasImmediate) {
        switch (op) {
        case WASMOpStatement::SetLocal:
            parseSetLocal(context, WASMOpKind::Statement, WASMExpressionType::Void);
            break;
        case WASMOpStatement::SetGlobal:
            parseSetGlobal(context, WASMOpKind::Statement, WASMExpressionType::Void);
            break;
        case WASMOpStatement::I32Store8:
            parseStore(context, WASMOpKind::Statement, WASMExpressionType::I32, WASMMemoryType::I8, MemoryAccessOffsetMode::NoOffset);
            break;
        case WASMOpStatement::I32StoreWithOffset8:
            parseStore(context, WASMOpKind::Statement, WASMExpressionType::I32, WASMMemoryType::I8, MemoryAccessOffsetMode::WithOffset);
            break;
        case WASMOpStatement::I32Store16:
            parseStore(context, WASMOpKind::Statement, WASMExpressionType::I32, WASMMemoryType::I16, MemoryAccessOffsetMode::NoOffset);
            break;
        case WASMOpStatement::I32StoreWithOffset16:
            parseStore(context, WASMOpKind::Statement, WASMExpressionType::I32, WASMMemoryType::I16, MemoryAccessOffsetMode::WithOffset);
            break;
        case WASMOpStatement::I32Store32:
            parseStore(context, WASMOpKind::Statement, WASMExpressionType::I32, WASMMemoryType::I32, MemoryAccessOffsetMode::NoOffset);
            break;
        case WASMOpStatement::I32StoreWithOffset32:
            parseStore(context, WASMOpKind::Statement, WASMExpressionType::I32, WASMMemoryType::I32, MemoryAccessOffsetMode::WithOffset);
            break;
        case WASMOpStatement::F32Store:
            parseStore(context, WASMOpKind::Statement, WASMExpressionType::F32, WASMMemoryType::F32, MemoryAccessOffsetMode::NoOffset);
            break;
        case WASMOpStatement::F32StoreWithOffset:
            parseStore(context, WASMOpKind::Statement, WASMExpressionType::F32, WASMMemoryType::F32, MemoryAccessOffsetMode::WithOffset);
            break;
        case WASMOpStatement::F64Store:
            parseStore(context, WASMOpKind::Statement, WASMExpressionType::F64, WASMMemoryType::F64, MemoryAccessOffsetMode::NoOffset);
            break;
        case WASMOpStatement::F64StoreWithOffset:
            parseStore(context, WASMOpKind::Statement, WASMExpressionType::F64, WASMMemoryType::F64, MemoryAccessOffsetMode::WithOffset);
            break;
        case WASMOpStatement::CallInternal:
            parseCallInternal(context, WASMOpKind::Statement, WASMExpressionType::Void);
            break;
        case WASMOpStatement::CallIndirect:
            parseCallIndirect(context, WASMOpKind::Statement, WASMExpressionType::Void);
            break;
        case WASMOpStatement::CallImport:
            parseCallImport(context, WASMOpKind::Statement, WASMExpressionType::Void);
            break;
        case WASMOpStatement::Return:
            parseReturnStatement(context);
            break;
        case WASMOpStatement::Block:
            parseBlockStatement(context);
            break;
        case WASMOpStatement::If:
            parseIfStatement(context);
            break;
        case WASMOpStatement::IfElse:
            parseIfElseStatement(context);
            break;
        case WASMOpStatement::While:
            parseWhileStatement(context);
            break;
        case WASMOpStatement::Do:
            parseDoStatement(context);
            break;
        case WASMOpStatement::Label:
            parseLabelStatement(context);
            break;
        case WASMOpStatement::Break:
            parseBreakStatement(context);
            break;
        case WASMOpStatement::BreakLabel:
            parseBreakLabelStatement(context);
            break;
        case WASMOpStatement::Continue:
            parseContinueStatement(context);
            break;
        case WASMOpStatement::ContinueLabel:
            parseContinueLabelStatement(context);
            break;
        case WASMOpStatement::Switch:
            parseSwitchStatement(context);
            break;
        default:
            ASSERT_NOT_REACHED();
        }
    } else {
        switch (opWithImmediate) {
        case WASMOpStatementWithImmediate::SetLocal:
            parseSetLocal(context, WASMOpKind::Statement, WASMExpressionType::Void, immediate);
            break;
        case WASMOpStatementWithImmediate::SetGlobal:
            parseSetGlobal(context, WASMOpKind::Statement, WASMExpressionType::Void, immediate);
            break;
        default:
            ASSERT_NOT_REACHED();
        }
    }
    return UNUSED;
}

template <class Context>
ContextStatement WASMFunctionParser::parseReturnStatement(Context& context)
{
    ContextExpression expression = 0;
    if (m_returnType != WASMExpressionType::Void) {
        expression = parseExpression(context, m_returnType);
        PROPAGATE_ERROR();
    }
    context.buildReturn(expression, m_returnType);
    return UNUSED;
}

template <class Context>
ContextStatement WASMFunctionParser::parseBlockStatement(Context& context)
{
    uint32_t numberOfStatements;
    READ_COMPACT_UINT32_OR_FAIL(numberOfStatements, "Cannot read the number of statements.");
    for (uint32_t i = 0; i < numberOfStatements; ++i) {
        parseStatement(context);
        PROPAGATE_ERROR();
    }
    return UNUSED;
}

template <class Context>
ContextStatement WASMFunctionParser::parseIfStatement(Context& context)
{
    ContextJumpTarget end;

    ContextExpression expression = parseExpressionI32(context);
    PROPAGATE_ERROR();

    context.jumpToTargetIf(Context::JumpCondition::Zero, expression, end);

    parseStatement(context);
    PROPAGATE_ERROR();

    context.linkTarget(end);
    return UNUSED;
}

template <class Context>
ContextStatement WASMFunctionParser::parseIfElseStatement(Context& context)
{
    ContextJumpTarget elseTarget;
    ContextJumpTarget end;

    ContextExpression expression = parseExpressionI32(context);
    PROPAGATE_ERROR();

    context.jumpToTargetIf(Context::JumpCondition::Zero, expression, elseTarget);

    parseStatement(context);
    PROPAGATE_ERROR();

    context.jumpToTarget(end);
    context.linkTarget(elseTarget);

    parseStatement(context);
    PROPAGATE_ERROR();

    context.linkTarget(end);
    return UNUSED;
}

template <class Context>
ContextStatement WASMFunctionParser::parseWhileStatement(Context& context)
{
    context.startLoop();
    context.linkTarget(context.continueTarget());

    ContextExpression expression = parseExpressionI32(context);
    PROPAGATE_ERROR();

    context.jumpToTargetIf(Context::JumpCondition::Zero, expression, context.breakTarget());

    m_breakScopeDepth++;
    m_continueScopeDepth++;
    parseStatement(context);
    PROPAGATE_ERROR();
    m_continueScopeDepth--;
    m_breakScopeDepth--;

    context.jumpToTarget(context.continueTarget());

    context.linkTarget(context.breakTarget());
    context.endLoop();
    return UNUSED;
}

template <class Context>
ContextStatement WASMFunctionParser::parseDoStatement(Context& context)
{
    context.startLoop();

    ContextJumpTarget topOfLoop;
    context.linkTarget(topOfLoop);

    m_breakScopeDepth++;
    m_continueScopeDepth++;
    parseStatement(context);
    PROPAGATE_ERROR();
    m_continueScopeDepth--;
    m_breakScopeDepth--;

    context.linkTarget(context.continueTarget());

    ContextExpression expression = parseExpressionI32(context);
    PROPAGATE_ERROR();

    context.jumpToTargetIf(Context::JumpCondition::NonZero, expression, topOfLoop);

    context.linkTarget(context.breakTarget());
    context.endLoop();
    return UNUSED;
}

template <class Context>
ContextStatement WASMFunctionParser::parseLabelStatement(Context& context)
{
    context.startLabel();
    m_labelDepth++;
    parseStatement(context);
    PROPAGATE_ERROR();
    m_labelDepth--;
    context.endLabel();
    return UNUSED;
}

template <class Context>
ContextStatement WASMFunctionParser::parseBreakStatement(Context& context)
{
    FAIL_IF_FALSE(m_breakScopeDepth, "'break' is only valid inside a switch or loop statement.");
    context.jumpToTarget(context.breakTarget());
    return UNUSED;
}

template <class Context>
ContextStatement WASMFunctionParser::parseBreakLabelStatement(Context& context)
{
    uint32_t labelIndex;
    READ_COMPACT_UINT32_OR_FAIL(labelIndex, "Cannot read the label index.");
    FAIL_IF_FALSE(labelIndex < m_labelDepth, "The label index is incorrect.");
    context.jumpToTarget(context.breakLabelTarget(labelIndex));
    return UNUSED;
}

template <class Context>
ContextStatement WASMFunctionParser::parseContinueStatement(Context& context)
{
    FAIL_IF_FALSE(m_continueScopeDepth, "'continue' is only valid inside a loop statement.");
    context.jumpToTarget(context.continueTarget());
    return UNUSED;
}

template <class Context>
ContextStatement WASMFunctionParser::parseContinueLabelStatement(Context& context)
{
    uint32_t labelIndex;
    READ_COMPACT_UINT32_OR_FAIL(labelIndex, "Cannot read the label index.");
    FAIL_IF_FALSE(labelIndex < m_labelDepth, "The label index is incorrect.");
    context.jumpToTarget(context.continueLabelTarget(labelIndex));
    return UNUSED;
}

template <class Context>
ContextStatement WASMFunctionParser::parseSwitchStatement(Context& context)
{
    context.startSwitch();
    uint32_t numberOfCases;
    READ_COMPACT_UINT32_OR_FAIL(numberOfCases, "Cannot read the number of cases.");
    ContextExpression expression = parseExpressionI32(context);
    PROPAGATE_ERROR();

    ContextJumpTarget compare;
    context.jumpToTarget(compare);

    Vector<int64_t> cases;
    Vector<ContextJumpTarget> targets;
    cases.reserveInitialCapacity(numberOfCases);
    targets.reserveInitialCapacity(numberOfCases);
    bool hasDefault = false;
    ContextJumpTarget defaultTarget;

    m_breakScopeDepth++;
    for (uint32_t i = 0; i < numberOfCases; ++i) {
        WASMSwitchCase switchCase;
        READ_SWITCH_CASE_OR_FAIL(switchCase, "Cannot read the switch case.");
        switch (switchCase) {
        case WASMSwitchCase::CaseWithNoStatements:
        case WASMSwitchCase::CaseWithStatement:
        case WASMSwitchCase::CaseWithBlockStatement: {
            uint32_t value;
            READ_COMPACT_INT32_OR_FAIL(value, "Cannot read the value of the switch case.");
            cases.uncheckedAppend(value);
            ContextJumpTarget target;
            context.linkTarget(target);
            targets.uncheckedAppend(target);
            if (switchCase == WASMSwitchCase::CaseWithStatement) {
                parseStatement(context);
                PROPAGATE_ERROR();
            } else if (switchCase == WASMSwitchCase::CaseWithBlockStatement) {
                parseBlockStatement(context);
                PROPAGATE_ERROR();
            }
            break;
        }
        case WASMSwitchCase::DefaultWithNoStatements:
        case WASMSwitchCase::DefaultWithStatement:
        case WASMSwitchCase::DefaultWithBlockStatement: {
            FAIL_IF_FALSE(i == numberOfCases - 1, "The default case must be the last case.");
            hasDefault = true;
            context.linkTarget(defaultTarget);
            if (switchCase == WASMSwitchCase::DefaultWithStatement) {
                parseStatement(context);
                PROPAGATE_ERROR();
            } else if (switchCase == WASMSwitchCase::DefaultWithBlockStatement) {
                parseBlockStatement(context);
                PROPAGATE_ERROR();
            }
            break;
        }
        default:
            ASSERT_NOT_REACHED();
        }
    }
    if (!hasDefault)
        context.linkTarget(defaultTarget);

    m_breakScopeDepth--;

    context.jumpToTarget(context.breakTarget());
    context.linkTarget(compare);

    context.buildSwitch(expression, cases, targets, defaultTarget);

    context.linkTarget(context.breakTarget());
    context.endSwitch();
    return UNUSED;
}

template <class Context>
ContextExpression WASMFunctionParser::parseExpression(Context& context, WASMExpressionType expressionType)
{
    switch (expressionType) {
    case WASMExpressionType::I32:
        return parseExpressionI32(context);
    case WASMExpressionType::F32:
        return parseExpressionF32(context);
    case WASMExpressionType::F64:
        return parseExpressionF64(context);
    case WASMExpressionType::Void:
        return parseExpressionVoid(context);
    default:
        RELEASE_ASSERT_NOT_REACHED();
    }
}

template <class Context>
ContextExpression WASMFunctionParser::parseExpressionI32(Context& context)
{
    bool hasImmediate;
    WASMOpExpressionI32 op;
    WASMOpExpressionI32WithImmediate opWithImmediate;
    uint8_t immediate;
    READ_OP_EXPRESSION_I32_OR_FAIL(hasImmediate, op, opWithImmediate, immediate, "Cannot read the int32 expression opcode.");
    if (!hasImmediate) {
        switch (op) {
        case WASMOpExpressionI32::ConstantPoolIndex:
            return parseConstantPoolIndexExpressionI32(context);
        case WASMOpExpressionI32::Immediate:
            return parseImmediateExpressionI32(context);
        case WASMOpExpressionI32::GetLocal:
            return parseGetLocalExpression(context, WASMType::I32);
        case WASMOpExpressionI32::GetGlobal:
            return parseGetGlobalExpression(context, WASMType::I32);
        case WASMOpExpressionI32::SetLocal:
            return parseSetLocal(context, WASMOpKind::Expression, WASMExpressionType::I32);
        case WASMOpExpressionI32::SetGlobal:
            return parseSetGlobal(context, WASMOpKind::Expression, WASMExpressionType::I32);
        case WASMOpExpressionI32::SLoad8:
            return parseLoad(context, WASMExpressionType::I32, WASMMemoryType::I8, MemoryAccessOffsetMode::NoOffset, MemoryAccessConversion::SignExtend);
        case WASMOpExpressionI32::SLoadWithOffset8:
            return parseLoad(context, WASMExpressionType::I32, WASMMemoryType::I8, MemoryAccessOffsetMode::WithOffset, MemoryAccessConversion::SignExtend);
        case WASMOpExpressionI32::ULoad8:
            return parseLoad(context, WASMExpressionType::I32, WASMMemoryType::I8, MemoryAccessOffsetMode::NoOffset, MemoryAccessConversion::ZeroExtend);
        case WASMOpExpressionI32::ULoadWithOffset8:
            return parseLoad(context, WASMExpressionType::I32, WASMMemoryType::I8, MemoryAccessOffsetMode::WithOffset, MemoryAccessConversion::ZeroExtend);
        case WASMOpExpressionI32::SLoad16:
            return parseLoad(context, WASMExpressionType::I32, WASMMemoryType::I16, MemoryAccessOffsetMode::NoOffset, MemoryAccessConversion::SignExtend);
        case WASMOpExpressionI32::SLoadWithOffset16:
            return parseLoad(context, WASMExpressionType::I32, WASMMemoryType::I16, MemoryAccessOffsetMode::WithOffset, MemoryAccessConversion::SignExtend);
        case WASMOpExpressionI32::ULoad16:
            return parseLoad(context, WASMExpressionType::I32, WASMMemoryType::I16, MemoryAccessOffsetMode::NoOffset, MemoryAccessConversion::ZeroExtend);
        case WASMOpExpressionI32::ULoadWithOffset16:
            return parseLoad(context, WASMExpressionType::I32, WASMMemoryType::I16, MemoryAccessOffsetMode::WithOffset, MemoryAccessConversion::ZeroExtend);
        case WASMOpExpressionI32::Load32:
            return parseLoad(context, WASMExpressionType::I32, WASMMemoryType::I32, MemoryAccessOffsetMode::NoOffset);
        case WASMOpExpressionI32::LoadWithOffset32:
            return parseLoad(context, WASMExpressionType::I32, WASMMemoryType::I32, MemoryAccessOffsetMode::WithOffset);
        case WASMOpExpressionI32::Store8:
            return parseStore(context, WASMOpKind::Expression, WASMExpressionType::I32, WASMMemoryType::I8, MemoryAccessOffsetMode::NoOffset);
        case WASMOpExpressionI32::StoreWithOffset8:
            return parseStore(context, WASMOpKind::Expression, WASMExpressionType::I32, WASMMemoryType::I8, MemoryAccessOffsetMode::WithOffset);
        case WASMOpExpressionI32::Store16:
            return parseStore(context, WASMOpKind::Expression, WASMExpressionType::I32, WASMMemoryType::I16, MemoryAccessOffsetMode::NoOffset);
        case WASMOpExpressionI32::StoreWithOffset16:
            return parseStore(context, WASMOpKind::Expression, WASMExpressionType::I32, WASMMemoryType::I16, MemoryAccessOffsetMode::WithOffset);
        case WASMOpExpressionI32::Store32:
            return parseStore(context, WASMOpKind::Expression, WASMExpressionType::I32, WASMMemoryType::I32, MemoryAccessOffsetMode::NoOffset);
        case WASMOpExpressionI32::StoreWithOffset32:
            return parseStore(context, WASMOpKind::Expression, WASMExpressionType::I32, WASMMemoryType::I32, MemoryAccessOffsetMode::WithOffset);
        case WASMOpExpressionI32::CallInternal:
            return parseCallInternal(context, WASMOpKind::Expression, WASMExpressionType::I32);
        case WASMOpExpressionI32::CallIndirect:
            return parseCallIndirect(context, WASMOpKind::Expression, WASMExpressionType::I32);
        case WASMOpExpressionI32::CallImport:
            return parseCallImport(context, WASMOpKind::Expression, WASMExpressionType::I32);
        case WASMOpExpressionI32::Conditional:
            return parseConditional(context, WASMExpressionType::I32);
        case WASMOpExpressionI32::Comma:
            return parseComma(context, WASMExpressionType::I32);
        case WASMOpExpressionI32::FromF32:
            return parseConvertType(context, WASMExpressionType::F32, WASMExpressionType::I32, WASMTypeConversion::ConvertSigned);
        case WASMOpExpressionI32::FromF64:
            return parseConvertType(context, WASMExpressionType::F64, WASMExpressionType::I32, WASMTypeConversion::ConvertSigned);
        case WASMOpExpressionI32::Negate:
        case WASMOpExpressionI32::BitNot:
        case WASMOpExpressionI32::CountLeadingZeros:
        case WASMOpExpressionI32::LogicalNot:
        case WASMOpExpressionI32::Abs:
            return parseUnaryExpressionI32(context, op);
        case WASMOpExpressionI32::Add:
        case WASMOpExpressionI32::Sub:
        case WASMOpExpressionI32::Mul:
        case WASMOpExpressionI32::SDiv:
        case WASMOpExpressionI32::UDiv:
        case WASMOpExpressionI32::SMod:
        case WASMOpExpressionI32::UMod:
        case WASMOpExpressionI32::BitOr:
        case WASMOpExpressionI32::BitAnd:
        case WASMOpExpressionI32::BitXor:
        case WASMOpExpressionI32::LeftShift:
        case WASMOpExpressionI32::ArithmeticRightShift:
        case WASMOpExpressionI32::LogicalRightShift:
            return parseBinaryExpressionI32(context, op);
        case WASMOpExpressionI32::EqualI32:
        case WASMOpExpressionI32::NotEqualI32:
        case WASMOpExpressionI32::SLessThanI32:
        case WASMOpExpressionI32::ULessThanI32:
        case WASMOpExpressionI32::SLessThanOrEqualI32:
        case WASMOpExpressionI32::ULessThanOrEqualI32:
        case WASMOpExpressionI32::SGreaterThanI32:
        case WASMOpExpressionI32::UGreaterThanI32:
        case WASMOpExpressionI32::SGreaterThanOrEqualI32:
        case WASMOpExpressionI32::UGreaterThanOrEqualI32:
            return parseRelationalI32ExpressionI32(context, op);
        case WASMOpExpressionI32::EqualF32:
        case WASMOpExpressionI32::NotEqualF32:
        case WASMOpExpressionI32::LessThanF32:
        case WASMOpExpressionI32::LessThanOrEqualF32:
        case WASMOpExpressionI32::GreaterThanF32:
        case WASMOpExpressionI32::GreaterThanOrEqualF32:
            return parseRelationalF32ExpressionI32(context, op);
        case WASMOpExpressionI32::EqualF64:
        case WASMOpExpressionI32::NotEqualF64:
        case WASMOpExpressionI32::LessThanF64:
        case WASMOpExpressionI32::LessThanOrEqualF64:
        case WASMOpExpressionI32::GreaterThanF64:
        case WASMOpExpressionI32::GreaterThanOrEqualF64:
            return parseRelationalF64ExpressionI32(context, op);
        case WASMOpExpressionI32::SMin:
        case WASMOpExpressionI32::UMin:
        case WASMOpExpressionI32::SMax:
        case WASMOpExpressionI32::UMax:
            return parseMinOrMaxExpressionI32(context, op);
        default:
            ASSERT_NOT_REACHED();
        }
    } else {
        switch (opWithImmediate) {
        case WASMOpExpressionI32WithImmediate::ConstantPoolIndex:
            return parseConstantPoolIndexExpressionI32(context, immediate);
        case WASMOpExpressionI32WithImmediate::Immediate:
            return parseImmediateExpressionI32(context, immediate);
        case WASMOpExpressionI32WithImmediate::GetLocal:
            return parseGetLocalExpression(context, WASMType::I32, immediate);
        default:
            ASSERT_NOT_REACHED();
        }
    }
    return 0;
}

template <class Context>
ContextExpression WASMFunctionParser::parseConstantPoolIndexExpressionI32(Context& context, uint32_t constantPoolIndex)
{
    FAIL_IF_FALSE(constantPoolIndex < m_module->i32Constants().size(), "The constant pool index is incorrect.");
    return context.buildImmediateI32(m_module->i32Constants()[constantPoolIndex]);
}

template <class Context>
ContextExpression WASMFunctionParser::parseConstantPoolIndexExpressionI32(Context& context)
{
    uint32_t constantPoolIndex;
    READ_COMPACT_UINT32_OR_FAIL(constantPoolIndex, "Cannot read the constant pool index.");
    return parseConstantPoolIndexExpressionI32(context, constantPoolIndex);
}

template <class Context>
ContextExpression WASMFunctionParser::parseImmediateExpressionI32(Context& context, uint32_t immediate)
{
    return context.buildImmediateI32(immediate);
}

template <class Context>
ContextExpression WASMFunctionParser::parseImmediateExpressionI32(Context& context)
{
    uint32_t immediate;
    READ_COMPACT_UINT32_OR_FAIL(immediate, "Cannot read the immediate.");
    return parseImmediateExpressionI32(context, immediate);
}

template <class Context>
ContextExpression WASMFunctionParser::parseUnaryExpressionI32(Context& context, WASMOpExpressionI32 op)
{
    ContextExpression expression = parseExpressionI32(context);
    PROPAGATE_ERROR();
    return context.buildUnaryI32(expression, op);
}

template <class Context>
ContextExpression WASMFunctionParser::parseBinaryExpressionI32(Context& context, WASMOpExpressionI32 op)
{
    ContextExpression left = parseExpressionI32(context);
    PROPAGATE_ERROR();
    ContextExpression right = parseExpressionI32(context);
    PROPAGATE_ERROR();
    return context.buildBinaryI32(left, right, op);
}

template <class Context>
ContextExpression WASMFunctionParser::parseRelationalI32ExpressionI32(Context& context, WASMOpExpressionI32 op)
{
    ContextExpression left = parseExpressionI32(context);
    PROPAGATE_ERROR();
    ContextExpression right = parseExpressionI32(context);
    PROPAGATE_ERROR();
    return context.buildRelationalI32(left, right, op);
}

template <class Context>
ContextExpression WASMFunctionParser::parseRelationalF32ExpressionI32(Context& context, WASMOpExpressionI32 op)
{
    ContextExpression left = parseExpressionF32(context);
    PROPAGATE_ERROR();
    ContextExpression right = parseExpressionF32(context);
    PROPAGATE_ERROR();
    return context.buildRelationalF32(left, right, op);
}

template <class Context>
ContextExpression WASMFunctionParser::parseRelationalF64ExpressionI32(Context& context, WASMOpExpressionI32 op)
{
    ContextExpression left = parseExpressionF64(context);
    PROPAGATE_ERROR();
    ContextExpression right = parseExpressionF64(context);
    PROPAGATE_ERROR();
    return context.buildRelationalF64(left, right, op);
}

template <class Context>
ContextExpression WASMFunctionParser::parseMinOrMaxExpressionI32(Context& context, WASMOpExpressionI32 op)
{
    uint32_t numberOfArguments;
    READ_COMPACT_UINT32_OR_FAIL(numberOfArguments, "Cannot read the number of arguments to min/max.");
    FAIL_IF_FALSE(numberOfArguments >= 2, "Min/max must be passed at least 2 arguments.");
    ContextExpression current = parseExpressionI32(context);
    PROPAGATE_ERROR();
    for (uint32_t i = 1; i < numberOfArguments; ++i) {
        ContextExpression expression = parseExpressionI32(context);
        PROPAGATE_ERROR();
        current = context.buildMinOrMaxI32(current, expression, op);
    }
    return current;
}

template <class Context>
ContextExpression WASMFunctionParser::parseExpressionF32(Context& context)
{
    bool hasImmediate;
    WASMOpExpressionF32 op;
    WASMOpExpressionF32WithImmediate opWithImmediate;
    uint8_t immediate;
    READ_OP_EXPRESSION_F32_OR_FAIL(hasImmediate, op, opWithImmediate, immediate, "Cannot read the float32 expression opcode.");
    if (!hasImmediate) {
        switch (op) {
        case WASMOpExpressionF32::ConstantPoolIndex:
            return parseConstantPoolIndexExpressionF32(context);
        case WASMOpExpressionF32::Immediate:
            return parseImmediateExpressionF32(context);
        case WASMOpExpressionF32::GetLocal:
            return parseGetLocalExpression(context, WASMType::F32);
        case WASMOpExpressionF32::GetGlobal:
            return parseGetGlobalExpression(context, WASMType::F32);
        case WASMOpExpressionF32::SetLocal:
            return parseSetLocal(context, WASMOpKind::Expression, WASMExpressionType::F32);
        case WASMOpExpressionF32::SetGlobal:
            return parseSetGlobal(context, WASMOpKind::Expression, WASMExpressionType::F32);
        case WASMOpExpressionF32::Load:
            return parseLoad(context, WASMExpressionType::F32, WASMMemoryType::F32, MemoryAccessOffsetMode::NoOffset);
        case WASMOpExpressionF32::LoadWithOffset:
            return parseLoad(context, WASMExpressionType::F32, WASMMemoryType::F32, MemoryAccessOffsetMode::WithOffset);
        case WASMOpExpressionF32::Store:
            return parseStore(context, WASMOpKind::Expression, WASMExpressionType::F32, WASMMemoryType::F32, MemoryAccessOffsetMode::NoOffset);
        case WASMOpExpressionF32::StoreWithOffset:
            return parseStore(context, WASMOpKind::Expression, WASMExpressionType::F32, WASMMemoryType::F32, MemoryAccessOffsetMode::WithOffset);
        case WASMOpExpressionF32::CallInternal:
            return parseCallInternal(context, WASMOpKind::Expression, WASMExpressionType::F32);
        case WASMOpExpressionF32::CallIndirect:
            return parseCallIndirect(context, WASMOpKind::Expression, WASMExpressionType::F32);
        case WASMOpExpressionF32::Conditional:
            return parseConditional(context, WASMExpressionType::F32);
        case WASMOpExpressionF32::Comma:
            return parseComma(context, WASMExpressionType::F32);
        case WASMOpExpressionF32::FromS32:
            return parseConvertType(context, WASMExpressionType::I32, WASMExpressionType::F32, WASMTypeConversion::ConvertSigned);
        case WASMOpExpressionF32::FromU32:
            return parseConvertType(context, WASMExpressionType::I32, WASMExpressionType::F32, WASMTypeConversion::ConvertUnsigned);
        case WASMOpExpressionF32::FromF64:
            return parseConvertType(context, WASMExpressionType::F64, WASMExpressionType::F32, WASMTypeConversion::Demote);
        case WASMOpExpressionF32::Negate:
        case WASMOpExpressionF32::Abs:
        case WASMOpExpressionF32::Ceil:
        case WASMOpExpressionF32::Floor:
        case WASMOpExpressionF32::Sqrt:
            return parseUnaryExpressionF32(context, op);
        case WASMOpExpressionF32::Add:
        case WASMOpExpressionF32::Sub:
        case WASMOpExpressionF32::Mul:
        case WASMOpExpressionF32::Div:
            return parseBinaryExpressionF32(context, op);
        default:
            ASSERT_NOT_REACHED();
        }
    } else {
        switch (opWithImmediate) {
        case WASMOpExpressionF32WithImmediate::ConstantPoolIndex:
            return parseConstantPoolIndexExpressionF32(context, immediate);
        case WASMOpExpressionF32WithImmediate::GetLocal:
            return parseGetLocalExpression(context, WASMType::F32, immediate);
        default:
            ASSERT_NOT_REACHED();
        }
    }
    return 0;
}

template <class Context>
ContextExpression WASMFunctionParser::parseConstantPoolIndexExpressionF32(Context& context, uint32_t constantIndex)
{
    FAIL_IF_FALSE(constantIndex < m_module->f32Constants().size(), "The constant pool index is incorrect.");
    return context.buildImmediateF32(m_module->f32Constants()[constantIndex]);
}

template <class Context>
ContextExpression WASMFunctionParser::parseConstantPoolIndexExpressionF32(Context& context)
{
    uint32_t constantIndex;
    READ_COMPACT_UINT32_OR_FAIL(constantIndex, "Cannot read the constant pool index.");
    return parseConstantPoolIndexExpressionF32(context, constantIndex);
}

template <class Context>
ContextExpression WASMFunctionParser::parseImmediateExpressionF32(Context& context)
{
    float immediate;
    READ_FLOAT_OR_FAIL(immediate, "Cannot read the immediate.");
    return context.buildImmediateF32(immediate);
}

template <class Context>
ContextExpression WASMFunctionParser::parseUnaryExpressionF32(Context& context, WASMOpExpressionF32 op)
{
    ContextExpression expression = parseExpressionF32(context);
    PROPAGATE_ERROR();
    return context.buildUnaryF32(expression, op);
}

template <class Context>
ContextExpression WASMFunctionParser::parseBinaryExpressionF32(Context& context, WASMOpExpressionF32 op)
{
    ContextExpression left = parseExpressionF32(context);
    PROPAGATE_ERROR();
    ContextExpression right = parseExpressionF32(context);
    PROPAGATE_ERROR();
    return context.buildBinaryF32(left, right, op);
}

template <class Context>
ContextExpression WASMFunctionParser::parseExpressionF64(Context& context)
{
    bool hasImmediate;
    WASMOpExpressionF64 op;
    WASMOpExpressionF64WithImmediate opWithImmediate;
    uint8_t immediate;
    READ_OP_EXPRESSION_F64_OR_FAIL(hasImmediate, op, opWithImmediate, immediate, "Cannot read the float64 expression opcode.");
    if (!hasImmediate) {
        switch (op) {
        case WASMOpExpressionF64::ConstantPoolIndex:
            return parseConstantPoolIndexExpressionF64(context);
        case WASMOpExpressionF64::Immediate:
            return parseImmediateExpressionF64(context);
        case WASMOpExpressionF64::GetLocal:
            return parseGetLocalExpression(context, WASMType::F64);
        case WASMOpExpressionF64::GetGlobal:
            return parseGetGlobalExpression(context, WASMType::F64);
        case WASMOpExpressionF64::SetLocal:
            return parseSetLocal(context, WASMOpKind::Expression, WASMExpressionType::F64);
        case WASMOpExpressionF64::SetGlobal:
            return parseSetGlobal(context, WASMOpKind::Expression, WASMExpressionType::F64);
        case WASMOpExpressionF64::Load:
            return parseLoad(context, WASMExpressionType::F64, WASMMemoryType::F64, MemoryAccessOffsetMode::NoOffset);
        case WASMOpExpressionF64::LoadWithOffset:
            return parseLoad(context, WASMExpressionType::F64, WASMMemoryType::F64, MemoryAccessOffsetMode::WithOffset);
        case WASMOpExpressionF64::Store:
            return parseStore(context, WASMOpKind::Expression, WASMExpressionType::F64, WASMMemoryType::F64, MemoryAccessOffsetMode::NoOffset);
        case WASMOpExpressionF64::StoreWithOffset:
            return parseStore(context, WASMOpKind::Expression, WASMExpressionType::F64, WASMMemoryType::F64, MemoryAccessOffsetMode::WithOffset);
        case WASMOpExpressionF64::CallInternal:
            return parseCallInternal(context, WASMOpKind::Expression, WASMExpressionType::F64);
        case WASMOpExpressionF64::CallImport:
            return parseCallImport(context, WASMOpKind::Expression, WASMExpressionType::F64);
        case WASMOpExpressionF64::CallIndirect:
            return parseCallIndirect(context, WASMOpKind::Expression, WASMExpressionType::F64);
        case WASMOpExpressionF64::Conditional:
            return parseConditional(context, WASMExpressionType::F64);
        case WASMOpExpressionF64::Comma:
            return parseComma(context, WASMExpressionType::F64);
        case WASMOpExpressionF64::FromS32:
            return parseConvertType(context, WASMExpressionType::I32, WASMExpressionType::F64, WASMTypeConversion::ConvertSigned);
        case WASMOpExpressionF64::FromU32:
            return parseConvertType(context, WASMExpressionType::I32, WASMExpressionType::F64, WASMTypeConversion::ConvertUnsigned);
        case WASMOpExpressionF64::FromF32:
            return parseConvertType(context, WASMExpressionType::F32, WASMExpressionType::F64, WASMTypeConversion::Promote);
        case WASMOpExpressionF64::Negate:
        case WASMOpExpressionF64::Abs:
        case WASMOpExpressionF64::Ceil:
        case WASMOpExpressionF64::Floor:
        case WASMOpExpressionF64::Sqrt:
        case WASMOpExpressionF64::Cos:
        case WASMOpExpressionF64::Sin:
        case WASMOpExpressionF64::Tan:
        case WASMOpExpressionF64::ACos:
        case WASMOpExpressionF64::ASin:
        case WASMOpExpressionF64::ATan:
        case WASMOpExpressionF64::Exp:
        case WASMOpExpressionF64::Ln:
            return parseUnaryExpressionF64(context, op);
        case WASMOpExpressionF64::Add:
        case WASMOpExpressionF64::Sub:
        case WASMOpExpressionF64::Mul:
        case WASMOpExpressionF64::Div:
        case WASMOpExpressionF64::Mod:
        case WASMOpExpressionF64::ATan2:
        case WASMOpExpressionF64::Pow:
            return parseBinaryExpressionF64(context, op);
        case WASMOpExpressionF64::Min:
        case WASMOpExpressionF64::Max:
            return parseMinOrMaxExpressionF64(context, op);
        default:
            ASSERT_NOT_REACHED();
        }
    } else {
        switch (opWithImmediate) {
        case WASMOpExpressionF64WithImmediate::ConstantPoolIndex:
            return parseConstantPoolIndexExpressionF64(context, immediate);
        case WASMOpExpressionF64WithImmediate::GetLocal:
            return parseGetLocalExpression(context, WASMType::F64, immediate);
        default:
            ASSERT_NOT_REACHED();
        }
    }
    return 0;
}

template <class Context>
ContextExpression WASMFunctionParser::parseConstantPoolIndexExpressionF64(Context& context, uint32_t constantIndex)
{
    FAIL_IF_FALSE(constantIndex < m_module->f64Constants().size(), "The constant index is incorrect.");
    return context.buildImmediateF64(m_module->f64Constants()[constantIndex]);
}

template <class Context>
ContextExpression WASMFunctionParser::parseConstantPoolIndexExpressionF64(Context& context)
{
    uint32_t constantIndex;
    READ_COMPACT_UINT32_OR_FAIL(constantIndex, "Cannot read the constant index.");
    return parseConstantPoolIndexExpressionF64(context, constantIndex);
}

template <class Context>
ContextExpression WASMFunctionParser::parseImmediateExpressionF64(Context& context)
{
    double immediate;
    READ_DOUBLE_OR_FAIL(immediate, "Cannot read the immediate.");
    return context.buildImmediateF64(immediate);
}

template <class Context>
ContextExpression WASMFunctionParser::parseUnaryExpressionF64(Context& context, WASMOpExpressionF64 op)
{
    ContextExpression expression = parseExpressionF64(context);
    PROPAGATE_ERROR();
    return context.buildUnaryF64(expression, op);
}

template <class Context>
ContextExpression WASMFunctionParser::parseBinaryExpressionF64(Context& context, WASMOpExpressionF64 op)
{
    ContextExpression left = parseExpressionF64(context);
    PROPAGATE_ERROR();
    ContextExpression right = parseExpressionF64(context);
    PROPAGATE_ERROR();
    return context.buildBinaryF64(left, right, op);
}

template <class Context>
ContextExpression WASMFunctionParser::parseMinOrMaxExpressionF64(Context& context, WASMOpExpressionF64 op)
{
    uint32_t numberOfArguments;
    READ_COMPACT_UINT32_OR_FAIL(numberOfArguments, "Cannot read the number of arguments to min/max.");
    FAIL_IF_FALSE(numberOfArguments >= 2, "Min/max must be passed at least 2 arguments.");
    ContextExpression current = parseExpressionF64(context);
    PROPAGATE_ERROR();
    for (uint32_t i = 1; i < numberOfArguments; ++i) {
        ContextExpression expression = parseExpressionF64(context);
        PROPAGATE_ERROR();
        current = context.buildMinOrMaxF64(current, expression, op);
    }
    return current;
}

template <class Context>
ContextExpression WASMFunctionParser::parseExpressionVoid(Context& context)
{
    WASMOpExpressionVoid op;
    READ_OP_EXPRESSION_VOID_OR_FAIL(op, "Cannot read the void expression opcode.");
    switch (op) {
    case WASMOpExpressionVoid::CallInternal:
        return parseCallInternal(context, WASMOpKind::Expression, WASMExpressionType::Void);
    case WASMOpExpressionVoid::CallIndirect:
        return parseCallIndirect(context, WASMOpKind::Expression, WASMExpressionType::Void);
    case WASMOpExpressionVoid::CallImport:
        return parseCallImport(context, WASMOpKind::Expression, WASMExpressionType::Void);
    default:
        RELEASE_ASSERT_NOT_REACHED();
    }
}

template <class Context>
ContextExpression WASMFunctionParser::parseGetLocalExpression(Context& context, WASMType type, uint32_t localIndex)
{
    FAIL_IF_FALSE(localIndex < m_localTypes.size(), "The local index is incorrect.");
    FAIL_IF_FALSE(m_localTypes[localIndex] == type, "Expected a local of type " + nameOfType(type) + '.');
    return context.buildGetLocal(localIndex, type);
}

template <class Context>
ContextExpression WASMFunctionParser::parseGetLocalExpression(Context& context, WASMType type)
{
    uint32_t localIndex;
    READ_COMPACT_UINT32_OR_FAIL(localIndex, "Cannot read the local index.");
    return parseGetLocalExpression(context, type, localIndex);
}

template <class Context>
ContextExpression WASMFunctionParser::parseGetGlobalExpression(Context& context, WASMType type)
{
    uint32_t globalIndex;
    READ_COMPACT_UINT32_OR_FAIL(globalIndex, "Cannot read the global index.");
    FAIL_IF_FALSE(globalIndex < m_module->globalVariableTypes().size(), "The global index is incorrect.");
    FAIL_IF_FALSE(m_module->globalVariableTypes()[globalIndex] == type, "Expected a global of type " + nameOfType(type) + '.');
    return context.buildGetGlobal(globalIndex, type);
}

template <class Context>
ContextExpression WASMFunctionParser::parseSetLocal(Context& context, WASMOpKind opKind, WASMExpressionType expressionType, uint32_t localIndex)
{
    FAIL_IF_FALSE(localIndex < m_localTypes.size(), "The local variable index is incorrect.");
    WASMType type = m_localTypes[localIndex];
    if (opKind == WASMOpKind::Expression)
        FAIL_IF_FALSE(expressionType == WASMExpressionType(type), "The type doesn't match.");
    ContextExpression expression = parseExpression(context, WASMExpressionType(type));
    PROPAGATE_ERROR();
    return context.buildSetLocal(opKind, localIndex, expression, type);
}

template <class Context>
ContextExpression WASMFunctionParser::parseSetLocal(Context& context, WASMOpKind opKind, WASMExpressionType expressionType)
{
    uint32_t localIndex;
    READ_COMPACT_UINT32_OR_FAIL(localIndex, "Cannot read the local index.");
    return parseSetLocal(context, opKind, expressionType, localIndex);
}

template <class Context>
ContextExpression WASMFunctionParser::parseSetGlobal(Context& context, WASMOpKind opKind, WASMExpressionType expressionType, uint32_t globalIndex)
{
    FAIL_IF_FALSE(globalIndex < m_module->globalVariableTypes().size(), "The global index is incorrect.");
    WASMType type = m_module->globalVariableTypes()[globalIndex];
    if (opKind == WASMOpKind::Expression)
        FAIL_IF_FALSE(expressionType == WASMExpressionType(type), "The type doesn't match.");
    ContextExpression expression = parseExpression(context, WASMExpressionType(type));
    PROPAGATE_ERROR();
    return context.buildSetGlobal(opKind, globalIndex, expression, type);
}

template <class Context>
ContextExpression WASMFunctionParser::parseSetGlobal(Context& context, WASMOpKind opKind, WASMExpressionType expressionType)
{
    uint32_t globalIndex;
    READ_COMPACT_UINT32_OR_FAIL(globalIndex, "Cannot read the global index.");
    return parseSetGlobal(context, opKind, expressionType, globalIndex);
}

template <class Context>
ContextMemoryAddress WASMFunctionParser::parseMemoryAddress(Context& context, MemoryAccessOffsetMode offsetMode)
{
    uint32_t offset = 0;
    if (offsetMode == MemoryAccessOffsetMode::WithOffset)
        READ_COMPACT_UINT32_OR_FAIL(offset, "Cannot read the address offset.");
    ContextExpression index = parseExpressionI32(context);
    PROPAGATE_ERROR();
    return ContextMemoryAddress(index, offset);
}

template <class Context>
ContextExpression WASMFunctionParser::parseLoad(Context& context, WASMExpressionType expressionType, WASMMemoryType memoryType, MemoryAccessOffsetMode offsetMode, MemoryAccessConversion conversion)
{
    FAIL_IF_FALSE(m_module->arrayBuffer(), "An ArrayBuffer is not provided.");
    const ContextMemoryAddress& memoryAddress = parseMemoryAddress(context, offsetMode);
    PROPAGATE_ERROR();
    return context.buildLoad(memoryAddress, expressionType, memoryType, conversion);
}

template <class Context>
ContextExpression WASMFunctionParser::parseStore(Context& context, WASMOpKind opKind, WASMExpressionType expressionType, WASMMemoryType memoryType, MemoryAccessOffsetMode offsetMode)
{
    FAIL_IF_FALSE(m_module->arrayBuffer(), "An ArrayBuffer is not provided.");
    const ContextMemoryAddress& memoryAddress = parseMemoryAddress(context, offsetMode);
    PROPAGATE_ERROR();

    ContextExpression value = parseExpression(context, expressionType);
    PROPAGATE_ERROR();
    return context.buildStore(opKind, memoryAddress, expressionType, memoryType, value);
}

template <class Context>
ContextExpressionList WASMFunctionParser::parseCallArguments(Context& context, const Vector<WASMType>& arguments)
{
    ContextExpressionList argumentList;
    for (size_t i = 0; i < arguments.size(); ++i) {
        ContextExpression expression = parseExpression(context, WASMExpressionType(arguments[i]));
        PROPAGATE_ERROR();
        context.appendExpressionList(argumentList, expression);
    }
    return argumentList;
}

template <class Context>
ContextExpression WASMFunctionParser::parseCallInternal(Context& context, WASMOpKind opKind, WASMExpressionType returnType)
{
    uint32_t functionIndex;
    READ_COMPACT_UINT32_OR_FAIL(functionIndex, "Cannot read the function index.");
    FAIL_IF_FALSE(functionIndex < m_module->functionDeclarations().size(), "The function index is incorrect.");
    const WASMSignature& signature = m_module->signatures()[m_module->functionDeclarations()[functionIndex].signatureIndex];
    if (opKind == WASMOpKind::Expression)
        FAIL_IF_FALSE(signature.returnType == returnType, "Wrong return type.");

    ContextExpressionList argumentList = parseCallArguments(context, signature.arguments);
    PROPAGATE_ERROR();
    return context.buildCallInternal(functionIndex, argumentList, signature, returnType);
}

template <class Context>
ContextExpression WASMFunctionParser::parseCallIndirect(Context& context, WASMOpKind opKind, WASMExpressionType returnType)
{
    uint32_t functionPointerTableIndex;
    READ_COMPACT_UINT32_OR_FAIL(functionPointerTableIndex, "Cannot read the function pointer table index.");
    FAIL_IF_FALSE(functionPointerTableIndex < m_module->functionPointerTables().size(), "The function pointer table index is incorrect.");
    const WASMFunctionPointerTable& functionPointerTable = m_module->functionPointerTables()[functionPointerTableIndex];
    const WASMSignature& signature = m_module->signatures()[functionPointerTable.signatureIndex];
    if (opKind == WASMOpKind::Expression)
        FAIL_IF_FALSE(signature.returnType == returnType, "Wrong return type.");

    ContextExpression index = parseExpressionI32(context);
    PROPAGATE_ERROR();

    ContextExpressionList argumentList = parseCallArguments(context, signature.arguments);
    PROPAGATE_ERROR();
    return context.buildCallIndirect(functionPointerTableIndex, index, argumentList, signature, returnType);
}

template <class Context>
ContextExpression WASMFunctionParser::parseCallImport(Context& context, WASMOpKind opKind, WASMExpressionType returnType)
{
    uint32_t functionImportSignatureIndex;
    READ_COMPACT_UINT32_OR_FAIL(functionImportSignatureIndex, "Cannot read the function import signature index.");
    FAIL_IF_FALSE(functionImportSignatureIndex < m_module->functionImportSignatures().size(), "The function import signature index is incorrect.");
    const WASMFunctionImportSignature& functionImportSignature = m_module->functionImportSignatures()[functionImportSignatureIndex];
    const WASMSignature& signature = m_module->signatures()[functionImportSignature.signatureIndex];
    if (opKind == WASMOpKind::Expression)
        FAIL_IF_FALSE(signature.returnType == returnType, "Wrong return type.");

    ContextExpressionList argumentList = parseCallArguments(context, signature.arguments);
    PROPAGATE_ERROR();
    return context.buildCallImport(functionImportSignature.functionImportIndex, argumentList, signature, returnType);
}

template <class Context>
ContextExpression WASMFunctionParser::parseConditional(Context& context, WASMExpressionType expressionType)
{
    ContextJumpTarget elseTarget;
    ContextJumpTarget end;

    ContextExpression condition = parseExpressionI32(context);
    PROPAGATE_ERROR();

    context.jumpToTargetIf(Context::JumpCondition::Zero, condition, elseTarget);

    parseExpression(context, expressionType);
    PROPAGATE_ERROR();
    
    context.jumpToTarget(end);
    context.linkTarget(elseTarget);

    // We use discard() here to decrement the stack top in the baseline JIT.
    context.discard(UNUSED);
    parseExpression(context, expressionType);
    PROPAGATE_ERROR();
    
    context.linkTarget(end);
    return UNUSED;
}

template <class Context>
ContextExpression WASMFunctionParser::parseComma(Context& context, WASMExpressionType expressionType)
{
    WASMExpressionType leftExpressionType;
    READ_EXPRESSION_TYPE_OR_FAIL(leftExpressionType, "Cannot read the expression type.");
    ContextExpression leftExpression = parseExpression(context, leftExpressionType);
    PROPAGATE_ERROR();
    if (leftExpressionType != WASMExpressionType::Void)
        context.discard(leftExpression);
    return parseExpression(context, expressionType);
}

template <class Context>
ContextExpression WASMFunctionParser::parseConvertType(Context& context, WASMExpressionType fromType, WASMExpressionType toType, WASMTypeConversion conversion)
{
    ContextExpression expression = parseExpression(context, fromType);
    PROPAGATE_ERROR();

    return context.buildConvertType(expression, fromType, toType, conversion);
}

} // namespace JSC

#endif // ENABLE(WEBASSEMBLY)
