#pragma once
#if ENABLE(B3_JIT)
#include "AirArg.h"
namespace JSC { namespace B3 { namespace Air {
template<typename T> struct ArgThingHelper;
template<> struct ArgThingHelper<Tmp> {
static bool is(const Arg& arg)
{
return arg.isTmp();
}
static Tmp as(const Arg& arg)
{
if (is(arg))
return arg.tmp();
return Tmp();
}
template<typename Functor>
static void forEachFast(Arg& arg, const Functor& functor)
{
arg.forEachTmpFast(functor);
}
template<typename Functor>
static void forEach(Arg& arg, Arg::Role role, Bank bank, Width width, const Functor& functor)
{
arg.forEachTmp(role, bank, width, functor);
}
};
template<> struct ArgThingHelper<Arg> {
static bool is(const Arg&)
{
return true;
}
static Arg as(const Arg& arg)
{
return arg;
}
template<typename Functor>
static void forEachFast(Arg& arg, const Functor& functor)
{
functor(arg);
}
template<typename Functor>
static void forEach(Arg& arg, Arg::Role role, Bank bank, Width width, const Functor& functor)
{
functor(arg, role, bank, width);
}
};
template<> struct ArgThingHelper<StackSlot*> {
static bool is(const Arg& arg)
{
return arg.isStack();
}
static StackSlot* as(const Arg& arg)
{
return arg.stackSlot();
}
template<typename Functor>
static void forEachFast(Arg& arg, const Functor& functor)
{
if (!arg.isStack())
return;
StackSlot* stackSlot = arg.stackSlot();
functor(stackSlot);
arg = Arg::stack(stackSlot, arg.offset());
}
template<typename Functor>
static void forEach(Arg& arg, Arg::Role role, Bank bank, Width width, const Functor& functor)
{
if (!arg.isStack())
return;
StackSlot* stackSlot = arg.stackSlot();
functor(stackSlot, role, bank, width);
arg = Arg::stack(stackSlot, arg.offset());
}
};
template<> struct ArgThingHelper<Reg> {
static bool is(const Arg& arg)
{
return arg.isReg();
}
static Reg as(const Arg& arg)
{
return arg.reg();
}
template<typename Functor>
static void forEachFast(Arg& arg, const Functor& functor)
{
arg.forEachTmpFast(
[&] (Tmp& tmp) {
if (!tmp.isReg())
return;
Reg reg = tmp.reg();
functor(reg);
tmp = Tmp(reg);
});
}
template<typename Functor>
static void forEach(Arg& arg, Arg::Role argRole, Bank argBank, Width argWidth, const Functor& functor)
{
arg.forEachTmp(
argRole, argBank, argWidth,
[&] (Tmp& tmp, Arg::Role role, Bank bank, Width width) {
if (!tmp.isReg())
return;
Reg reg = tmp.reg();
functor(reg, role, bank, width);
tmp = Tmp(reg);
});
}
};
template<typename Thing>
bool Arg::is() const
{
return ArgThingHelper<Thing>::is(*this);
}
template<typename Thing>
Thing Arg::as() const
{
return ArgThingHelper<Thing>::as(*this);
}
template<typename Thing, typename Functor>
void Arg::forEachFast(const Functor& functor)
{
ArgThingHelper<Thing>::forEachFast(*this, functor);
}
template<typename Thing, typename Functor>
void Arg::forEach(Role role, Bank bank, Width width, const Functor& functor)
{
ArgThingHelper<Thing>::forEach(*this, role, bank, width, functor);
}
} } }
#endif // ENABLE(B3_JIT)