/*
 * 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 "B3PatchpointSpecial.h"

#if ENABLE(B3_JIT)

#include "AirCode.h"
#include "AirGenerationContext.h"
#include "B3ProcedureInlines.h"
#include "B3StackmapGenerationParams.h"
#include "B3ValueInlines.h"

namespace JSC { namespace B3 {

using Arg = Air::Arg;
using Inst = Air::Inst;

PatchpointSpecial::PatchpointSpecial()
{
}

PatchpointSpecial::~PatchpointSpecial()
{
}

void PatchpointSpecial::forEachArg(Inst& inst, const ScopedLambda<Inst::EachArgCallback>& callback)
{
    const Procedure& procedure = code().proc();
    PatchpointValue* patchpoint = inst.origin->as<PatchpointValue>();
    unsigned argIndex = 1;

    Type type = patchpoint->type();
    for (; argIndex <= procedure.resultCount(type); ++argIndex) {
        Arg::Role role;
        if (patchpoint->resultConstraints[argIndex - 1].kind() == ValueRep::SomeEarlyRegister)
            role = Arg::EarlyDef;
        else
            role = Arg::Def;

        Type argType = type.isTuple() ? procedure.extractFromTuple(type, argIndex - 1) : type;
        callback(inst.args[argIndex], role, bankForType(argType), widthForType(argType));
    }

    forEachArgImpl(0, argIndex, inst, SameAsRep, WTF::nullopt, callback, WTF::nullopt);
    argIndex += inst.origin->numChildren();

    for (unsigned i = patchpoint->numGPScratchRegisters; i--;)
        callback(inst.args[argIndex++], Arg::Scratch, GP, conservativeWidth(GP));
    for (unsigned i = patchpoint->numFPScratchRegisters; i--;)
        callback(inst.args[argIndex++], Arg::Scratch, FP, conservativeWidth(FP));
}

bool PatchpointSpecial::isValid(Inst& inst)
{
    const Procedure& procedure = code().proc();
    PatchpointValue* patchpoint = inst.origin->as<PatchpointValue>();
    unsigned argIndex = 1;

    Type type = patchpoint->type();
    for (; argIndex <= procedure.resultCount(type); ++argIndex) {
        if (argIndex >= inst.args.size())
            return false;
        
        if (!isArgValidForType(inst.args[argIndex], type.isTuple() ? procedure.extractFromTuple(type, argIndex - 1) : type))
            return false;
        if (!isArgValidForRep(code(), inst.args[argIndex], patchpoint->resultConstraints[argIndex - 1]))
            return false;
    }

    if (!isValidImpl(0, argIndex, inst))
        return false;
    argIndex += patchpoint->numChildren();

    if (argIndex + patchpoint->numGPScratchRegisters + patchpoint->numFPScratchRegisters
        != inst.args.size())
        return false;

    for (unsigned i = patchpoint->numGPScratchRegisters; i--;) {
        Arg arg = inst.args[argIndex++];
        if (!arg.isGPTmp())
            return false;
    }
    for (unsigned i = patchpoint->numFPScratchRegisters; i--;) {
        Arg arg = inst.args[argIndex++];
        if (!arg.isFPTmp())
            return false;
    }

    return true;
}

bool PatchpointSpecial::admitsStack(Inst& inst, unsigned argIndex)
{
    ASSERT(argIndex);

    Type type = inst.origin->type();
    unsigned returnCount = code().proc().resultCount(type);

    if (argIndex <= returnCount) {
        switch (inst.origin->as<PatchpointValue>()->resultConstraints[argIndex - 1].kind()) {
        case ValueRep::WarmAny:
        case ValueRep::StackArgument:
            return true;
        case ValueRep::SomeRegister:
        case ValueRep::SomeRegisterWithClobber:
        case ValueRep::SomeEarlyRegister:
        case ValueRep::SomeLateRegister:
        case ValueRep::Register:
        case ValueRep::LateRegister:
            return false;
        default:
            RELEASE_ASSERT_NOT_REACHED();
            return false;
        }
    }

    return admitsStackImpl(0, returnCount + 1, inst, argIndex);
}

bool PatchpointSpecial::admitsExtendedOffsetAddr(Inst& inst, unsigned argIndex)
{
    return admitsStack(inst, argIndex);
}

CCallHelpers::Jump PatchpointSpecial::generate(Inst& inst, CCallHelpers& jit, Air::GenerationContext& context)
{
    const Procedure& procedure = code().proc();
    PatchpointValue* value = inst.origin->as<PatchpointValue>();
    ASSERT(value);

    Vector<ValueRep> reps;
    unsigned offset = 1;

    Type type = value->type();
    while (offset <= procedure.resultCount(type))
        reps.append(repForArg(*context.code, inst.args[offset++]));
    reps.appendVector(repsImpl(context, 0, offset, inst));
    offset += value->numChildren();

    StackmapGenerationParams params(value, reps, context);

    for (unsigned i = value->numGPScratchRegisters; i--;)
        params.m_gpScratch.append(inst.args[offset++].gpr());
    for (unsigned i = value->numFPScratchRegisters; i--;)
        params.m_fpScratch.append(inst.args[offset++].fpr());
    
    value->m_generator->run(jit, params);

    return CCallHelpers::Jump();
}

bool PatchpointSpecial::isTerminal(Inst& inst)
{
    return inst.origin->as<PatchpointValue>()->effects.terminal;
}

void PatchpointSpecial::dumpImpl(PrintStream& out) const
{
    out.print("Patchpoint");
}

void PatchpointSpecial::deepDumpImpl(PrintStream& out) const
{
    out.print("Lowered B3::PatchpointValue.");
}

} } // namespace JSC::B3

#endif // ENABLE(B3_JIT)
