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

#pragma once

#include "DirectArgumentsOffset.h"
#include "ScopeOffset.h"
#include "VirtualRegister.h"
#include <wtf/HashMap.h>

namespace JSC {

enum class VarKind : uint8_t {
    Invalid,
    Scope,
    Stack,
    DirectArgument
};

class VarOffset {
public:
    VarOffset()
        : m_kind(VarKind::Invalid)
        , m_offset(UINT_MAX)
    {
    }
    
    VarOffset(WTF::HashTableDeletedValueType)
        : m_kind(VarKind::Invalid)
        , m_offset(0)
    {
    }
    
    explicit VarOffset(VirtualRegister stackOffset)
    {
        if (!stackOffset.isValid()) {
            m_kind = VarKind::Invalid;
            m_offset = UINT_MAX;
        } else {
            m_kind = VarKind::Stack;
            m_offset = stackOffset.offset();
        }
    }
    
    explicit VarOffset(ScopeOffset scopeOffset)
    {
        if (!scopeOffset) {
            m_kind = VarKind::Invalid;
            m_offset = UINT_MAX;
        } else {
            m_kind = VarKind::Scope;
            m_offset = scopeOffset.offset();
        }
    }
    
    explicit VarOffset(DirectArgumentsOffset capturedArgumentsOffset)
    {
        if (!capturedArgumentsOffset) {
            m_kind = VarKind::Invalid;
            m_offset = UINT_MAX;
        } else {
            m_kind = VarKind::DirectArgument;
            m_offset = capturedArgumentsOffset.offset();
        }
    }
    
    static VarOffset assemble(VarKind kind, unsigned offset)
    {
        VarOffset result;
        result.m_kind = kind;
        result.m_offset = offset;
        result.checkSanity();
        return result;
    }
    
    bool isValid() const
    {
        return m_kind != VarKind::Invalid;
    }
    
    bool operator!() const
    {
        return !isValid();
    }
    
    VarKind kind() const { return m_kind; }
    
    bool isStack() const
    {
        return m_kind == VarKind::Stack;
    }
    
    bool isScope() const
    {
        return m_kind == VarKind::Scope;
    }
    
    bool isDirectArgument() const
    {
        return m_kind == VarKind::DirectArgument;
    }
    
    VirtualRegister stackOffsetUnchecked() const
    {
        if (!isStack())
            return VirtualRegister();
        return VirtualRegister(m_offset);
    }
    
    ScopeOffset scopeOffsetUnchecked() const
    {
        if (!isScope())
            return ScopeOffset();
        return ScopeOffset(m_offset);
    }
    
    DirectArgumentsOffset capturedArgumentsOffsetUnchecked() const
    {
        if (!isDirectArgument())
            return DirectArgumentsOffset();
        return DirectArgumentsOffset(m_offset);
    }
    
    VirtualRegister stackOffset() const
    {
        ASSERT(isStack());
        return VirtualRegister(m_offset);
    }
    
    ScopeOffset scopeOffset() const
    {
        ASSERT(isScope());
        return ScopeOffset(m_offset);
    }
    
    DirectArgumentsOffset capturedArgumentsOffset() const
    {
        ASSERT(isDirectArgument());
        return DirectArgumentsOffset(m_offset);
    }
    
    unsigned rawOffset() const
    {
        ASSERT(isValid());
        return m_offset;
    }
    
    void checkSanity() const
    {
        if (ASSERT_DISABLED)
            return;
        
        switch (m_kind) {
        case VarKind::Invalid:
            ASSERT(m_offset == UINT_MAX);
            return;
        case VarKind::Scope:
            ASSERT(scopeOffset());
            return;
        case VarKind::Stack:
            ASSERT(stackOffset().isValid());
            return;
        case VarKind::DirectArgument:
            ASSERT(capturedArgumentsOffset());
            return;
        }
        
        ASSERT_NOT_REACHED();
    }
    
    bool operator==(const VarOffset& other) const
    {
        return m_kind == other.m_kind
            && m_offset == other.m_offset;
    }
    
    bool operator!=(const VarOffset& other) const
    {
        return !(*this == other);
    }
    
    unsigned hash() const
    {
        return WTF::IntHash<unsigned>::hash((static_cast<unsigned>(m_kind) << 20) + m_offset);
    }
    
    bool isHashTableDeletedValue() const
    {
        return m_kind == VarKind::Invalid && !m_offset;
    }
    
    void dump(PrintStream&) const;
    
private:
    VarKind m_kind;
    unsigned m_offset;
};

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

} // namespace JSC

namespace WTF {

void printInternal(PrintStream&, JSC::VarKind);

template<typename T> struct DefaultHash;
template<> struct DefaultHash<JSC::VarOffset> {
    typedef JSC::VarOffsetHash Hash;
};

template<typename T> struct HashTraits;
template<> struct HashTraits<JSC::VarOffset> : SimpleClassHashTraits<JSC::VarOffset> {
    static const bool emptyValueIsZero = false;
};

} // namespace WTF
