/*
 * Copyright (C) 2016-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 "AirCustom.h"

#if ENABLE(B3_JIT)

#include "AirInstInlines.h"
#include "B3CCallValue.h"
#include "B3ValueInlines.h"
#include "CCallHelpers.h"

namespace JSC { namespace B3 { namespace Air {

bool PatchCustom::isValidForm(Inst& inst)
{
    if (inst.args.size() < 1)
        return false;
    if (!inst.args[0].isSpecial())
        return false;
    if (!inst.args[0].special()->isValid(inst))
        return false;
    RegisterSet clobberedEarly = inst.extraEarlyClobberedRegs();
    RegisterSet clobberedLate = inst.extraClobberedRegs();
    bool ok = true;
    inst.forEachTmp(
        [&] (Tmp& tmp, Arg::Role role, Bank, Width) {
            if (!tmp.isReg())
                return;
            if (Arg::isLateDef(role) || Arg::isLateUse(role))
                ok &= !clobberedLate.get(tmp.reg());
            else
                ok &= !clobberedEarly.get(tmp.reg());
        });
    return ok;
}

bool CCallCustom::isValidForm(Inst& inst)
{
    CCallValue* value = inst.origin->as<CCallValue>();
    if (!value)
        return false;

    if (inst.args.size() != (value->type() == Void ? 0 : 1) + value->numChildren())
        return false;

    // The arguments can only refer to the stack, tmps, or immediates.
    for (Arg& arg : inst.args) {
        if (!arg.isTmp() && !arg.isStackMemory() && !arg.isSomeImm())
            return false;
    }

    unsigned offset = 0;

    if (!inst.args[0].isGP())
        return false;

    // If there is a result then it cannot be an immediate.
    if (value->type() != Void) {
        if (inst.args[1].isSomeImm())
            return false;
        if (!inst.args[1].canRepresent(value))
            return false;
        offset++;
    }

    for (unsigned i = value->numChildren(); i-- > 1;) {
        Value* child = value->child(i);
        Arg arg = inst.args[offset + i];
        if (!arg.canRepresent(child))
            return false;
    }

    return true;
}

MacroAssembler::Jump CCallCustom::generate(Inst& inst, CCallHelpers&, GenerationContext&)
{
    dataLog("FATAL: Unlowered C call: ", inst, "\n");
    UNREACHABLE_FOR_PLATFORM();
    return MacroAssembler::Jump();
}

bool ShuffleCustom::isValidForm(Inst& inst)
{
    if (inst.args.size() % 3)
        return false;

    // A destination may only appear once. This requirement allows us to avoid the undefined behavior
    // of having a destination that is supposed to get multiple inputs simultaneously. It also
    // imposes some interesting constraints on the "shape" of the shuffle. If we treat a shuffle pair
    // as an edge and the Args as nodes, then the single-destination requirement means that the
    // shuffle graph consists of two kinds of subgraphs:
    //
    // - Spanning trees. We call these shifts. They can be executed as a sequence of Move
    //   instructions and don't usually require scratch registers.
    //
    // - Closed loops. These loops consist of nodes that have one successor and one predecessor, so
    //   there is no way to "get into" the loop from outside of it. These can be executed using swaps
    //   or by saving one of the Args to a scratch register and executing it as a shift.
    HashSet<Arg> dsts;

    for (unsigned i = 0; i < inst.args.size(); ++i) {
        Arg arg = inst.args[i];
        unsigned mode = i % 3;

        if (mode == 2) {
            // It's the width.
            if (!arg.isWidthArg())
                return false;
            continue;
        }

        // The source can be an immediate.
        if (!mode) {
            if (arg.isSomeImm())
                continue;

            if (!arg.isCompatibleBank(inst.args[i + 1]))
                return false;
        } else {
            ASSERT(mode == 1);
            if (!dsts.add(arg).isNewEntry)
                return false;
        }

        if (arg.isTmp() || arg.isMemory())
            continue;

        return false;
    }

    // No destination register may appear in any address expressions. The lowering can't handle it
    // and it's not useful for the way we end up using Shuffles. Normally, Shuffles only used for
    // stack addresses and non-stack registers.
    for (Arg& arg : inst.args) {
        if (!arg.isMemory())
            continue;
        bool ok = true;
        arg.forEachTmpFast(
            [&] (Tmp tmp) {
                if (dsts.contains(tmp))
                    ok = false;
            });
        if (!ok)
            return false;
    }

    return true;
}

MacroAssembler::Jump ShuffleCustom::generate(Inst& inst, CCallHelpers&, GenerationContext&)
{
    dataLog("FATAL: Unlowered shuffle: ", inst, "\n");
    UNREACHABLE_FOR_PLATFORM();
    return MacroAssembler::Jump();
}

bool WasmBoundsCheckCustom::isValidForm(Inst& inst)
{
    if (inst.args.size() != 2)
        return false;
    if (!inst.args[0].isTmp() && !inst.args[0].isSomeImm())
        return false;

    return inst.args[1].isReg() || inst.args[1].isTmp() || inst.args[1].isSomeImm();
}

MacroAssembler::Jump WasmBoundsCheckCustom::generate(Inst& inst, CCallHelpers& jit, GenerationContext& context)
{
    WasmBoundsCheckValue* value = inst.origin->as<WasmBoundsCheckValue>();
    MacroAssembler::Jump outOfBounds = Inst(Air::Branch64, value, Arg::relCond(MacroAssembler::AboveOrEqual), inst.args[0], inst.args[1]).generate(jit, context);

    context.latePaths.append(createSharedTask<GenerationContext::LatePathFunction>(
        [outOfBounds, value] (CCallHelpers& jit, Air::GenerationContext& context) {
            outOfBounds.link(&jit);
            switch (value->boundsType()) {
            case WasmBoundsCheckValue::Type::Pinned:
                context.code->wasmBoundsCheckGenerator()->run(jit, value->bounds().pinnedSize);
                break;

            case WasmBoundsCheckValue::Type::Maximum:
                context.code->wasmBoundsCheckGenerator()->run(jit, InvalidGPRReg);
                break;
            }
        }));

    // We said we were not a terminal.
    return MacroAssembler::Jump();
}

} } } // namespace JSC::B3::Air

#endif // ENABLE(B3_JIT)

