/*
 * Copyright (C) 2011, 2013 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. 
 */

#ifndef DFGGenerationInfo_h
#define DFGGenerationInfo_h

#if ENABLE(DFG_JIT)

#include "DFGJITCompiler.h"
#include "DFGMinifiedID.h"
#include "DFGVariableEvent.h"
#include "DFGVariableEventStream.h"
#include "DataFormat.h"

namespace JSC { namespace DFG {

// === GenerationInfo ===
//
// This class is used to track the current status of live values during code generation.
// Can provide information as to whether a value is in machine registers, and if so which,
// whether a value has been spilled to the RegisterFile, and if so may be able to provide
// details of the format in memory (all values are spilled in a boxed form, but we may be
// able to track the type of box), and tracks how many outstanding uses of a value remain,
// so that we know when the value is dead and the machine registers associated with it
// may be released.
class GenerationInfo {
public:
    GenerationInfo()
        : m_node(0)
        , m_useCount(0)
        , m_registerFormat(DataFormatNone)
        , m_spillFormat(DataFormatNone)
        , m_canFill(false)
        , m_bornForOSR(false)
        , m_isConstant(false)
    {
    }

    void initConstant(Node* node, uint32_t useCount)
    {
        m_node = node;
        m_useCount = useCount;
        m_registerFormat = DataFormatNone;
        m_spillFormat = DataFormatNone;
        m_canFill = true;
        m_bornForOSR = false;
        m_isConstant = true;
        ASSERT(m_useCount);
    }
    void initGPR(Node* node, uint32_t useCount, GPRReg gpr, DataFormat format)
    {
        ASSERT(gpr != InvalidGPRReg);
        m_node = node;
        m_useCount = useCount;
        m_registerFormat = format;
        m_spillFormat = DataFormatNone;
        m_canFill = false;
        u.gpr = gpr;
        m_bornForOSR = false;
        m_isConstant = false;
        ASSERT(m_useCount);
    }
    void initInt32(Node* node, uint32_t useCount, GPRReg gpr)
    {
        initGPR(node, useCount, gpr, DataFormatInt32);
    }
    void initInt52(Node* node, uint32_t useCount, GPRReg reg, DataFormat format)
    {
        ASSERT(format == DataFormatInt52 || format == DataFormatStrictInt52);
        initGPR(node, useCount, reg, format);
    }
    void initInt52(Node* node, uint32_t useCount, GPRReg reg)
    {
        initGPR(node, useCount, reg, DataFormatInt52);
    }
    void initStrictInt52(Node* node, uint32_t useCount, GPRReg reg)
    {
        initGPR(node, useCount, reg, DataFormatStrictInt52);
    }
#if USE(JSVALUE64)
    void initJSValue(Node* node, uint32_t useCount, GPRReg gpr, DataFormat format = DataFormatJS)
    {
        ASSERT(format & DataFormatJS);
        initGPR(node, useCount, gpr, format);
    }
#elif USE(JSVALUE32_64)
    void initJSValue(Node* node, uint32_t useCount, GPRReg tagGPR, GPRReg payloadGPR, DataFormat format = DataFormatJS)
    {
        ASSERT(format & DataFormatJS);

        m_node = node;
        m_useCount = useCount;
        m_registerFormat = format;
        m_spillFormat = DataFormatNone;
        m_canFill = false;
        u.v.tagGPR = tagGPR;
        u.v.payloadGPR = payloadGPR;
        m_bornForOSR = false;
        m_isConstant = false;
        ASSERT(m_useCount);
    }
#endif
    void initCell(Node* node, uint32_t useCount, GPRReg gpr)
    {
        initGPR(node, useCount, gpr, DataFormatCell);
    }
    void initBoolean(Node* node, uint32_t useCount, GPRReg gpr)
    {
        initGPR(node, useCount, gpr, DataFormatBoolean);
    }
    void initDouble(Node* node, uint32_t useCount, FPRReg fpr)
    {
        ASSERT(fpr != InvalidFPRReg);
        m_node = node;
        m_useCount = useCount;
        m_registerFormat = DataFormatDouble;
        m_spillFormat = DataFormatNone;
        m_canFill = false;
        u.fpr = fpr;
        m_bornForOSR = false;
        m_isConstant = false;
        ASSERT(m_useCount);
    }
    void initStorage(Node* node, uint32_t useCount, GPRReg gpr)
    {
        initGPR(node, useCount, gpr, DataFormatStorage);
    }

    // Get the node that produced this value.
    Node* node() { return m_node; }
    
    void noticeOSRBirth(VariableEventStream& stream, Node* node, VirtualRegister virtualRegister)
    {
        if (m_node != node)
            return;
        if (!alive())
            return;
        if (m_bornForOSR)
            return;
        
        m_bornForOSR = true;
        
        if (m_isConstant)
            appendBirth(stream);
        else if (m_registerFormat != DataFormatNone)
            appendFill(BirthToFill, stream);
        else if (m_spillFormat != DataFormatNone)
            appendSpill(BirthToSpill, stream, virtualRegister);
    }

