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

#if ENABLE(WEBASSEMBLY)

#include "AirCode.h"
#include "AllowMacroScratchRegisterUsage.h"
#include "B3ArgumentRegValue.h"
#include "B3BasicBlock.h"
#include "B3Const64Value.h"
#include "B3ConstrainedValue.h"
#include "B3MemoryValue.h"
#include "B3PatchpointValue.h"
#include "B3Procedure.h"
#include "B3StackmapGenerationParams.h"
#include "CallFrame.h"
#include "LinkBuffer.h"
#include "RegisterSet.h"
#include "WasmFormat.h"
#include "WasmSignature.h"

namespace JSC { namespace Wasm {

typedef unsigned (*NextOffset)(unsigned currentOffset);

template<unsigned headerSize, NextOffset updateOffset>
class CallingConvention {
public:
    CallingConvention(Vector<Reg>&& gprArgs, Vector<Reg>&& fprArgs, RegisterSet&& calleeSaveRegisters)
        : m_gprArgs(WTFMove(gprArgs))
        , m_fprArgs(WTFMove(fprArgs))
        , m_calleeSaveRegisters(WTFMove(calleeSaveRegisters))
    {
    }

private:
    B3::ValueRep marshallArgumentImpl(const Vector<Reg>& regArgs, size_t& count, size_t& stackOffset) const
    {
        if (count < regArgs.size())
            return B3::ValueRep::reg(regArgs[count++]);

        count++;
        B3::ValueRep result = B3::ValueRep::stackArgument(stackOffset);
        stackOffset = updateOffset(stackOffset);
        return result;
    }

    B3::ValueRep marshallArgument(B3::Type type, size_t& gpArgumentCount, size_t& fpArgumentCount, size_t& stackOffset) const
    {
        switch (type) {
        case B3::Int32:
        case B3::Int64:
            return marshallArgumentImpl(m_gprArgs, gpArgumentCount, stackOffset);
        case B3::Float:
        case B3::Double:
            return marshallArgumentImpl(m_fprArgs, fpArgumentCount, stackOffset);
        case B3::Void:
            break;
        }
        RELEASE_ASSERT_NOT_REACHED();
    }

public:
    static unsigned headerSizeInBytes() { return headerSize; }
    void setupFrameInPrologue(CodeLocationDataLabelPtr<WasmEntryPtrTag>* calleeMoveLocation, B3::Procedure& proc, B3::Origin origin, B3::BasicBlock* block) const
    {
        static_assert(CallFrameSlot::callee * sizeof(Register) < headerSize, "We rely on this here for now.");
        static_assert(CallFrameSlot::codeBlock * sizeof(Register) < headerSize, "We rely on this here for now.");

        B3::PatchpointValue* getCalleePatchpoint = block->appendNew<B3::PatchpointValue>(proc, B3::Int64, origin);
        getCalleePatchpoint->resultConstraint = B3::ValueRep::SomeRegister;
        getCalleePatchpoint->effects = B3::Effects::none();
        getCalleePatchpoint->setGenerator(
            [=] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
                GPRReg result = params[0].gpr();
                MacroAssembler::DataLabelPtr moveLocation = jit.moveWithPatch(MacroAssembler::TrustedImmPtr(nullptr), result);
                jit.addLinkTask([calleeMoveLocation, moveLocation] (LinkBuffer& linkBuffer) {
                    *calleeMoveLocation = linkBuffer.locationOf<WasmEntryPtrTag>(moveLocation);
                });
            });

        B3::Value* framePointer = block->appendNew<B3::Value>(proc, B3::FramePointer, origin);
        B3::Value* offsetOfCallee = block->appendNew<B3::Const64Value>(proc, origin, CallFrameSlot::callee * sizeof(Register));
        block->appendNew<B3::MemoryValue>(proc, B3::Store, origin,
            getCalleePatchpoint,
            block->appendNew<B3::Value>(proc, B3::Add, origin, framePointer, offsetOfCallee));

        // FIXME: We shouldn't have to store zero into the CodeBlock* spot in the call frame,
        // but there are places that interpret non-null CodeBlock slot to mean a valid CodeBlock.
        // When doing unwinding, we'll need to verify that the entire runtime is OK with a non-null
        // CodeBlock not implying that the CodeBlock is valid.
        // https://bugs.webkit.org/show_bug.cgi?id=165321
        B3::Value* offsetOfCodeBlock = block->appendNew<B3::Const64Value>(proc, origin, CallFrameSlot::codeBlock * sizeof(Register));
        block->appendNew<B3::MemoryValue>(proc, B3::Store, origin,
            block->appendNew<B3::Const64Value>(proc, origin, 0),
            block->appendNew<B3::Value>(proc, B3::Add, origin, framePointer, offsetOfCodeBlock));
    }

