/*
 * Copyright (C) 2011, 2012, 2013, 2015, 2016 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/PrintStream.h>
#include <wtf/Vector.h>

namespace JSC {

template<typename T> struct OperandValueTraits;

enum OperandKind { ArgumentOperand, LocalOperand };

enum OperandsLikeTag { OperandsLike };

template<typename T>
class Operands {
public:
    Operands()
        : m_numArguments(0) { }
    
    explicit Operands(size_t numArguments, size_t numLocals)
        : m_numArguments(numArguments)
    {
        if (WTF::VectorTraits<T>::needsInitialization) {
            m_values.resize(numArguments + numLocals);
        } else {
            m_values.fill(T(), numArguments + numLocals);
        }
    }

    explicit Operands(size_t numArguments, size_t numLocals, const T& initialValue)
        : m_numArguments(numArguments)
    {
        m_values.fill(initialValue, numArguments + numLocals);
    }
    
    template<typename U>
    explicit Operands(OperandsLikeTag, const Operands<U>& other)
        : m_numArguments(other.numberOfArguments())
    {
        m_values.fill(T(), other.numberOfArguments() + other.numberOfLocals());
    }
    
    size_t numberOfArguments() const { return m_numArguments; }
    size_t numberOfLocals() const { return m_values.size() - m_numArguments; }
    
    T& argument(size_t idx)
    {
        ASSERT(idx < m_numArguments);
        return m_values[idx];
    }
    const T& argument(size_t idx) const
    {
        ASSERT(idx < m_numArguments);
        return m_values[idx];
    }
    
    T& local(size_t idx) { return m_values[m_numArguments + idx]; }
    const T& local(size_t idx) const { return m_values[m_numArguments + idx]; }
    
    template<OperandKind operandKind>
    size_t sizeFor() const
    {
        if (operandKind == ArgumentOperand)
            return numberOfArguments();
        return numberOfLocals();
    }
    template<OperandKind operandKind>
    T& atFor(size_t idx)
    {
        if (operandKind == ArgumentOperand)
            return argument(idx);
        return local(idx);
    }
    template<OperandKind operandKind>
    const T& atFor(size_t idx) const
    {
        if (operandKind == ArgumentOperand)
            return argument(idx);
        return local(idx);
    }
    
    void ensureLocals(size_t size)
    {
        size_t oldSize = m_values.size();
        size_t newSize = m_numArguments + size;
        if (newSize <= oldSize)
            return;

        m_values.grow(newSize);
        if (!WTF::VectorTraits<T>::needsInitialization) {
            for (size_t i = oldSize; i < m_values.size(); ++i)
                m_values[i] = T();
        }
    }

    void ensureLocals(size_t size, const T& ensuredValue)
    {
        size_t oldSize = m_values.size();
        size_t newSize = m_numArguments + size;
        if (newSize <= oldSize)
            return;

        m_values.grow(newSize);
        for (size_t i = oldSize; i < m_values.size(); ++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);
    }
    
    T& operand(int operand)
    {
        if (operandIsArgument(operand))
            return argument(VirtualRegister(operand).toArgument());
        return local(VirtualRegister(operand).toLocal());
    }

    T& operand(VirtualRegister virtualRegister)
    {
        return operand(virtualRegister.offset());
    }

    const T& operand(int operand) const { return const_cast<const T&>(const_cast<Operands*>(this)->operand(operand)); }
    const T& operand(VirtualRegister operand) const { return const_cast<const T&>(const_cast<Operands*>(this)->operand(operand)); }
    
    bool hasOperand(int operand) const
    {
        if (operandIsArgument(operand))
            return true;
        return static_cast<size_t>(VirtualRegister(operand).toLocal()) < numberOfLocals();
    }
    bool hasOperand(VirtualRegister reg) const
    {
        return hasOperand(reg.offset());
    }
    
    void setOperand(int operand, const T& value)
    {
        this->operand(operand) = value;
    }
    
    void setOperand(VirtualRegister virtualRegister, const T& value)
    {
        setOperand(virtualRegister.offset(), value);
    }

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

    bool isArgument(size_t index) const { return index < m_numArguments; }
    bool isVariable(size_t index) const { return !isArgument(index); }
    int operandForIndex(size_t index) const
    {
        if (index < numberOfArguments())
            return virtualRegisterForArgument(index).offset();
        return virtualRegisterForLocal(index - numberOfArguments()).offset();
    }
    VirtualRegister virtualRegisterForIndex(size_t index) const
    {
        return VirtualRegister(operandForIndex(index));
    }
    
    void setOperandFirstTime(int operand, const T& value)
    {
        if (operandIsArgument(operand)) {
            setArgumentFirstTime(VirtualRegister(operand).toArgument(), value);
            return;
        }
        
        setLocalFirstTime(VirtualRegister(operand).toLocal(), value);
    }
    
    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());
        
        return m_values == other.m_values;
    }
    
    void dumpInContext(PrintStream& out, DumpContext* context) const;
    void dump(PrintStream& out) const;
    
private:
    // The first m_numArguments of m_values are arguments, the rest are locals.
    Vector<T, 24> m_values;
    unsigned m_numArguments;
};

} // namespace JSC