    // Mark the value as having been used (decrement the useCount).
    // Returns true if this was the last use of the value, and any
    // associated machine registers may be freed.
    bool use(VariableEventStream& stream)
    {
        ASSERT(m_useCount);
        bool result = !--m_useCount;
        
        if (result && m_bornForOSR) {
            ASSERT(m_node);
            stream.appendAndLog(VariableEvent::death(MinifiedID(m_node)));
        }
        
        return result;
    }

    // Used to check the operands of operations to see if they are on
    // their last use; in some cases it may be safe to reuse the same
    // machine register for the result of the operation.
    uint32_t useCount()
    {
        ASSERT(m_useCount);
        return m_useCount;
    }

    // Get the format of the value in machine registers (or 'none').
    DataFormat registerFormat() { return m_registerFormat; }
    // Get the format of the value as it is spilled in the JSStack (or 'none').
    DataFormat spillFormat() { return m_spillFormat; }
    
    bool isFormat(DataFormat expectedFormat)
    {
        return registerFormat() == expectedFormat || spillFormat() == expectedFormat;
    }
    
    bool isJSFormat(DataFormat expectedFormat)
    {
        return JSC::isJSFormat(registerFormat(), expectedFormat) || JSC::isJSFormat(spillFormat(), expectedFormat);
    }
    
    bool isJSInt32()
    {
        return isJSFormat(DataFormatJSInt32);
    }
    
    bool isInt52()
    {
        return isFormat(DataFormatInt52);
    }
    
    bool isStrictInt52()
    {
        return isFormat(DataFormatStrictInt52);
    }
    
    bool isJSDouble()
    {
        return isJSFormat(DataFormatJSDouble);
    }
    
    bool isJSCell()
    {
        return isJSFormat(DataFormatJSCell);
    }
    
    bool isJSBoolean()
    {
        return isJSFormat(DataFormatJSBoolean);
    }
    
    bool isUnknownJS()
    {
        return spillFormat() == DataFormatNone
            ? registerFormat() == DataFormatJS || registerFormat() == DataFormatNone
            : spillFormat() == DataFormatJS;
    }

    // Get the machine resister currently holding the value.
#if USE(JSVALUE64)
    GPRReg gpr() { ASSERT(m_registerFormat && m_registerFormat != DataFormatDouble); return u.gpr; }
    FPRReg fpr() { ASSERT(m_registerFormat == DataFormatDouble); return u.fpr; }
    JSValueRegs jsValueRegs() { ASSERT(m_registerFormat & DataFormatJS); return JSValueRegs(u.gpr); }
#elif USE(JSVALUE32_64)
    GPRReg gpr() { ASSERT(!(m_registerFormat & DataFormatJS) && m_registerFormat != DataFormatDouble); return u.gpr; }
    GPRReg tagGPR() { ASSERT(m_registerFormat & DataFormatJS); return u.v.tagGPR; }
    GPRReg payloadGPR() { ASSERT(m_registerFormat & DataFormatJS); return u.v.payloadGPR; }
    FPRReg fpr() { ASSERT(m_registerFormat == DataFormatDouble || m_registerFormat == DataFormatJSDouble); return u.fpr; }
    JSValueRegs jsValueRegs() { ASSERT(m_registerFormat & DataFormatJS); return JSValueRegs(u.v.tagGPR, u.v.payloadGPR); }
#endif

    // Check whether a value needs spilling in order to free up any associated machine registers.
    bool needsSpill()
    {
        // This should only be called on values that are currently in a register.
        ASSERT(m_registerFormat != DataFormatNone);
        // Constants do not need spilling, nor do values that have already been
        // spilled to the JSStack.
        return !m_canFill;
    }

    // Called when a VirtualRegister is being spilled to the JSStack for the first time.
    void spill(VariableEventStream& stream, VirtualRegister virtualRegister, DataFormat spillFormat)
    {
        // We shouldn't be spill values that don't need spilling.
        ASSERT(!m_canFill);
        ASSERT(m_spillFormat == DataFormatNone);
        // We should only be spilling values that are currently in machine registers.
        ASSERT(m_registerFormat != DataFormatNone);

        m_registerFormat = DataFormatNone;
        m_spillFormat = spillFormat;
        m_canFill = true;
        
        if (m_bornForOSR)
            appendSpill(Spill, stream, virtualRegister);
    }

    // Called on values that don't need spilling (constants and values that have
    // already been spilled), to mark them as no longer being in machine registers.
    void setSpilled(VariableEventStream& stream, VirtualRegister virtualRegister)
    {
        // Should only be called on values that don't need spilling, and are currently in registers.
        ASSERT(m_canFill && m_registerFormat != DataFormatNone);
        m_registerFormat = DataFormatNone;
        
        if (m_bornForOSR)
            appendSpill(Spill, stream, virtualRegister);
    }
    
    void killSpilled()
    {
        m_spillFormat = DataFormatNone;
        m_canFill = false;
    }
    
    void fillGPR(VariableEventStream& stream, GPRReg gpr, DataFormat format)
    {
        ASSERT(gpr != InvalidGPRReg);
        m_registerFormat = format;
        u.gpr = gpr;
        if (m_bornForOSR)
            appendFill(Fill, stream);
    }

