- stop using lambda functions for CreateCall because MSVC lambas use a different calling convention and "converts" them to the right one by generating a thunk function

This commit is contained in:
Magnus Norddahl 2018-11-17 05:12:47 +01:00
commit f99bba48dc
5 changed files with 232 additions and 161 deletions

View file

@ -38,6 +38,23 @@ void JitCompiler::EmitMOVEV3()
cc.movsd(regF[A + 2], regF[B + 2]);
}
static void CastI2S(FString *a, int b) { a->Format("%d", b); }
static void CastU2S(FString *a, int b) { a->Format("%u", b); }
static void CastF2S(FString *a, double b) { a->Format("%.5f", b); }
static void CastV22S(FString *a, double b, double b1) { a->Format("(%.5f, %.5f)", b, b1); }
static void CastV32S(FString *a, double b, double b1, double b2) { a->Format("(%.5f, %.5f, %.5f)", b, b1, b2); }
static void CastP2S(FString *a, void *b) { if (b == nullptr) *a = "null"; else a->Format("%p", b); }
static int CastS2I(FString *b) { return (VM_SWORD)b->ToLong(); }
static double CastS2F(FString *b) { return b->ToDouble(); }
static int CastS2N(FString *b) { return b->Len() == 0 ? FName(NAME_None) : FName(*b); }
static void CastN2S(FString *a, int b) { FName name = FName(ENamedName(b)); *a = name.IsValidName() ? name.GetChars() : ""; }
static int CastS2Co(FString *b) { return V_GetColor(nullptr, *b); }
static void CastCo2S(FString *a, int b) { PalEntry c(b); a->Format("%02x %02x %02x", c.r, c.g, c.b); }
static int CastS2So(FString *b) { return FSoundID(*b); }
static void CastSo2S(FString *a, int b) { *a = S_sfx[b].name; }
static void CastSID2S(FString *a, unsigned int b) { *a = (b >= sprites.Size()) ? "TNT1" : sprites[b].name; }
static void CastTID2S(FString *a, int b) { auto tex = TexMan[*(FTextureID*)&b]; *a = (tex == nullptr) ? "(null)" : tex->Name.GetChars(); }
void JitCompiler::EmitCAST()
{
asmjit::X86Gp tmp, resultD;
@ -64,95 +81,95 @@ void JitCompiler::EmitCAST()
cc.mov(regD[A], tmp.r32());
break;
case CAST_I2S:
call = CreateCall<void, FString*, int>([](FString *a, int b) { a->Format("%d", b); });
call = CreateCall<void, FString*, int>(CastI2S);
call->setArg(0, regS[A]);
call->setArg(1, regD[B]);
break;
case CAST_U2S:
call = CreateCall<void, FString*, int>([](FString *a, int b) { a->Format("%u", b); });
call = CreateCall<void, FString*, int>(CastU2S);
call->setArg(0, regS[A]);
call->setArg(1, regD[B]);
break;
case CAST_F2S:
call = CreateCall<void, FString*, double>([](FString *a, double b) { a->Format("%.5f", b); });
call = CreateCall<void, FString*, double>(CastF2S);
call->setArg(0, regS[A]);
call->setArg(1, regF[B]);
break;
case CAST_V22S:
call = CreateCall<void, FString*, double, double>([](FString *a, double b, double b1) { a->Format("(%.5f, %.5f)", b, b1); });
call = CreateCall<void, FString*, double, double>(CastV22S);
call->setArg(0, regS[A]);
call->setArg(1, regF[B]);
call->setArg(2, regF[B + 1]);
break;
case CAST_V32S:
call = CreateCall<void, FString*, double, double, double>([](FString *a, double b, double b1, double b2) { a->Format("(%.5f, %.5f, %.5f)", b, b1, b2); });
call = CreateCall<void, FString*, double, double, double>(CastV32S);
call->setArg(0, regS[A]);
call->setArg(1, regF[B]);
call->setArg(2, regF[B + 1]);
call->setArg(3, regF[B + 2]);
break;
case CAST_P2S:
call = CreateCall<void, FString*, void*>([](FString *a, void *b) { if (b == nullptr) *a = "null"; else a->Format("%p", b); });
call = CreateCall<void, FString*, void*>(CastP2S);
call->setArg(0, regS[A]);
call->setArg(1, regA[B]);
break;
case CAST_S2I:
resultD = newResultInt32();
call = CreateCall<int, FString*>([](FString *b) -> int { return (VM_SWORD)b->ToLong(); });
call = CreateCall<int, FString*>(CastS2I);
call->setRet(0, resultD);
call->setArg(0, regS[B]);
cc.mov(regD[A], resultD);
break;
case CAST_S2F:
resultF = newResultXmmSd();
call = CreateCall<double, FString*>([](FString *b) -> double { return b->ToDouble(); });
call = CreateCall<double, FString*>(CastS2F);
call->setRet(0, resultF);
call->setArg(0, regS[B]);
cc.movsd(regF[A], resultF);
break;
case CAST_S2N:
resultD = newResultInt32();
call = CreateCall<int, FString*>([](FString *b) -> int { return b->Len() == 0 ? FName(NAME_None) : FName(*b); });
call = CreateCall<int, FString*>(CastS2N);
call->setRet(0, resultD);
call->setArg(0, regS[B]);
cc.mov(regD[A], resultD);
break;
case CAST_N2S:
call = CreateCall<void, FString*, int>([](FString *a, int b) { FName name = FName(ENamedName(b)); *a = name.IsValidName() ? name.GetChars() : ""; });
call = CreateCall<void, FString*, int>(CastN2S);
call->setArg(0, regS[A]);
call->setArg(1, regD[B]);
break;
case CAST_S2Co:
resultD = newResultInt32();
call = CreateCall<int, FString*>([](FString *b) -> int { return V_GetColor(nullptr, *b); });
call = CreateCall<int, FString*>(CastS2Co);
call->setRet(0, resultD);
call->setArg(0, regS[B]);
cc.mov(regD[A], resultD);
break;
case CAST_Co2S:
call = CreateCall<void, FString*, int>([](FString *a, int b) { PalEntry c(b); a->Format("%02x %02x %02x", c.r, c.g, c.b); });
call = CreateCall<void, FString*, int>(CastCo2S);
call->setArg(0, regS[A]);
call->setArg(1, regD[B]);
break;
case CAST_S2So:
resultD = newResultInt32();
call = CreateCall<int, FString*>([](FString *b) -> int { return FSoundID(*b); });
call = CreateCall<int, FString*>(CastS2So);
call->setRet(0, resultD);
call->setArg(0, regS[B]);
cc.mov(regD[A], resultD);
break;
case CAST_So2S:
call = CreateCall<void, FString*, int>([](FString *a, int b) { *a = S_sfx[b].name; });
call = CreateCall<void, FString*, int>(CastSo2S);
call->setArg(0, regS[A]);
call->setArg(1, regD[B]);
break;
case CAST_SID2S:
call = CreateCall<void, FString*, unsigned int>([](FString *a, unsigned int b) { *a = (b >= sprites.Size()) ? "TNT1" : sprites[b].name; });
call = CreateCall<void, FString*, unsigned int>(CastSID2S);
call->setArg(0, regS[A]);
call->setArg(1, regD[B]);
break;
case CAST_TID2S:
call = CreateCall<void, FString*, int>([](FString *a, int b) { auto tex = TexMan[*(FTextureID*)&b]; *a = (tex == nullptr) ? "(null)" : tex->Name.GetChars(); });
call = CreateCall<void, FString*, int>(CastTID2S);
call->setArg(0, regS[A]);
call->setArg(1, regD[B]);
break;
@ -161,6 +178,8 @@ void JitCompiler::EmitCAST()
}
}
static int CastB_S(FString *s) { return s->Len() > 0; }
void JitCompiler::EmitCASTB()
{
if (C == CASTB_I)
@ -189,19 +208,22 @@ void JitCompiler::EmitCASTB()
else
{
auto result = newResultInt32();
auto call = CreateCall<int, FString*>([](FString *s) -> int { return s->Len() > 0; });
auto call = CreateCall<int, FString*>(CastB_S);
call->setRet(0, result);
call->setArg(0, regS[B]);
cc.mov(regD[A], result);
}
}
static DObject *DynCast(DObject *obj, PClass *cls)
{
return (obj && obj->IsKindOf(cls)) ? obj : nullptr;
}
void JitCompiler::EmitDYNCAST_R()
{
auto result = newResultIntPtr();
auto call = CreateCall<DObject*, DObject*, PClass*>([](DObject *obj, PClass *cls) -> DObject* {
return (obj && obj->IsKindOf(cls)) ? obj : nullptr;
});
auto call = CreateCall<DObject*, DObject*, PClass*>(DynCast);
call->setRet(0, result);
call->setArg(0, regA[B]);
call->setArg(1, regA[C]);
@ -213,21 +235,22 @@ void JitCompiler::EmitDYNCAST_K()
auto result = newResultIntPtr();
auto c = newTempIntPtr();
cc.mov(c, asmjit::imm_ptr(konsta[C].o));
auto call = CreateCall<DObject*, DObject*, PClass*>([](DObject *obj, PClass *cls) -> DObject* {
return (obj && obj->IsKindOf(cls)) ? obj : nullptr;
});
auto call = CreateCall<DObject*, DObject*, PClass*>(DynCast);
call->setRet(0, result);
call->setArg(0, regA[B]);
call->setArg(1, c);
cc.mov(regA[A], result);
}
static PClass *DynCastC(PClass *cls1, PClass *cls2)
{
return (cls1 && cls1->IsDescendantOf(cls2)) ? cls1 : nullptr;
}
void JitCompiler::EmitDYNCASTC_R()
{
auto result = newResultIntPtr();
auto call = CreateCall<PClass*, PClass*, PClass*>([](PClass *cls1, PClass *cls2) -> PClass* {
return (cls1 && cls1->IsDescendantOf(cls2)) ? cls1 : nullptr;
});
auto call = CreateCall<PClass*, PClass*, PClass*>(DynCastC);
call->setRet(0, result);
call->setArg(0, regA[B]);
call->setArg(1, regA[C]);
@ -241,9 +264,7 @@ void JitCompiler::EmitDYNCASTC_K()
auto c = newTempIntPtr();
cc.mov(c, asmjit::imm_ptr(konsta[C].o));
typedef PClass*(*FuncPtr)(PClass*, PClass*);
auto call = CreateCall<PClass*, PClass*, PClass*>([](PClass *cls1, PClass *cls2) -> PClass* {
return (cls1 && cls1->IsDescendantOf(cls2)) ? cls1 : nullptr;
});
auto call = CreateCall<PClass*, PClass*, PClass*>(DynCastC);
call->setRet(0, result);
call->setArg(0, regA[B]);
call->setArg(1, c);