/*
 * Copyright (C) 2015-2017 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

#if ENABLE(B3_JIT)

#include "B3Bank.h"
#include "FPRInfo.h"
#include "GPRInfo.h"
#include "Reg.h"
#include <wtf/HashMap.h>

namespace JSC { namespace B3 { namespace Air {

class Arg;
class Code;

// A Tmp is a generalization of a register. It can be used to refer to any GPR or FPR. It can also
// be used to refer to an unallocated register (i.e. a temporary). Like many Air classes, we use
// deliberately terse naming since we will have to use this name a lot.

class Tmp {
public:
    Tmp()
        : m_value(0)
    {
    }

    explicit Tmp(Reg reg)
    {
        if (reg) {
            if (reg.isGPR())
                m_value = encodeGPR(reg.gpr());
            else
                m_value = encodeFPR(reg.fpr());
        } else
            m_value = 0;
    }

    explicit Tmp(const Arg&);

    static Tmp gpTmpForIndex(unsigned index)
    {
        Tmp result;
        result.m_value = encodeGPTmp(index);
        return result;
    }

    static Tmp fpTmpForIndex(unsigned index)
    {
        Tmp result;
        result.m_value = encodeFPTmp(index);
        return result;
    }
    
    static Tmp tmpForIndex(Bank bank, unsigned index)
    {
        if (bank == GP)
            return gpTmpForIndex(index);
        ASSERT(bank == FP);
        return fpTmpForIndex(index);
    }

    explicit operator bool() const { return !!m_value; }
    
    bool isGP() const
    {
        return isEncodedGP(m_value);
    }

    bool isFP() const
    {
        return isEncodedFP(m_value);
    }

    // For null tmps, returns GP.
    Bank bank() const
    {
        return isFP() ? FP : GP;
    }

    bool isGPR() const
    {
        return isEncodedGPR(m_value);
    }

    bool isFPR() const
    {
        return isEncodedFPR(m_value);
    }

    bool isReg() const
    {
        return isGPR() || isFPR();
    }

    GPRReg gpr() const
    {
        return decodeGPR(m_value);
    }

    FPRReg fpr() const
    {
        return decodeFPR(m_value);
    }

    Reg reg() const
    {
        if (isGP())
            return gpr();
        return fpr();
    }

    bool hasTmpIndex() const
    {
        return !isReg();
    }

    unsigned gpTmpIndex() const
    {
        return decodeGPTmp(m_value);
    }

    unsigned fpTmpIndex() const
    {
        return decodeFPTmp(m_value);
    }
    
    unsigned tmpIndex(Bank bank) const
    {
        if (bank == GP)
            return gpTmpIndex();
        ASSERT(bank == FP);
        return fpTmpIndex();
    }

    unsigned tmpIndex() const
    {
        if (isGP())
            return gpTmpIndex();
        return fpTmpIndex();
    }
    
    template<Bank bank> class Indexed;
    template<Bank bank> class AbsolutelyIndexed;
    class LinearlyIndexed;
    
    template<Bank bank>
    Indexed<bank> indexed() const;
    
    template<Bank bank>
    AbsolutelyIndexed<bank> absolutelyIndexed() const;
    
    LinearlyIndexed linearlyIndexed(Code&) const;

    static unsigned indexEnd(Code&, Bank);
    static unsigned absoluteIndexEnd(Code&, Bank);
    static unsigned linearIndexEnd(Code&);
    
    bool isAlive() const
    {
        return !!*this;
    }

    bool operator==(const Tmp& other) const
    {
        return m_value == other.m_value;
    }

    bool operator!=(const Tmp& other) const
    {
        return !(*this == other);
    }

    void dump(PrintStream& out) const;

    Tmp(WTF::HashTableDeletedValueType)
        : m_value(std::numeric_limits<int>::max())
    {
    }

    bool isHashTableDeletedValue() const
    {
        return *this == Tmp(WTF::HashTableDeletedValue);
    }

    unsigned hash() const
    {
        return WTF::IntHash<int>::hash(m_value);
    }

    unsigned internalValue() const { return static_cast<unsigned>(m_value); }

    static Tmp tmpForInternalValue(unsigned index)
    {
        Tmp result;
        result.m_value = static_cast<int>(index);
        return result;
    }
    
    static Tmp tmpForAbsoluteIndex(Bank, unsigned);
    
    static Tmp tmpForLinearIndex(Code&, unsigned);
    
private:
    static int encodeGP(unsigned index)
    {
        return 1 + index;
    }

    static int encodeFP(unsigned index)
    {
        return -1 - index;
    }

    static int encodeGPR(GPRReg gpr)
    {
        return encodeGP(gpr - MacroAssembler::firstRegister());
    }

    static int encodeFPR(FPRReg fpr)
    {
        return encodeFP(fpr - MacroAssembler::firstFPRegister());
    }

    static int encodeGPTmp(unsigned index)
    {
        return encodeGPR(MacroAssembler::lastRegister()) + 1 + index;
    }

    static int encodeFPTmp(unsigned index)
    {
        return encodeFPR(MacroAssembler::lastFPRegister()) - 1 - index;
    }

    static bool isEncodedGP(int value)
    {
        return value > 0;
    }

    static bool isEncodedFP(int value)
    {
        return value < 0;
    }

    static bool isEncodedGPR(int value)
    {
        return isEncodedGP(value) && value <= encodeGPR(MacroAssembler::lastRegister());
    }

    static bool isEncodedFPR(int value)
    {
        return isEncodedFP(value) && value >= encodeFPR(MacroAssembler::lastFPRegister());
    }

    static bool isEncodedGPTmp(int value)
    {
        return isEncodedGP(value) && !isEncodedGPR(value);
    }

    static bool isEncodedFPTmp(int value)
    {
        return isEncodedFP(value) && !isEncodedFPR(value);
    }

    static GPRReg decodeGPR(int value)
    {
        ASSERT(isEncodedGPR(value));
        return static_cast<GPRReg>(
            (value - encodeGPR(MacroAssembler::firstRegister())) + MacroAssembler::firstRegister());
    }

    static FPRReg decodeFPR(int value)
    {
        ASSERT(isEncodedFPR(value));
        return static_cast<FPRReg>(
            (encodeFPR(MacroAssembler::firstFPRegister()) - value) +
            MacroAssembler::firstFPRegister());
    }

    static unsigned decodeGPTmp(int value)
    {
        ASSERT(isEncodedGPTmp(value));
        return value - (encodeGPR(MacroAssembler::lastRegister()) + 1);
    }

    static unsigned decodeFPTmp(int value)
    {
        ASSERT(isEncodedFPTmp(value));
        return (encodeFPR(MacroAssembler::lastFPRegister()) - 1) - value;
    }

    // 0: empty Tmp
    // positive: GPRs and then GP temps.
    // negative: FPRs and then FP temps.
    int m_value;
};

struct TmpHash {
    static unsigned hash(const Tmp& key) { return key.hash(); }
    static bool equal(const Tmp& a, const Tmp& b) { return a == b; }
    static const bool safeToCompareToEmptyOrDeleted = true;
};

} } } // namespace JSC::B3::Air

namespace WTF {

template<typename T> struct DefaultHash;
template<> struct DefaultHash<JSC::B3::Air::Tmp> {
    typedef JSC::B3::Air::TmpHash Hash;
};

template<typename T> struct HashTraits;
template<> struct HashTraits<JSC::B3::Air::Tmp> : SimpleClassHashTraits<JSC::B3::Air::Tmp> { };

} // namespace WTF

#endif // ENABLE(B3_JIT)