    // Record that this value is filled into machine registers,
    // tracking which registers, and what format the value has.
#if USE(JSVALUE64)
    void fillJSValue(VariableEventStream& stream, GPRReg gpr, DataFormat format = DataFormatJS)
    {
        ASSERT(format & DataFormatJS);
        fillGPR(stream, gpr, format);
    }
#elif USE(JSVALUE32_64)
    void fillJSValue(VariableEventStream& stream, GPRReg tagGPR, GPRReg payloadGPR, DataFormat format = DataFormatJS)
    {
        ASSERT(format & DataFormatJS);
        m_registerFormat = format;
        u.v.tagGPR = tagGPR; // FIXME: for JSValues with known type (boolean, integer, cell etc.) no tagGPR is needed?
        u.v.payloadGPR = payloadGPR;
        
        if (m_bornForOSR)
            appendFill(Fill, stream);
    }
    void fillCell(VariableEventStream& stream, GPRReg gpr)
    {
        fillGPR(stream, gpr, DataFormatCell);
    }
#endif
    void fillInt32(VariableEventStream& stream, GPRReg gpr)
    {
        fillGPR(stream, gpr, DataFormatInt32);
    }
    void fillInt52(VariableEventStream& stream, GPRReg gpr, DataFormat format)
    {
        ASSERT(format == DataFormatInt52 || format == DataFormatStrictInt52);
        fillGPR(stream, gpr, format);
    }
    void fillInt52(VariableEventStream& stream, GPRReg gpr)
    {
        fillGPR(stream, gpr, DataFormatInt52);
    }
    void fillStrictInt52(VariableEventStream& stream, GPRReg gpr)
    {
        fillGPR(stream, gpr, DataFormatStrictInt52);
    }
    void fillBoolean(VariableEventStream& stream, GPRReg gpr)
    {
        fillGPR(stream, gpr, DataFormatBoolean);
    }
    void fillDouble(VariableEventStream& stream, FPRReg fpr)
    {
        ASSERT(fpr != InvalidFPRReg);
        m_registerFormat = DataFormatDouble;
        u.fpr = fpr;
        
        if (m_bornForOSR)
            appendFill(Fill, stream);
    }
    void fillStorage(VariableEventStream& stream, GPRReg gpr)
    {
        fillGPR(stream, gpr, DataFormatStorage);
    }

    bool alive()
    {
        return m_useCount;
    }

    ValueRecovery recovery(VirtualRegister spillSlot) const
    {
        if (m_isConstant)
            return ValueRecovery::constant(m_node->constant()->value());

        if (m_registerFormat == DataFormatDouble)
            return ValueRecovery::inFPR(u.fpr, DataFormatDouble);

#if USE(JSVALUE32_64)
        if (m_registerFormat & DataFormatJS) {
            if (m_registerFormat == DataFormatJS)
                return ValueRecovery::inPair(u.v.tagGPR, u.v.payloadGPR);
            return ValueRecovery::inGPR(u.v.payloadGPR, static_cast<DataFormat>(m_registerFormat & ~DataFormatJS));
        }
#endif
        if (m_registerFormat)
            return ValueRecovery::inGPR(u.gpr, m_registerFormat);

        ASSERT(m_spillFormat);

        return ValueRecovery::displacedInJSStack(spillSlot, m_spillFormat);
    }

private:
    void appendBirth(VariableEventStream& stream)
    {
        stream.appendAndLog(VariableEvent::birth(MinifiedID(m_node)));
    }
    
    void appendFill(VariableEventKind kind, VariableEventStream& stream)
    {
        ASSERT(m_bornForOSR);
        
        if (m_registerFormat == DataFormatDouble) {
            stream.appendAndLog(VariableEvent::fillFPR(kind, MinifiedID(m_node), u.fpr));
            return;
        }
#if USE(JSVALUE32_64)
        if (m_registerFormat & DataFormatJS) {
            stream.appendAndLog(VariableEvent::fillPair(kind, MinifiedID(m_node), u.v.tagGPR, u.v.payloadGPR));
            return;
        }
#endif
        stream.appendAndLog(VariableEvent::fillGPR(kind, MinifiedID(m_node), u.gpr, m_registerFormat));
    }
    
    void appendSpill(VariableEventKind kind, VariableEventStream& stream, VirtualRegister virtualRegister)
    {
        stream.appendAndLog(VariableEvent::spill(kind, MinifiedID(m_node), virtualRegister, m_spillFormat));
    }
    
    // The node whose result is stored in this virtual register.
    Node* m_node;
    uint32_t m_useCount;
    DataFormat m_registerFormat;
    DataFormat m_spillFormat;
    bool m_canFill;
    bool m_bornForOSR;
    bool m_isConstant;
    union {
        GPRReg gpr;
        FPRReg fpr;
#if USE(JSVALUE32_64)
        struct {
            GPRReg tagGPR;
            GPRReg payloadGPR;
        } v;
#endif
    } u;
};

} } // namespace JSC::DFG

#endif
#endif
