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

#pragma once

#include "BytecodeGenerator.h"
#include "BytecodeStructs.h"
#include "InterpreterInlines.h"
#include "Opcode.h"
#include "PreciseJumpTargets.h"

namespace JSC {

#define SWITCH_JMP(CASE_OP, SWITCH_CASE, SWITCH_DEFAULT_OFFSET) \
    switch (instruction->opcodeID()) { \
    CASE_OP(OpJmp) \
    \
    CASE_OP(OpJtrue) \
    CASE_OP(OpJfalse) \
    CASE_OP(OpJeqNull) \
    CASE_OP(OpJneqNull) \
    CASE_OP(OpJundefinedOrNull) \
    CASE_OP(OpJnundefinedOrNull) \
    CASE_OP(OpJneqPtr) \
    \
    CASE_OP(OpJless) \
    CASE_OP(OpJlesseq) \
    CASE_OP(OpJgreater) \
    CASE_OP(OpJgreatereq) \
    CASE_OP(OpJnless) \
    CASE_OP(OpJnlesseq) \
    CASE_OP(OpJngreater) \
    CASE_OP(OpJngreatereq) \
    CASE_OP(OpJeq) \
    CASE_OP(OpJneq) \
    CASE_OP(OpJstricteq) \
    CASE_OP(OpJnstricteq) \
    CASE_OP(OpJbelow) \
    CASE_OP(OpJbeloweq) \
    case op_switch_imm: { \
        auto bytecode = instruction->as<OpSwitchImm>(); \
        auto& table = codeBlock->switchJumpTable(bytecode.m_tableIndex); \
        for (unsigned i = table.branchOffsets.size(); i--;) \
            SWITCH_CASE(table.branchOffsets[i]); \
        SWITCH_DEFAULT_OFFSET(OpSwitchImm); \
        break; \
    } \
    case op_switch_char: { \
        auto bytecode = instruction->as<OpSwitchChar>(); \
        auto& table = codeBlock->switchJumpTable(bytecode.m_tableIndex); \
        for (unsigned i = table.branchOffsets.size(); i--;) \
            SWITCH_CASE(table.branchOffsets[i]); \
        SWITCH_DEFAULT_OFFSET(OpSwitchChar); \
        break; \
    } \
    case op_switch_string: { \
        auto bytecode = instruction->as<OpSwitchString>(); \
        auto& table = codeBlock->stringSwitchJumpTable(bytecode.m_tableIndex); \
        auto iter = table.offsetTable.begin(); \
        auto end = table.offsetTable.end(); \
        for (; iter != end; ++iter) \
            SWITCH_CASE(iter->value.branchOffset); \
        SWITCH_DEFAULT_OFFSET(OpSwitchString); \
        break; \
    } \
    default: \
        break; \
    } \


template<typename Block>
inline int jumpTargetForInstruction(Block* codeBlock, const InstructionStream::Ref& instruction, unsigned target)
{
    if (target)
        return target;
    return codeBlock->outOfLineJumpOffset(instruction);
}

template<typename HashMap>
inline int jumpTargetForInstruction(HashMap& outOfLineJumpTargets, const InstructionStream::Ref& instruction, unsigned target)
{
    if (target)
        return target;
    ASSERT(outOfLineJumpTargets.contains(instruction.offset()));
    return outOfLineJumpTargets.get(instruction.offset());
}

template<typename Op, typename Block>
inline int jumpTargetForInstruction(Block&& codeBlock, const InstructionStream::Ref& instruction)
{
    auto bytecode = instruction->as<Op>();
    return jumpTargetForInstruction(codeBlock, instruction, bytecode.m_targetLabel);
}

template<typename Block, typename Function>
inline void extractStoredJumpTargetsForInstruction(Block&& codeBlock, const InstructionStream::Ref& instruction, const Function& function)
{
#define CASE_OP(__op) \
    case __op::opcodeID: \
        function(jumpTargetForInstruction<__op>(codeBlock, instruction)); \
        break;

#define SWITCH_CASE(__target) \
    function(__target)

#define SWITCH_DEFAULT_OFFSET(__op) \
    function(jumpTargetForInstruction(codeBlock, instruction, bytecode.m_defaultOffset)) \

SWITCH_JMP(CASE_OP, SWITCH_CASE, SWITCH_DEFAULT_OFFSET)

#undef CASE_OP
#undef SWITCH_CASE
#undef SWITCH_DEFAULT_OFFSET
}

template<typename Block, typename Function, typename CodeBlockOrHashMap>
inline void updateStoredJumpTargetsForInstruction(Block&& codeBlock, unsigned finalOffset, InstructionStream::MutableRef instruction, const Function& function, CodeBlockOrHashMap& codeBlockOrHashMap)
{
#define CASE_OP(__op) \
    case __op::opcodeID: { \
        int32_t target = jumpTargetForInstruction<__op>(codeBlockOrHashMap, instruction); \
        int32_t newTarget = function(target); \
        instruction->cast<__op>()->setTargetLabel(BoundLabel(newTarget), [&]() { \
            codeBlock->addOutOfLineJumpTarget(finalOffset + instruction.offset(), newTarget); \
            return BoundLabel(); \
        }); \
        break; \
    }

#define SWITCH_CASE(__target) \
    do { \
        int32_t target = __target; \
        __target = function(target); \
    } while (false)

#define SWITCH_DEFAULT_OFFSET(__op) \
    do { \
        int32_t target = jumpTargetForInstruction(codeBlockOrHashMap, instruction, bytecode.m_defaultOffset); \
        int32_t newTarget = function(target); \
        instruction->cast<__op>()->setDefaultOffset(BoundLabel(newTarget), [&]() { \
            codeBlock->addOutOfLineJumpTarget(finalOffset + instruction.offset(), newTarget); \
            return BoundLabel(); \
        }); \
    } while (false)

SWITCH_JMP(CASE_OP, SWITCH_CASE, SWITCH_DEFAULT_OFFSET)

#undef CASE_OP
#undef JMP_TARGET
}

template<typename Block, typename Function>
inline void updateStoredJumpTargetsForInstruction(Block* codeBlock, unsigned finalOffset, InstructionStream::MutableRef instruction, Function function)
{
    updateStoredJumpTargetsForInstruction(codeBlock, finalOffset, instruction, function, codeBlock);
}

} // namespace JSC
