- implement OP_TAIL and OP_TAIL_K

This commit is contained in:
Magnus Norddahl 2018-09-17 09:02:23 +02:00
parent d032914c3d
commit f61df60240
3 changed files with 49 additions and 12 deletions

View file

@ -146,15 +146,8 @@ bool JitCompiler::CanJit(VMScriptFunction *sfunc)
{ {
// Functions not implemented at all yet: // Functions not implemented at all yet:
switch (sfunc->Code[i].op) if (sfunc->Code[i].op == OP_IJMP)
{
default:
break;
case OP_IJMP:
case OP_TAIL:
case OP_TAIL_K:
return false; return false;
}
// Partially implemented functions: // Partially implemented functions:

View file

@ -138,12 +138,14 @@ void JitCompiler::EmitCALL_K()
void JitCompiler::EmitTAIL() void JitCompiler::EmitTAIL()
{ {
I_FatalError("EmitTAIL not implemented\n"); EmitDoTail(regA[A]);
} }
void JitCompiler::EmitTAIL_K() void JitCompiler::EmitTAIL_K()
{ {
I_FatalError("EmitTAIL_K not implemented\n"); auto ptr = cc.newIntPtr();
cc.mov(ptr, ToMemAddress(konsta[A].o));
EmitDoTail(ptr);
} }
void JitCompiler::EmitDoCall(asmjit::X86Gp ptr) void JitCompiler::EmitDoCall(asmjit::X86Gp ptr)
@ -160,8 +162,7 @@ void JitCompiler::EmitDoCall(asmjit::X86Gp ptr)
if (B != NumParam) if (B != NumParam)
{ {
paramsptr = cc.newIntPtr(); paramsptr = cc.newIntPtr();
cc.mov(paramsptr, params); cc.lea(paramsptr, x86::ptr(params, (int)((NumParam - B) * sizeof(VMValue))));
cc.add(paramsptr, (int)((NumParam - B) * sizeof(VMValue)));
} }
else else
{ {
@ -196,6 +197,48 @@ void JitCompiler::EmitDoCall(asmjit::X86Gp ptr)
ParamOpcodes.Resize(ParamOpcodes.Size() - B); ParamOpcodes.Resize(ParamOpcodes.Size() - B);
} }
void JitCompiler::EmitDoTail(asmjit::X86Gp ptr)
{
// Whereas the CALL instruction uses its third operand to specify how many return values
// it expects, TAIL ignores its third operand and uses whatever was passed to this Exec call.
// Note: this is not a true tail call, but then again, it isn't in the vmexec implementation either..
using namespace asmjit;
if (NumParam < B)
I_FatalError("OP_TAIL parameter count does not match the number of preceding OP_PARAM instructions");
StoreInOuts(B); // Is REGT_ADDROF even allowed for (true) tail calls?
X86Gp paramsptr;
if (B != NumParam)
{
paramsptr = cc.newIntPtr();
cc.lea(paramsptr, x86::ptr(params, (int)((NumParam - B) * sizeof(VMValue))));
}
else
{
paramsptr = params;
}
auto result = cc.newInt32();
auto call = cc.call(ToMemAddress(reinterpret_cast<const void*>(&JitCompiler::DoCall)), FuncSignature7<int, void*, void*, int, int, void*, void*, void*>());
call->setRet(0, result);
call->setArg(0, stack);
call->setArg(1, ptr);
call->setArg(2, asmjit::Imm(B));
call->setArg(3, numret);
call->setArg(4, paramsptr);
call->setArg(5, ret);
call->setArg(6, exceptInfo);
cc.ret(result);
NumParam -= B;
ParamOpcodes.Resize(ParamOpcodes.Size() - B);
}
void JitCompiler::StoreInOuts(int b) void JitCompiler::StoreInOuts(int b)
{ {
using namespace asmjit; using namespace asmjit;

View file

@ -43,6 +43,7 @@ private:
void EmitOpcode(); void EmitOpcode();
void EmitDoCall(asmjit::X86Gp ptr); void EmitDoCall(asmjit::X86Gp ptr);
void EmitDoTail(asmjit::X86Gp ptr);
void StoreInOuts(int b); void StoreInOuts(int b);
void LoadInOuts(int b); void LoadInOuts(int b);
void LoadReturns(const VMOP *retval, int numret); void LoadReturns(const VMOP *retval, int numret);