    template<typename Functor>
    void loadArguments(const Signature& signature, B3::Procedure& proc, B3::BasicBlock* block, B3::Origin origin, const Functor& functor) const
    {
        B3::Value* framePointer = block->appendNew<B3::Value>(proc, B3::FramePointer, origin);

        size_t gpArgumentCount = 0;
        size_t fpArgumentCount = 0;
        size_t stackOffset = headerSize;

        for (size_t i = 0; i < signature.argumentCount(); ++i) {
            B3::Type type = toB3Type(signature.argument(i));
            B3::Value* argument;
            B3::ValueRep rep = marshallArgument(type, gpArgumentCount, fpArgumentCount, stackOffset);
            if (rep.isReg()) {
                argument = block->appendNew<B3::ArgumentRegValue>(proc, origin, rep.reg());
                if (type == B3::Int32 || type == B3::Float)
                    argument = block->appendNew<B3::Value>(proc, B3::Trunc, origin, argument);
            } else {
                ASSERT(rep.isStackArgument());
                B3::Value* address = block->appendNew<B3::Value>(proc, B3::Add, origin, framePointer,
                    block->appendNew<B3::Const64Value>(proc, origin, rep.offsetFromSP()));
                argument = block->appendNew<B3::MemoryValue>(proc, B3::Load, type, origin, address);
            }
            functor(argument, i);
        }
    }

    // It's expected that the pachpointFunctor sets the generator for the call operation.
    template<typename Functor>
    B3::Value* setupCall(B3::Procedure& proc, B3::BasicBlock* block, B3::Origin origin, const Vector<B3::Value*>& arguments, B3::Type returnType, const Functor& patchpointFunctor) const
    {
        size_t gpArgumentCount = 0;
        size_t fpArgumentCount = 0;
        size_t stackOffset = headerSize - sizeof(CallerFrameAndPC);

        Vector<B3::ConstrainedValue> constrainedArguments;
        for (B3::Value* argument : arguments) {
            B3::ValueRep rep = marshallArgument(argument->type(), gpArgumentCount, fpArgumentCount, stackOffset);
            constrainedArguments.append(B3::ConstrainedValue(argument, rep));
        }

        proc.requestCallArgAreaSizeInBytes(WTF::roundUpToMultipleOf(stackAlignmentBytes(), stackOffset));

        B3::PatchpointValue* patchpoint = block->appendNew<B3::PatchpointValue>(proc, returnType, origin);
        patchpoint->clobberEarly(RegisterSet::macroScratchRegisters());
        patchpoint->clobberLate(RegisterSet::volatileRegistersForJSCall());
        patchpointFunctor(patchpoint);
        patchpoint->appendVector(constrainedArguments);

        switch (returnType) {
        case B3::Void:
            return nullptr;
        case B3::Float:
        case B3::Double:
            patchpoint->resultConstraint = B3::ValueRep::reg(FPRInfo::returnValueFPR);
            break;
        case B3::Int32:
        case B3::Int64:
            patchpoint->resultConstraint = B3::ValueRep::reg(GPRInfo::returnValueGPR);
            break;
        }
        return patchpoint;
    }

    const Vector<Reg> m_gprArgs;
    const Vector<Reg> m_fprArgs;
    const RegisterSet m_calleeSaveRegisters;
    const RegisterSet m_callerSaveRegisters;
};

// FIXME: Share more code with CallingConvention above:
// https://bugs.webkit.org/show_bug.cgi?id=194065
template<unsigned headerSize, NextOffset updateOffset>
class CallingConventionAir {
public:
    CallingConventionAir(Vector<Reg>&& gprArgs, Vector<Reg>&& fprArgs, RegisterSet&& calleeSaveRegisters)
        : m_gprArgs(WTFMove(gprArgs))
        , m_fprArgs(WTFMove(fprArgs))
        , m_calleeSaveRegisters(WTFMove(calleeSaveRegisters))
    {
        RegisterSet scratch = RegisterSet::allGPRs();
        scratch.exclude(RegisterSet::macroScratchRegisters());
        scratch.exclude(RegisterSet::reservedHardwareRegisters());
        scratch.exclude(RegisterSet::stackRegisters());
        for (Reg reg : m_gprArgs)
            scratch.clear(reg);
        for (Reg reg : m_calleeSaveRegisters)
            scratch.clear(reg);
        for (Reg reg : scratch)
            m_scratchGPRs.append(reg);
        RELEASE_ASSERT(m_scratchGPRs.size() >= 2);
    }

