/*
 * Copyright (C) 2011, 2013-2015 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 DFGValueSource_h
#define DFGValueSource_h

#if ENABLE(DFG_JIT)

#include "DFGCommon.h"
#include "DFGFlushFormat.h"
#include "DFGMinifiedID.h"
#include "DataFormat.h"
#include "SpeculatedType.h"
#include "ValueRecovery.h"

namespace JSC { namespace DFG {

enum ValueSourceKind {
    SourceNotSet,
    ValueInJSStack,
    Int32InJSStack,
    Int52InJSStack,
    CellInJSStack,
    BooleanInJSStack,
    DoubleInJSStack,
    SourceIsDead,
    HaveNode
};

static inline ValueSourceKind dataFormatToValueSourceKind(DataFormat dataFormat)
{
    switch (dataFormat) {
    case DataFormatInt32:
        return Int32InJSStack;
    case DataFormatInt52:
        return Int52InJSStack;
    case DataFormatDouble:
        return DoubleInJSStack;
    case DataFormatBoolean:
        return BooleanInJSStack;
    case DataFormatCell:
        return CellInJSStack;
    case DataFormatDead:
        return SourceIsDead;
    default:
        RELEASE_ASSERT(dataFormat & DataFormatJS);
        return ValueInJSStack;
    }
}

static inline DataFormat valueSourceKindToDataFormat(ValueSourceKind kind)
{
    switch (kind) {
    case ValueInJSStack:
        return DataFormatJS;
    case Int32InJSStack:
        return DataFormatInt32;
    case Int52InJSStack:
        return DataFormatInt52;
    case CellInJSStack:
        return DataFormatCell;
    case BooleanInJSStack:
        return DataFormatBoolean;
    case DoubleInJSStack:
        return DataFormatDouble;
    case SourceIsDead:
        return DataFormatDead;
    default:
        return DataFormatNone;
    }
}

static inline bool isInJSStack(ValueSourceKind kind)
{
    DataFormat format = valueSourceKindToDataFormat(kind);
    return format != DataFormatNone && format < DataFormatOSRMarker;
}

// Can this value be recovered without having to look at register allocation state or
// DFG node liveness?
static inline bool isTriviallyRecoverable(ValueSourceKind kind)
{
    return valueSourceKindToDataFormat(kind) != DataFormatNone;
}

class ValueSource {
public:
    ValueSource()
        : m_kind(SourceNotSet)
    {
    }
    
    explicit ValueSource(ValueSourceKind valueSourceKind)
        : m_kind(valueSourceKind)
    {
        ASSERT(kind() == SourceIsDead);
    }
    
    explicit ValueSource(MinifiedID id)
        : m_kind(HaveNode)
        , m_value(id.bits())
    {
        ASSERT(!!id);
        ASSERT(kind() == HaveNode);
    }
    
    ValueSource(ValueSourceKind valueSourceKind, VirtualRegister where)
        : m_kind(valueSourceKind)
        , m_value(static_cast<intptr_t>(where.offset()))
    {
        ASSERT(kind() != SourceNotSet);
        ASSERT(kind() != HaveNode);
    }
    
    static ValueSource forFlushFormat(VirtualRegister where, FlushFormat format)
    {
        switch (format) {
        case DeadFlush:
        case ConflictingFlush:
            return ValueSource(SourceIsDead);
        case FlushedJSValue:
            return ValueSource(ValueInJSStack, where);
        case FlushedDouble:
            return ValueSource(DoubleInJSStack, where);
        case FlushedInt32:
            return ValueSource(Int32InJSStack, where);
        case FlushedInt52:
            return ValueSource(Int52InJSStack, where);
        case FlushedCell:
            return ValueSource(CellInJSStack, where);
        case FlushedBoolean:
            return ValueSource(BooleanInJSStack, where);
        }
        RELEASE_ASSERT_NOT_REACHED();
        return ValueSource();
    }
    
    static ValueSource forDataFormat(VirtualRegister where, DataFormat dataFormat)
    {
        return ValueSource(dataFormatToValueSourceKind(dataFormat), where);
    }
    
    bool isSet() const
    {
        return kind() != SourceNotSet;
    }
    
    bool operator!() const { return !isSet(); }
    
    ValueSourceKind kind() const
    {
        return m_kind;
    }
    
    bool isInJSStack() const { return JSC::DFG::isInJSStack(kind()); }
    bool isTriviallyRecoverable() const { return JSC::DFG::isTriviallyRecoverable(kind()); }
    
    DataFormat dataFormat() const
    {
        return valueSourceKindToDataFormat(kind());
    }
    
    ValueRecovery valueRecovery() const
    {
        ASSERT(isTriviallyRecoverable());
        switch (kind()) {
        case SourceIsDead:
            return ValueRecovery::constant(jsUndefined());
            
        default:
            return ValueRecovery::displacedInJSStack(virtualRegister(), dataFormat());
        }
    }
    
    MinifiedID id() const
    {
        ASSERT(kind() == HaveNode);
        return MinifiedID::fromBits(m_value);
    }
    
    VirtualRegister virtualRegister() const
    {
        ASSERT(isInJSStack());
        return VirtualRegister(m_value);
    }
    
    void dump(PrintStream&) const;
    void dumpInContext(PrintStream&, DumpContext*) const;
    
private:
    ValueSourceKind m_kind;
    uintptr_t m_value;
};

} } // namespace JSC::DFG

#endif // ENABLE(DFG_JIT)

#endif // DFGValueSource_h

