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

#pragma once

#include "Opcode.h"
#include "OpcodeSize.h"

namespace JSC {

struct JSOpcodeTraits {
    using OpcodeID = ::JSC::OpcodeID;
    static constexpr OpcodeID numberOfBytecodesWithCheckpoints = static_cast<OpcodeID>(NUMBER_OF_BYTECODE_WITH_CHECKPOINTS);
    static constexpr OpcodeID numberOfBytecodesWithMetadata = static_cast<OpcodeID>(NUMBER_OF_BYTECODE_WITH_METADATA);
    static_assert(numberOfBytecodesWithCheckpoints <= numberOfBytecodesWithMetadata);
    static constexpr OpcodeID wide16 = op_wide16;
    static constexpr OpcodeID wide32 = op_wide32;
    static constexpr const unsigned* opcodeLengths = ::JSC::opcodeLengths;
    static constexpr const char* const* opcodeNames = ::JSC::opcodeNames;
};

struct WasmOpcodeTraits {
    using OpcodeID = WasmOpcodeID;
    static constexpr OpcodeID numberOfBytecodesWithCheckpoints = static_cast<OpcodeID>(NUMBER_OF_WASM_WITH_CHECKPOINTS);
    static constexpr OpcodeID numberOfBytecodesWithMetadata = static_cast<OpcodeID>(NUMBER_OF_WASM_WITH_METADATA);
    static_assert(numberOfBytecodesWithCheckpoints <= numberOfBytecodesWithMetadata);
    static constexpr OpcodeID wide16 = wasm_wide16;
    static constexpr OpcodeID wide32 = wasm_wide32;
    static constexpr const unsigned* opcodeLengths = wasmOpcodeLengths;
    static constexpr const char* const* opcodeNames = wasmOpcodeNames;
};


template<typename Opcode>
struct BaseInstruction {

    struct Metadata { };

protected:
    BaseInstruction()
    { }

private:
    template<OpcodeSize Width>
    class Impl {
    public:
        template<typename Traits = JSOpcodeTraits>
        typename Traits::OpcodeID opcodeID() const { return static_cast<typename Traits::OpcodeID>(m_opcode); }

    private:
        typename TypeBySize<OpcodeSize::Narrow>::unsignedType m_opcode;
    };

public:
    template<typename Traits = JSOpcodeTraits>
    typename Traits::OpcodeID opcodeID() const
    {
        if (isWide32<Traits>())
            return wide32<Traits>()->template opcodeID<Traits>();
        if (isWide16<Traits>())
            return wide16<Traits>()->template opcodeID<Traits>();
        return narrow()->template opcodeID<Traits>();
    }

    template<typename Traits = JSOpcodeTraits>
    const char* name() const
    {
        return Traits::opcodeNames[opcodeID()];
    }

    template<typename Traits = JSOpcodeTraits>
    bool isWide16() const
    {
        return narrow()->template opcodeID<Traits>() == Traits::wide16;
    }

    template<typename Traits = JSOpcodeTraits>
    bool isWide32() const
    {
        return narrow()->template opcodeID<Traits>() == Traits::wide32;
    }

    template<typename Traits = JSOpcodeTraits>
    OpcodeSize width() const
    {
        if (isWide32<Traits>())
            return OpcodeSize::Wide32;
        return isWide16<Traits>() ? OpcodeSize::Wide16 : OpcodeSize::Narrow;
    }

    template<typename Traits = JSOpcodeTraits>
    bool hasMetadata() const
    {
        return opcodeID<Traits>() < Traits::numberOfBytecodesWithMetadata;
    }

    template<typename Traits = JSOpcodeTraits>
    bool hasCheckpoints() const
    {
        return opcodeID<Traits>() < Traits::numberOfBytecodesWithCheckpoints;
    }

    template<typename Traits = JSOpcodeTraits>
    int sizeShiftAmount() const
    {
        if (isWide32<Traits>())
            return 2;
        if (isWide16<Traits>())
            return 1;
        return 0;
    }

    template<typename Traits = JSOpcodeTraits>
    size_t size() const
    {
        auto sizeShiftAmount = this->sizeShiftAmount<Traits>();
        size_t prefixSize = sizeShiftAmount ? 1 : 0;
        size_t operandSize = static_cast<size_t>(1) << sizeShiftAmount;
        size_t sizeOfBytecode = 1;
        return sizeOfBytecode + (Traits::opcodeLengths[opcodeID<Traits>()] - 1) * operandSize + prefixSize;
    }

    template<class T, typename Traits = JSOpcodeTraits>
    bool is() const
    {
        return opcodeID<Traits>() == T::opcodeID;
    }

    template<class T, typename Traits = JSOpcodeTraits>
    T as() const
    {
        ASSERT((is<T, Traits>()));
        return T::decode(reinterpret_cast<const uint8_t*>(this));
    }

    template<class T, OpcodeSize width, typename Traits = JSOpcodeTraits>
    T asKnownWidth() const
    {
        ASSERT((is<T, Traits>()));
        return T(reinterpret_cast<const typename TypeBySize<width>::unsignedType*>(this + (width == OpcodeSize::Narrow ? 1 : 2)));
    }

    template<class T, typename Traits = JSOpcodeTraits>
    T* cast()
    {
        ASSERT((is<T, Traits>()));
        return bitwise_cast<T*>(this);
    }

    template<class T, typename Traits = JSOpcodeTraits>
    const T* cast() const
    {
        ASSERT((is<T, Traits>()));
        return reinterpret_cast<const T*>(this);
    }

    const Impl<OpcodeSize::Narrow>* narrow() const
    {
        return reinterpret_cast<const Impl<OpcodeSize::Narrow>*>(this);
    }

    template<typename Traits = JSOpcodeTraits>
    const Impl<OpcodeSize::Wide16>* wide16() const
    {

        ASSERT(isWide16<Traits>());
        return reinterpret_cast<const Impl<OpcodeSize::Wide16>*>(this + 1);
    }

    template<typename Traits = JSOpcodeTraits>
    const Impl<OpcodeSize::Wide32>* wide32() const
    {

        ASSERT(isWide32<Traits>());
        return reinterpret_cast<const Impl<OpcodeSize::Wide32>*>(this + 1);
    }
};

struct Instruction : public BaseInstruction<OpcodeID> {
};
static_assert(sizeof(Instruction) == 1, "So pointer math is the same as byte math");

struct WasmInstance : public BaseInstruction<WasmOpcodeID> {
};
static_assert(sizeof(WasmInstance) == 1, "So pointer math is the same as byte math");

} // namespace JSC