    GPRReg prologueScratch(size_t i) const { return m_scratchGPRs[i].gpr(); }

private:
    template <typename RegFunc, typename StackFunc>
    void marshallArgumentImpl(const Vector<Reg>& regArgs, size_t& count, size_t& stackOffset, const RegFunc& regFunc, const StackFunc& stackFunc) const
    {
        if (count < regArgs.size()) {
            regFunc(regArgs[count++]);
            return;
        }

        count++;
        stackFunc(stackOffset);
        stackOffset = updateOffset(stackOffset);
    }

    template <typename RegFunc, typename StackFunc>
    void marshallArgument(Type type, size_t& gpArgumentCount, size_t& fpArgumentCount, size_t& stackOffset, const RegFunc& regFunc, const StackFunc& stackFunc) const
    {
        switch (type) {
        case Type::I32:
        case Type::I64:
        case Type::Anyref:
        case Wasm::Funcref:
            marshallArgumentImpl(m_gprArgs, gpArgumentCount, stackOffset, regFunc, stackFunc);
            break;
        case Type::F32:
        case Type::F64:
            marshallArgumentImpl(m_fprArgs, fpArgumentCount, stackOffset, regFunc, stackFunc);
            break;
        default:
            RELEASE_ASSERT_NOT_REACHED();
        }
    }

public:
    static unsigned headerSizeInBytes() { return headerSize; }

    template<typename Functor>
    void loadArguments(const Signature& signature, const Functor& functor) const
    {
        size_t gpArgumentCount = 0;
        size_t fpArgumentCount = 0;
        size_t stackOffset = headerSize;

        for (size_t i = 0; i < signature.argumentCount(); ++i) {
            marshallArgument(signature.argument(i), gpArgumentCount, fpArgumentCount, stackOffset,
                [&] (Reg reg) {
                    functor(B3::Air::Tmp(reg), i);
                },
                [&] (size_t stackOffset) {
                    functor(B3::Air::Arg::addr(B3::Air::Tmp(GPRInfo::callFrameRegister), stackOffset), i);
                });
        }
    }

    // It's expected that the pachpointFunctor sets the generator for the call operation.
    template<typename Functor>
    void setupCall(B3::Air::Code& code, Type returnType, B3::PatchpointValue* patchpoint, const Vector<B3::Air::Tmp>& args, const Functor& functor) const
    {
        size_t gpArgumentCount = 0;
        size_t fpArgumentCount = 0;
        size_t stackOffset = headerSize - sizeof(CallerFrameAndPC);

        for (auto tmp : args) {
            marshallArgument(tmp.isGP() ? Type::I64 : Type::F64, gpArgumentCount, fpArgumentCount, stackOffset,
                [&] (Reg reg) {
                    functor(tmp, B3::ValueRep::reg(reg));
                },
                [&] (size_t stackOffset) {
                    functor(tmp, B3::ValueRep::stackArgument(stackOffset));
                });
        }

        code.requestCallArgAreaSizeInBytes(WTF::roundUpToMultipleOf(stackAlignmentBytes(), stackOffset));

        patchpoint->clobberEarly(RegisterSet::macroScratchRegisters());
        patchpoint->clobberLate(RegisterSet::volatileRegistersForJSCall());

        switch (returnType) {
        case Type::Void:
            break;
        case Type::F32:
        case Type::F64:
            patchpoint->resultConstraint = B3::ValueRep::reg(FPRInfo::returnValueFPR);
            break;
        case Type::I32:
        case Type::I64:
        case Type::Anyref:
        case Wasm::Funcref:
            patchpoint->resultConstraint = B3::ValueRep::reg(GPRInfo::returnValueGPR);
            break;
        default:
            RELEASE_ASSERT_NOT_REACHED();
        }
    }

    const Vector<Reg> m_gprArgs;
    const Vector<Reg> m_fprArgs;
    Vector<Reg> m_scratchGPRs;
    const RegisterSet m_calleeSaveRegisters;
    const RegisterSet m_callerSaveRegisters;
};

inline unsigned nextJSCOffset(unsigned currentOffset)
{
    return currentOffset + sizeof(Register);
}

constexpr unsigned jscHeaderSize = ExecState::headerSizeInRegisters * sizeof(Register);

using JSCCallingConvention = CallingConvention<jscHeaderSize, nextJSCOffset>;
using WasmCallingConvention = JSCCallingConvention;
const JSCCallingConvention& jscCallingConvention();
const WasmCallingConvention& wasmCallingConvention();

using JSCCallingConventionAir = CallingConventionAir<jscHeaderSize, nextJSCOffset>;
using WasmCallingConventionAir = JSCCallingConventionAir;
const JSCCallingConventionAir& jscCallingConventionAir();
const WasmCallingConventionAir& wasmCallingConventionAir();

} } // namespace JSC::Wasm

#endif // ENABLE(WEBASSEMBLY)
