/*
 * 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. 
 */

#include "config.h"
#include "B3MemoryValue.h"

#if ENABLE(B3_JIT)

#include "B3MemoryValueInlines.h"
#include "B3ValueInlines.h"

namespace JSC { namespace B3 {

MemoryValue::~MemoryValue()
{
}

bool MemoryValue::isLegalOffsetImpl(int64_t offset) const
{
    return B3::isRepresentableAs<OffsetType>(offset) && isLegalOffset(static_cast<OffsetType>(offset));
}

Type MemoryValue::accessType() const
{
    if (isLoad())
        return type();
    // This happens to work for atomics, too. That's why AtomicValue does not need to override this.
    return child(0)->type();
}

Bank MemoryValue::accessBank() const
{
    return bankForType(accessType());
}

size_t MemoryValue::accessByteSize() const
{
    return bytes(accessWidth());
}

void MemoryValue::dumpMeta(CommaPrinter& comma, PrintStream& out) const
{
    if (m_offset)
        out.print(comma, "offset = ", m_offset);
    if ((isLoad() && effects().reads != range())
        || (isStore() && effects().writes != range())
        || isExotic())
        out.print(comma, "range = ", range());
    if (isExotic())
        out.print(comma, "fenceRange = ", fenceRange());
}

// Use this form for Load (but not Load8Z, Load8S, or any of the Loads that have a suffix that
// describes the returned type).
MemoryValue::MemoryValue(MemoryValue::MemoryValueLoad, Kind kind, Type type, Origin origin, Value* pointer, MemoryValue::OffsetType offset, HeapRange range, HeapRange fenceRange)
    : Value(CheckedOpcode, kind, type, One, origin, pointer)
    , m_offset(offset)
    , m_range(range)
    , m_fenceRange(fenceRange)
{
    if (ASSERT_ENABLED) {
        switch (kind.opcode()) {
        case Load:
            break;
        case Load8Z:
        case Load8S:
        case Load16Z:
        case Load16S:
            ASSERT(type == Int32);
            break;
        case Store8:
        case Store16:
        case Store:
            ASSERT(type == Void);
            break;
        default:
            ASSERT_NOT_REACHED();
        }
    }
}

// Use this form for loads where the return type is implied.
MemoryValue::MemoryValue(MemoryValue::MemoryValueLoadImplied, Kind kind, Origin origin, Value* pointer, MemoryValue::OffsetType offset, HeapRange range, HeapRange fenceRange)
    : MemoryValue(kind, Int32, origin, pointer, offset, range, fenceRange)
{
    if (ASSERT_ENABLED) {
        switch (kind.opcode()) {
        case Load8Z:
        case Load8S:
        case Load16Z:
        case Load16S:
            break;
        default:
            ASSERT_NOT_REACHED();
        }
    }
}

// Use this form for stores.
MemoryValue::MemoryValue(MemoryValue::MemoryValueStore, Kind kind, Origin origin, Value* value, Value* pointer, MemoryValue::OffsetType offset, HeapRange range, HeapRange fenceRange)
    : Value(CheckedOpcode, kind, Void, Two, origin, value, pointer)
    , m_offset(offset)
    , m_range(range)
    , m_fenceRange(fenceRange)
{
    ASSERT(B3::isStore(kind.opcode()));
}

} } // namespace JSC::B3

#endif // ENABLE(B3_JIT)
