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

#include "config.h"
#include "CallFrameShuffleData.h"

#if ENABLE(JIT)

#include "BaselineJITRegisters.h"
#include "BytecodeStructs.h"
#include "CodeBlock.h"
#include "RegisterAtOffsetList.h"

namespace JSC {

void CallFrameShuffleData::setupCalleeSaveRegisters(const RegisterAtOffsetList* registerSaveLocations)
{
    RegisterSet calleeSaveRegisters { RegisterSet::vmCalleeSaveRegisters() };

    for (size_t i = 0; i < registerSaveLocations->registerCount(); ++i) {
        RegisterAtOffset entry { registerSaveLocations->at(i) };
        if (!calleeSaveRegisters.get(entry.reg()))
            continue;

        int saveSlotIndexInCPURegisters = entry.offsetAsIndex();

#if USE(JSVALUE64)
        // CPU registers are the same size as virtual registers
        VirtualRegister saveSlot { saveSlotIndexInCPURegisters };
        registers[entry.reg()]
            = ValueRecovery::displacedInJSStack(saveSlot, DataFormatJS);
#elif USE(JSVALUE32_64)
        // On 32-bit architectures, 2 callee saved GPRs may be packed into the same slot
        if (entry.reg().isGPR()) {
            static_assert(!PayloadOffset || !TagOffset);
            static_assert(PayloadOffset == 4 || TagOffset == 4);
            bool inTag = (saveSlotIndexInCPURegisters & 1) == !!TagOffset;
            if (saveSlotIndexInCPURegisters < 0)
                saveSlotIndexInCPURegisters -= 1; // Round towards -inf
            VirtualRegister saveSlot { saveSlotIndexInCPURegisters / 2 };
            registers[entry.reg()] = ValueRecovery::calleeSaveGPRDisplacedInJSStack(saveSlot, inTag);
        } else {
            ASSERT(!(saveSlotIndexInCPURegisters & 1)); // Should be at an even offset
            VirtualRegister saveSlot { saveSlotIndexInCPURegisters / 2 };
            registers[entry.reg()] = ValueRecovery::displacedInJSStack(saveSlot, DataFormatDouble);
        }
#endif
    }

    for (Reg reg = Reg::first(); reg <= Reg::last(); reg = reg.next()) {
        if (!calleeSaveRegisters.get(reg))
            continue;

        if (registers[reg])
            continue;

#if USE(JSVALUE64)
        registers[reg] = ValueRecovery::inRegister(reg, DataFormatJS);
#elif USE(JSVALUE32_64)
        registers[reg] = ValueRecovery::inRegister(reg, reg.isGPR() ? DataFormatInt32 : DataFormatDouble);
#endif
    }
}

CallFrameShuffleData CallFrameShuffleData::createForBaselineOrLLIntTailCall(const OpTailCall& bytecode, unsigned numParameters)
{
    CallFrameShuffleData shuffleData;
    shuffleData.numPassedArgs = bytecode.m_argc;
    shuffleData.numParameters = numParameters;
#if USE(JSVALUE64)
    shuffleData.numberTagRegister = GPRInfo::numberTagRegister;
#endif
    shuffleData.numLocals = bytecode.m_argv - sizeof(CallerFrameAndPC) / sizeof(Register);
    shuffleData.args.resize(bytecode.m_argc);
    for (unsigned i = 0; i < bytecode.m_argc; ++i) {
        shuffleData.args[i] =
            ValueRecovery::displacedInJSStack(
                virtualRegisterForArgumentIncludingThis(i) - bytecode.m_argv,
                DataFormatJS);
    }
#if USE(JSVALUE64)
    shuffleData.callee = ValueRecovery::inGPR(BaselineJITRegisters::Call::calleeJSR.payloadGPR(), DataFormatJS);
#elif USE(JSVALUE32_64)
    shuffleData.callee = ValueRecovery::inPair(BaselineJITRegisters::Call::calleeJSR.tagGPR(), BaselineJITRegisters::Call::calleeJSR.payloadGPR());
#endif
    shuffleData.setupCalleeSaveRegisters(&RegisterAtOffsetList::llintBaselineCalleeSaveRegisters());
    shuffleData.shrinkToFit();
    return shuffleData;
}

} // namespace JSC

#endif // ENABLE(JIT)
