#include "config.h"
#include "AirCustom.h"
#if ENABLE(B3_JIT)
#include "AirInstInlines.h"
#include "B3CCallValue.h"
#include "B3ValueInlines.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;
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 (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;
}
CCallHelpers::Jump CCallCustom::generate(Inst& inst, CCallHelpers&, GenerationContext&)
{
dataLog("FATAL: Unlowered C call: ", inst, "\n");
UNREACHABLE_FOR_PLATFORM();
return CCallHelpers::Jump();
}
bool ShuffleCustom::isValidForm(Inst& inst)
{
if (inst.args.size() % 3)
return false;
HashSet<Arg> dsts;
for (unsigned i = 0; i < inst.args.size(); ++i) {
Arg arg = inst.args[i];
unsigned mode = i % 3;
if (mode == 2) {
if (!arg.isWidthArg())
return false;
continue;
}
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;
}
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;
}
CCallHelpers::Jump ShuffleCustom::generate(Inst& inst, CCallHelpers&, GenerationContext&)
{
dataLog("FATAL: Unlowered shuffle: ", inst, "\n");
UNREACHABLE_FOR_PLATFORM();
return CCallHelpers::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();
}
} } }
#endif // ENABLE(B3_JIT)