/*
 * Copyright (C) 2011-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 "CallFrame.h"
#include "VirtualRegister.h"

#include <wtf/FixedVector.h>
#include <wtf/PrintStream.h>
#include <wtf/Vector.h>

namespace JSC {

template<typename T> struct OperandValueTraits;

constexpr unsigned maxNumCheckpointTmps = 4;

// A OperandKind::Tmp is one that exists for exiting to a checkpoint but does not exist between bytecodes.
enum class OperandKind : uint32_t { Argument, Local, Tmp }; // Keep bit-width in sync with Operand::operandKindBits' definition.
static constexpr OperandKind lastOperandKind = OperandKind::Tmp;

class Operand {
public:
    static constexpr unsigned kindBits = WTF::getMSBSetConstexpr(static_cast<std::underlying_type_t<OperandKind>>(lastOperandKind)) + 1;
    static constexpr unsigned maxBits = 32 + kindBits;
    static_assert(maxBits == 34);

    Operand() = default;
    Operand(const Operand&) = default;

    Operand(VirtualRegister operand)
        : Operand(operand.isLocal() ? OperandKind::Local : OperandKind::Argument, operand.offset())
    { }

    Operand(OperandKind kind, int operand)
#if CPU(LITTLE_ENDIAN)
        : m_operand(operand)
        , m_kind(kind)
#else
        : m_kind(kind)
        , m_operand(operand)
#endif
    { 
        ASSERT(kind == OperandKind::Tmp || VirtualRegister(operand).isLocal() == (kind == OperandKind::Local));
    }
    static Operand tmp(uint32_t index) { return Operand(OperandKind::Tmp, index); }

    Operand& operator=(const Operand&) = default;

    OperandKind kind() const { return m_kind; }
    int value() const { return m_operand; }
    VirtualRegister virtualRegister() const
    {
        ASSERT(m_kind != OperandKind::Tmp);
        return VirtualRegister(m_operand);
    }
    uint64_t asBits() const
    {
        uint64_t bits = bitwise_cast<uint64_t>(*this);
        ASSERT(bits < (1ULL << maxBits));
        return bits;
    }
    static Operand fromBits(uint64_t value);

    bool isTmp() const { return kind() == OperandKind::Tmp; }
    bool isArgument() const { return kind() == OperandKind::Argument; }
    bool isLocal() const { return kind() == OperandKind::Local && virtualRegister().isLocal(); }
    bool isHeader() const { return kind() != OperandKind::Tmp && virtualRegister().isHeader(); }
    bool isConstant() const { return kind() != OperandKind::Tmp && virtualRegister().isConstant(); }

    int toArgument() const { ASSERT(isArgument()); return virtualRegister().toArgument(); }
    int toLocal() const { ASSERT(isLocal()); return virtualRegister().toLocal(); }

    inline bool isValid() const;

    inline bool operator==(const Operand&) const;

    void dump(PrintStream&) const;

private:
#if CPU(LITTLE_ENDIAN)
    int m_operand { VirtualRegister::invalidVirtualRegister };
    OperandKind m_kind { OperandKind::Argument };
#else
    OperandKind m_kind { OperandKind::Argument };
    int m_operand { VirtualRegister::invalidVirtualRegister };
#endif
};

ALWAYS_INLINE bool Operand::operator==(const Operand& other) const
{
    if (kind() != other.kind())
        return false;
    if (isTmp())
        return value() == other.value();
    return virtualRegister() == other.virtualRegister();
}

inline bool Operand::isValid() const
{
    if (isTmp())
        return value() >= 0;
    return virtualRegister().isValid();
}

inline Operand Operand::fromBits(uint64_t value)
{
    Operand result = bitwise_cast<Operand>(value);
    ASSERT(result.isValid());
    return result;
}

static_assert(sizeof(Operand) == sizeof(uint64_t), "Operand::asBits() relies on this.");

enum OperandsLikeTag { OperandsLike };

template<typename T, typename StorageArg = std::conditional_t<std::is_same_v<T, bool>, FastBitVector, Vector<T, 0, UnsafeVectorOverflow>>>
class Operands {
public:
    template<typename, typename> friend class Operands;

    using Storage = StorageArg;
    using RefType = std::conditional_t<std::is_same_v<T, bool>, FastBitReference, T&>;
    using ConstRefType = std::conditional_t<std::is_same_v<T, bool>, bool, const T&>;

    Operands() = default;

    explicit Operands(size_t numArguments, size_t numLocals, size_t numTmps)
        : m_values(numArguments + numLocals + numTmps)
        , m_numArguments(numArguments)
        , m_numLocals(numLocals)
    {
        if (!WTF::VectorTraits<T>::needsInitialization)
            m_values.fill(T());
    }

    explicit Operands(size_t numArguments, size_t numLocals, size_t numTmps, const T& initialValue)
        : m_values(numArguments + numLocals + numTmps)
        , m_numArguments(numArguments)
        , m_numLocals(numLocals)
    {
        m_values.fill(initialValue);
    }
    
    template<typename U, typename V>
    explicit Operands(OperandsLikeTag, const Operands<U, V>& other, const T& initialValue = T())
        : m_values(other.size())
        , m_numArguments(other.numberOfArguments())
        , m_numLocals(other.numberOfLocals())
    {
        m_values.fill(initialValue);
    }

    template<typename U>
    explicit Operands(const Operands<T, U>& other)
        : m_values(other.m_values)
        , m_numArguments(other.m_numArguments)
        , m_numLocals(other.m_numLocals)
    {
    }

    size_t numberOfArguments() const { return m_numArguments; }
    size_t numberOfLocals() const { return m_numLocals; }
    size_t numberOfTmps() const { return m_values.size() - numberOfArguments() - numberOfLocals(); }

    size_t tmpIndex(size_t idx) const
    {
        ASSERT(idx < numberOfTmps());
        return idx + numberOfArguments() + numberOfLocals();
    }
    size_t argumentIndex(size_t idx) const
    {
        ASSERT(idx < numberOfArguments());
        return idx;
    }
    
    size_t localIndex(size_t idx) const
    {
        ASSERT(idx < numberOfLocals());
        return numberOfArguments() + idx;
    }

    RefType tmp(size_t idx) { return m_values[tmpIndex(idx)]; }
    ConstRefType tmp(size_t idx) const { return m_values[tmpIndex(idx)]; }
    
    RefType argument(size_t idx) { return m_values[argumentIndex(idx)]; }
    ConstRefType argument(size_t idx) const { return m_values[argumentIndex(idx)]; }
    
    RefType local(size_t idx) { return m_values[localIndex(idx)]; }
    ConstRefType local(size_t idx) const { return m_values[localIndex(idx)]; }
    
    template<OperandKind operandKind>
    size_t sizeFor() const
    {
        switch (operandKind) {
        case OperandKind::Tmp:
            return numberOfTmps();
        case OperandKind::Argument:
            return numberOfArguments();
        case OperandKind::Local:
            return numberOfLocals();
        }
        RELEASE_ASSERT_NOT_REACHED();
        return 0;
    }
    template<OperandKind operandKind>
    RefType atFor(size_t idx)
    {
        switch (operandKind) {
        case OperandKind::Tmp:
            return tmp(idx);
        case OperandKind::Argument:
            return argument(idx);
        case OperandKind::Local:
            return local(idx);
        }
        RELEASE_ASSERT_NOT_REACHED();
        return tmp(0);
    }
    template<OperandKind operandKind>
    ConstRefType atFor(size_t idx) const
    {
        switch (operandKind) {
        case OperandKind::Tmp:
            return tmp(idx);
        case OperandKind::Argument:
            return argument(idx);
        case OperandKind::Local:
            return local(idx);
        }
        RELEASE_ASSERT_NOT_REACHED();
        return tmp(0);
    }

    void ensureLocals(size_t size, const T& ensuredValue = T())
    {
        if (size <= numberOfLocals())
            return;

        size_t newSize = numberOfArguments() + numberOfTmps() + size;
        size_t oldNumLocals = numberOfLocals();
        size_t oldNumTmps = numberOfTmps();
        m_values.grow(newSize);
        for (size_t i = 0; i < oldNumTmps; ++i)
            m_values[newSize - 1 - i] = m_values[tmpIndex(oldNumTmps - 1 - i)];

        m_numLocals = size;
        if (ensuredValue != T() || !WTF::VectorTraits<T>::needsInitialization) {
            for (size_t i = 0; i < size - oldNumLocals; ++i)
                m_values[localIndex(oldNumLocals + i)] = ensuredValue;
        }
    }

    void ensureTmps(size_t size, const T& ensuredValue = T())
    {
        if (size <= numberOfTmps())
            return;

        size_t oldSize = m_values.size();
        size_t newSize = numberOfArguments() + numberOfLocals() + size;
        m_values.grow(newSize);

        if (ensuredValue != T() || !WTF::VectorTraits<T>::needsInitialization) {
            for (size_t i = oldSize; i < newSize; ++i)
                m_values[i] = ensuredValue;
        }
    }
    
    void setLocal(size_t idx, const T& value)
    {
        ensureLocals(idx + 1);
        local(idx) = value;
    }
    
    T getLocal(size_t idx)
    {
        return idx >= numberOfLocals() ? T() : local(idx);
    }
    
    void setArgumentFirstTime(size_t idx, const T& value)
    {
        ASSERT(m_values[idx] == T());
        argument(idx) = value;
    }
    
    void setLocalFirstTime(size_t idx, const T& value)
    {
        ASSERT(idx >= numberOfLocals() || local(idx) == T());
        setLocal(idx, value);
    }

    RefType getForOperandIndex(size_t index) { return m_values[index]; }
    ConstRefType getForOperandIndex(size_t index) const { return const_cast<Operands*>(this)->getForOperandIndex(index); }

    size_t operandIndex(VirtualRegister operand) const
    {
        if (operand.isArgument())
            return argumentIndex(operand.toArgument());
        return localIndex(operand.toLocal());
    }
    
    size_t operandIndex(Operand op) const
    {
        if (!op.isTmp())
            return operandIndex(op.virtualRegister());
        return tmpIndex(op.value());
    }
    
    RefType operand(VirtualRegister operand)
    {
        if (operand.isArgument())
            return argument(operand.toArgument());
        return local(operand.toLocal());
    }

    RefType operand(Operand op)
    {
        if (!op.isTmp())
            return operand(op.virtualRegister());
        return tmp(op.value());
    }

    ConstRefType operand(VirtualRegister operand) const { return const_cast<Operands*>(this)->operand(operand); }
    ConstRefType operand(Operand operand) const { return const_cast<Operands*>(this)->operand(operand); }
    
    bool hasOperand(VirtualRegister operand) const
    {
        if (operand.isArgument())
            return true;
        return static_cast<size_t>(operand.toLocal()) < numberOfLocals();
    }
    bool hasOperand(Operand op) const
    {
        if (op.isTmp()) {
            ASSERT(op.value() >= 0);
            return static_cast<size_t>(op.value()) < numberOfTmps();
        }
        return hasOperand(op.virtualRegister());
    }
    
    void setOperand(Operand operand, const T& value)
    {
        this->operand(operand) = value;
    }

    size_t size() const { return m_values.size(); }
    ConstRefType at(size_t index) const { return m_values[index]; }
    RefType at(size_t index) { return m_values[index]; }
    ConstRefType operator[](size_t index) const { return at(index); }
    RefType operator[](size_t index) { return at(index); }

    Operand operandForIndex(size_t index) const
    {
        if (index < numberOfArguments())
            return virtualRegisterForArgumentIncludingThis(index);
        else if (index < numberOfLocals() + numberOfArguments())
            return virtualRegisterForLocal(index - numberOfArguments());
        return Operand::tmp(index - (numberOfLocals() + numberOfArguments()));
    }

    void fill(T value)
    {
        for (size_t i = 0; i < m_values.size(); ++i)
            m_values[i] = value;
    }
    
    void clear()
    {
        fill(T());
    }
    
    bool operator==(const Operands& other) const
    {
        ASSERT(numberOfArguments() == other.numberOfArguments());
        ASSERT(numberOfLocals() == other.numberOfLocals());
        ASSERT(numberOfTmps() == other.numberOfTmps());
        
        return m_values == other.m_values;
    }

    bool operator!=(const Operands& other) const
    {
        return !(*this == other);
    }
    
    void dumpInContext(PrintStream& out, DumpContext* context) const;
    void dump(PrintStream& out) const;
    
private:
    // The first m_numArguments of m_values are arguments, the next m_numLocals are locals, and the rest are tmps.
    Storage m_values;
    unsigned m_numArguments { 0 };
    unsigned m_numLocals { 0 };
};

template<typename T>
using FixedOperands = Operands<T, std::conditional_t<std::is_same_v<T, bool>, FastBitVector, FixedVector<T>>>;

} // namespace JSC
