AirCCallSpecial.cpp [plain text]
#include "config.h"
#include "AirCCallSpecial.h"
#if ENABLE(B3_JIT)
#include "CCallHelpers.h"
namespace JSC { namespace B3 { namespace Air {
CCallSpecial::CCallSpecial()
{
m_clobberedRegs = RegisterSet::allRegisters();
m_clobberedRegs.exclude(RegisterSet::stackRegisters());
m_clobberedRegs.exclude(RegisterSet::reservedHardwareRegisters());
m_clobberedRegs.exclude(RegisterSet::calleeSaveRegisters());
m_clobberedRegs.clear(GPRInfo::returnValueGPR);
m_clobberedRegs.clear(GPRInfo::returnValueGPR2);
m_clobberedRegs.clear(FPRInfo::returnValueFPR);
}
CCallSpecial::~CCallSpecial()
{
}
void CCallSpecial::forEachArg(Inst& inst, const ScopedLambda<Inst::EachArgCallback>& callback)
{
for (unsigned i = 0; i < numCalleeArgs; ++i)
callback(inst.args[calleeArgOffset + i], Arg::Use, GP, pointerWidth());
for (unsigned i = 0; i < numReturnGPArgs; ++i)
callback(inst.args[returnGPArgOffset + i], Arg::Def, GP, pointerWidth());
for (unsigned i = 0; i < numReturnFPArgs; ++i)
callback(inst.args[returnFPArgOffset + i], Arg::Def, FP, Width64);
for (unsigned i = argArgOffset; i < inst.args.size(); ++i) {
Bank bank = inst.args[i].bank();
callback(inst.args[i], Arg::Use, bank, conservativeWidth(bank));
}
}
bool CCallSpecial::isValid(Inst& inst)
{
if (inst.args.size() < argArgOffset)
return false;
for (unsigned i = 0; i < numCalleeArgs; ++i) {
Arg& arg = inst.args[i + calleeArgOffset];
if (!arg.isGP())
return false;
switch (arg.kind()) {
case Arg::Imm:
if (is32Bit())
break;
return false;
case Arg::BigImm:
if (is64Bit())
break;
return false;
case Arg::Tmp:
case Arg::Addr:
case Arg::ExtendedOffsetAddr:
case Arg::Stack:
case Arg::CallArg:
break;
default:
return false;
}
}
if (inst.args[returnGPArgOffset + 0] != Tmp(GPRInfo::returnValueGPR))
return false;
if (inst.args[returnGPArgOffset + 1] != Tmp(GPRInfo::returnValueGPR2))
return false;
if (inst.args[returnFPArgOffset + 0] != Tmp(FPRInfo::returnValueFPR))
return false;
for (unsigned i = argArgOffset; i < inst.args.size(); ++i) {
if (!inst.args[i].isReg())
return false;
if (inst.args[i] == Tmp(scratchRegister))
return false;
}
return true;
}
bool CCallSpecial::admitsStack(Inst&, unsigned argIndex)
{
if (argIndex == calleeArgOffset)
return !isARM64();
return false;
}
bool CCallSpecial::admitsExtendedOffsetAddr(Inst& inst, unsigned argIndex)
{
return admitsStack(inst, argIndex);
}
void CCallSpecial::reportUsedRegisters(Inst&, const RegisterSet&)
{
}
CCallHelpers::Jump CCallSpecial::generate(Inst& inst, CCallHelpers& jit, GenerationContext&)
{
switch (inst.args[calleeArgOffset].kind()) {
case Arg::Imm:
case Arg::BigImm:
jit.move(inst.args[calleeArgOffset].asTrustedImmPtr(), scratchRegister);
jit.call(scratchRegister, B3CCallPtrTag);
break;
case Arg::Tmp:
jit.call(inst.args[calleeArgOffset].gpr(), B3CCallPtrTag);
break;
case Arg::Addr:
case Arg::ExtendedOffsetAddr:
jit.call(inst.args[calleeArgOffset].asAddress(), B3CCallPtrTag);
break;
default:
RELEASE_ASSERT_NOT_REACHED();
break;
}
return CCallHelpers::Jump();
}
RegisterSet CCallSpecial::extraEarlyClobberedRegs(Inst&)
{
return m_emptyRegs;
}
RegisterSet CCallSpecial::extraClobberedRegs(Inst&)
{
return m_clobberedRegs;
}
void CCallSpecial::dumpImpl(PrintStream& out) const
{
out.print("CCall");
}
void CCallSpecial::deepDumpImpl(PrintStream& out) const
{
out.print("function call that uses the C calling convention.");
}
} } }
#endif // ENABLE(B3_JIT)