- fix CALL_K and disable CALL

This commit is contained in:
Magnus Norddahl 2018-09-12 21:58:31 +02:00
parent ced793b791
commit afc3c6b562
1 changed files with 65 additions and 18 deletions

View File

@ -105,6 +105,9 @@ public:
} }
else if (sfunc->Code[i].op == OP_PARAM) else if (sfunc->Code[i].op == OP_PARAM)
{ {
if (!!(B & REGT_MULTIREG3) || !!(B & REGT_MULTIREG2))
return false;
switch (B) switch (B)
{ {
case REGT_STRING: case REGT_STRING:
@ -117,6 +120,9 @@ public:
} }
else if (sfunc->Code[i].op == OP_RESULT) else if (sfunc->Code[i].op == OP_RESULT)
{ {
if (!!(B & REGT_MULTIREG3) || !!(B & REGT_MULTIREG2))
return false;
if ((B & REGT_TYPE) == REGT_STRING) if ((B & REGT_TYPE) == REGT_STRING)
return false; return false;
} }
@ -213,7 +219,7 @@ private:
//EMIT_OP(IJMP); //EMIT_OP(IJMP);
EMIT_OP(PARAM); EMIT_OP(PARAM);
EMIT_OP(PARAMI); EMIT_OP(PARAMI);
EMIT_OP(CALL); //EMIT_OP(CALL);
EMIT_OP(CALL_K); EMIT_OP(CALL_K);
EMIT_OP(VTBL); EMIT_OP(VTBL);
EMIT_OP(SCOPE); EMIT_OP(SCOPE);
@ -1003,6 +1009,7 @@ private:
using namespace asmjit; using namespace asmjit;
int index = NumParam++; int index = NumParam++;
ParamOpcodes.Push(pc);
X86Gp stackPtr, tmp; X86Gp stackPtr, tmp;
X86Xmm tmp2; X86Xmm tmp2;
@ -1021,8 +1028,6 @@ private:
stackPtr = cc.newIntPtr(); stackPtr = cc.newIntPtr();
cc.mov(stackPtr, frameD); cc.mov(stackPtr, frameD);
cc.add(stackPtr, C * sizeof(int32_t)); cc.add(stackPtr, C * sizeof(int32_t));
cc.mov(x86::dword_ptr(stackPtr), regD[C]);
cc.mov(x86::ptr(params, index * sizeof(VMValue) + offsetof(VMValue, a)), stackPtr); cc.mov(x86::ptr(params, index * sizeof(VMValue) + offsetof(VMValue, a)), stackPtr);
cc.mov(x86::byte_ptr(params, index * sizeof(VMValue) + offsetof(VMValue, Type)), (int)REGT_POINTER); cc.mov(x86::byte_ptr(params, index * sizeof(VMValue) + offsetof(VMValue, Type)), (int)REGT_POINTER);
break; break;
@ -1041,13 +1046,13 @@ private:
stackPtr = cc.newIntPtr(); stackPtr = cc.newIntPtr();
cc.mov(stackPtr, frameA); cc.mov(stackPtr, frameA);
cc.add(stackPtr, C * sizeof(void*)); cc.add(stackPtr, C * sizeof(void*));
cc.mov(x86::ptr(stackPtr), regA[C]);
cc.mov(x86::ptr(params, index * sizeof(VMValue) + offsetof(VMValue, a)), stackPtr); cc.mov(x86::ptr(params, index * sizeof(VMValue) + offsetof(VMValue, a)), stackPtr);
cc.mov(x86::byte_ptr(params, index * sizeof(VMValue) + offsetof(VMValue, Type)), (int)REGT_POINTER); cc.mov(x86::byte_ptr(params, index * sizeof(VMValue) + offsetof(VMValue, Type)), (int)REGT_POINTER);
break; break;
case REGT_POINTER | REGT_KONST: case REGT_POINTER | REGT_KONST:
cc.mov(x86::ptr(params, index * sizeof(VMValue) + offsetof(VMValue, a)), ToMemAddress(konsta[C].v)); tmp = cc.newIntPtr();
cc.mov(tmp, ToMemAddress(konsta[C].v));
cc.mov(x86::ptr(params, index * sizeof(VMValue) + offsetof(VMValue, a)), tmp);
cc.mov(x86::byte_ptr(params, index * sizeof(VMValue) + offsetof(VMValue, Type)), (int)REGT_POINTER); cc.mov(x86::byte_ptr(params, index * sizeof(VMValue) + offsetof(VMValue, Type)), (int)REGT_POINTER);
break; break;
case REGT_FLOAT: case REGT_FLOAT:
@ -1058,6 +1063,7 @@ private:
cc.movsd(x86::qword_ptr(params, index * sizeof(VMValue) + offsetof(VMValue, f)), regF[C]); cc.movsd(x86::qword_ptr(params, index * sizeof(VMValue) + offsetof(VMValue, f)), regF[C]);
cc.mov(x86::byte_ptr(params, index * sizeof(VMValue) + offsetof(VMValue, Type)), (int)REGT_FLOAT); cc.mov(x86::byte_ptr(params, index * sizeof(VMValue) + offsetof(VMValue, Type)), (int)REGT_FLOAT);
index = NumParam++; index = NumParam++;
ParamOpcodes.Push(pc);
cc.movsd(x86::qword_ptr(params, index * sizeof(VMValue) + offsetof(VMValue, f)), regF[C + 1]); cc.movsd(x86::qword_ptr(params, index * sizeof(VMValue) + offsetof(VMValue, f)), regF[C + 1]);
cc.mov(x86::byte_ptr(params, index * sizeof(VMValue) + offsetof(VMValue, Type)), (int)REGT_FLOAT); cc.mov(x86::byte_ptr(params, index * sizeof(VMValue) + offsetof(VMValue, Type)), (int)REGT_FLOAT);
break; break;
@ -1065,9 +1071,11 @@ private:
cc.movsd(x86::qword_ptr(params, index * sizeof(VMValue) + offsetof(VMValue, f)), regF[C]); cc.movsd(x86::qword_ptr(params, index * sizeof(VMValue) + offsetof(VMValue, f)), regF[C]);
cc.mov(x86::byte_ptr(params, index * sizeof(VMValue) + offsetof(VMValue, Type)), (int)REGT_FLOAT); cc.mov(x86::byte_ptr(params, index * sizeof(VMValue) + offsetof(VMValue, Type)), (int)REGT_FLOAT);
index = NumParam++; index = NumParam++;
ParamOpcodes.Push(pc);
cc.movsd(x86::qword_ptr(params, index * sizeof(VMValue) + offsetof(VMValue, f)), regF[C + 1]); cc.movsd(x86::qword_ptr(params, index * sizeof(VMValue) + offsetof(VMValue, f)), regF[C + 1]);
cc.mov(x86::byte_ptr(params, index * sizeof(VMValue) + offsetof(VMValue, Type)), (int)REGT_FLOAT); cc.mov(x86::byte_ptr(params, index * sizeof(VMValue) + offsetof(VMValue, Type)), (int)REGT_FLOAT);
index = NumParam++; index = NumParam++;
ParamOpcodes.Push(pc);
cc.movsd(x86::qword_ptr(params, index * sizeof(VMValue) + offsetof(VMValue, f)), regF[C + 2]); cc.movsd(x86::qword_ptr(params, index * sizeof(VMValue) + offsetof(VMValue, f)), regF[C + 2]);
cc.mov(x86::byte_ptr(params, index * sizeof(VMValue) + offsetof(VMValue, Type)), (int)REGT_FLOAT); cc.mov(x86::byte_ptr(params, index * sizeof(VMValue) + offsetof(VMValue, Type)), (int)REGT_FLOAT);
break; break;
@ -1075,8 +1083,6 @@ private:
stackPtr = cc.newIntPtr(); stackPtr = cc.newIntPtr();
cc.mov(stackPtr, frameF); cc.mov(stackPtr, frameF);
cc.add(stackPtr, C * sizeof(double)); cc.add(stackPtr, C * sizeof(double));
cc.movsd(x86::qword_ptr(stackPtr), regF[C]);
cc.mov(x86::ptr(params, index * sizeof(VMValue) + offsetof(VMValue, a)), stackPtr); cc.mov(x86::ptr(params, index * sizeof(VMValue) + offsetof(VMValue, a)), stackPtr);
cc.mov(x86::byte_ptr(params, index * sizeof(VMValue) + offsetof(VMValue, Type)), (int)REGT_POINTER); cc.mov(x86::byte_ptr(params, index * sizeof(VMValue) + offsetof(VMValue, Type)), (int)REGT_POINTER);
break; break;
@ -1092,11 +1098,13 @@ private:
I_FatalError("Unknown REGT value passed to EmitPARAM\n"); I_FatalError("Unknown REGT value passed to EmitPARAM\n");
break; break;
} }
} }
void EmitPARAMI() void EmitPARAMI()
{ {
int index = NumParam++; int index = NumParam++;
ParamOpcodes.Push(pc);
cc.mov(asmjit::x86::dword_ptr(params, index * sizeof(VMValue) + offsetof(VMValue, i)), (int)ABCs); cc.mov(asmjit::x86::dword_ptr(params, index * sizeof(VMValue) + offsetof(VMValue, i)), (int)ABCs);
cc.mov(asmjit::x86::byte_ptr(params, index * sizeof(VMValue) + offsetof(VMValue, Type)), (int)REGT_INT); cc.mov(asmjit::x86::byte_ptr(params, index * sizeof(VMValue) + offsetof(VMValue, Type)), (int)REGT_INT);
} }
@ -1117,12 +1125,24 @@ private:
{ {
using namespace asmjit; using namespace asmjit;
if (NumParam != B) if (NumParam < B)
I_FatalError("OP_CALL parameter count does not match the number of preceding OP_PARAM instructions"); I_FatalError("OP_CALL parameter count does not match the number of preceding OP_PARAM instructions");
NumParam = 0;
StoreInOuts(B);
FillReturns(pc + 1, C); FillReturns(pc + 1, C);
X86Gp paramsptr;
if (B != NumParam)
{
paramsptr = cc.newIntPtr();
cc.mov(paramsptr, params);
cc.add(paramsptr, (NumParam - B) * sizeof(VMValue));
}
else
{
paramsptr = params;
}
auto result = cc.newInt32(); auto result = cc.newInt32();
auto call = cc.call(ToMemAddress(&JitCompiler::DoCall), FuncSignature7<int, void*, void*, int, int, void*, void*, void*>()); auto call = cc.call(ToMemAddress(&JitCompiler::DoCall), FuncSignature7<int, void*, void*, int, int, void*, void*, void*>());
call->setRet(0, result); call->setRet(0, result);
@ -1130,7 +1150,7 @@ private:
call->setArg(1, ptr); call->setArg(1, ptr);
call->setArg(2, asmjit::Imm(B)); call->setArg(2, asmjit::Imm(B));
call->setArg(3, asmjit::Imm(C)); call->setArg(3, asmjit::Imm(C));
call->setArg(4, params); call->setArg(4, paramsptr);
call->setArg(5, callReturns); call->setArg(5, callReturns);
call->setArg(6, exceptInfo); call->setArg(6, exceptInfo);
@ -1146,17 +1166,43 @@ private:
LoadReturns(pc - B, B, true); LoadReturns(pc - B, B, true);
LoadReturns(pc + 1, C, false); LoadReturns(pc + 1, C, false);
NumParam -= B;
ParamOpcodes.Resize(ParamOpcodes.Size() - B);
} }
void LoadReturns(const VMOP *retval, int numret, const VMOP *argval, int numarg) void StoreInOuts(int b)
{ {
// Put the stored returns back into asmjit virtual registers: using namespace asmjit;
// Put any inout arguments back into asmjit virtual registers: for (unsigned int i = ParamOpcodes.Size() - b; i < ParamOpcodes.Size(); i++)
for (int i = 0; i < numarg; ++i)
{ {
int type = argval[i].b; asmjit::X86Gp stackPtr;
int regnum = argval[i].c; switch (ParamOpcodes[i]->b)
{
case REGT_INT | REGT_ADDROF:
stackPtr = cc.newIntPtr();
cc.mov(stackPtr, frameD);
cc.add(stackPtr, C * sizeof(int32_t));
cc.mov(x86::dword_ptr(stackPtr), regD[C]);
break;
//case REGT_STRING | REGT_ADDROF:
// break;
case REGT_POINTER | REGT_ADDROF:
stackPtr = cc.newIntPtr();
cc.mov(stackPtr, frameA);
cc.add(stackPtr, C * sizeof(void*));
cc.mov(x86::ptr(stackPtr), regA[C]);
break;
case REGT_FLOAT | REGT_ADDROF:
stackPtr = cc.newIntPtr();
cc.mov(stackPtr, frameF);
cc.add(stackPtr, C * sizeof(double));
cc.movsd(x86::qword_ptr(stackPtr), regF[C]);
break;
default:
break;
}
} }
} }
@ -3350,7 +3396,8 @@ private:
asmjit::X86Gp frameF; asmjit::X86Gp frameF;
asmjit::X86Gp frameA; asmjit::X86Gp frameA;
asmjit::X86Gp params; asmjit::X86Gp params;
int NumParam = 0; // Actually part of vmframe (f->NumParam), but we are going to assume that the backend never reuses parameters int NumParam = 0; // Actually part of vmframe (f->NumParam), but nobody seems to read that?
TArray<const VMOP *> ParamOpcodes;
asmjit::X86Gp callReturns; asmjit::X86Gp callReturns;
const int *konstd; const int *konstd;