mirror of
https://github.com/ZDoom/qzdoom-gpl.git
synced 2025-02-12 06:40:56 +00:00
- branch optimization.
This commit is contained in:
parent
17d9a152e7
commit
77192fa9dd
4 changed files with 166 additions and 97 deletions
|
@ -288,6 +288,45 @@ ExpEmit FxExpression::Emit (VMFunctionBuilder *build)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void FxExpression::EmitCompare(VMFunctionBuilder *build, bool invert, TArray<size_t> &patchspots_yes, TArray<size_t> &patchspots_no)
|
||||||
|
{
|
||||||
|
ExpEmit op = Emit(build);
|
||||||
|
ExpEmit i;
|
||||||
|
assert(op.RegType != REGT_NIL && op.RegCount == 1 && !op.Konst);
|
||||||
|
switch (op.RegType)
|
||||||
|
{
|
||||||
|
case REGT_INT:
|
||||||
|
build->Emit(OP_EQ_K, !invert, op.RegNum, build->GetConstantInt(0));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REGT_FLOAT:
|
||||||
|
build->Emit(OP_EQF_K, !invert, op.RegNum, build->GetConstantFloat(0));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REGT_POINTER:
|
||||||
|
build->Emit(OP_EQA_K, !invert, op.RegNum, build->GetConstantAddress(0, ATAG_GENERIC));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REGT_STRING:
|
||||||
|
i = ExpEmit(build, REGT_INT);
|
||||||
|
build->Emit(OP_LENS, i.RegNum, op.RegNum);
|
||||||
|
build->Emit(OP_EQ_K, !invert, i.RegNum, build->GetConstantInt(0));
|
||||||
|
i.Free(build);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
patchspots_no.Push(build->Emit(OP_JMP, 0));
|
||||||
|
op.Free(build);
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
@ -757,7 +796,6 @@ ExpEmit FxBoolCast::Emit(VMFunctionBuilder *build)
|
||||||
{
|
{
|
||||||
ExpEmit to(build, REGT_INT);
|
ExpEmit to(build, REGT_INT);
|
||||||
from.Free(build);
|
from.Free(build);
|
||||||
// Preload result with 0.
|
|
||||||
build->Emit(OP_CASTB, to.RegNum, from.RegNum, from.RegType == REGT_INT ? CASTB_I : from.RegType == REGT_FLOAT ? CASTB_F : CASTB_A);
|
build->Emit(OP_CASTB, to.RegNum, from.RegNum, from.RegType == REGT_INT ? CASTB_I : from.RegType == REGT_FLOAT ? CASTB_F : CASTB_A);
|
||||||
return to;
|
return to;
|
||||||
}
|
}
|
||||||
|
@ -773,6 +811,17 @@ ExpEmit FxBoolCast::Emit(VMFunctionBuilder *build)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
|
void FxBoolCast::EmitCompare(VMFunctionBuilder *build, bool invert, TArray<size_t> &patchspots_yes, TArray<size_t> &patchspots_no)
|
||||||
|
{
|
||||||
|
basex->EmitCompare(build, invert, patchspots_yes, patchspots_no);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
FxIntCast::FxIntCast(FxExpression *x, bool nowarn, bool explicitly)
|
FxIntCast::FxIntCast(FxExpression *x, bool nowarn, bool explicitly)
|
||||||
: FxExpression(EFX_IntCast, x->ScriptPosition)
|
: FxExpression(EFX_IntCast, x->ScriptPosition)
|
||||||
{
|
{
|
||||||
|
@ -1872,6 +1921,17 @@ ExpEmit FxUnaryNotBoolean::Emit(VMFunctionBuilder *build)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
|
void FxUnaryNotBoolean::EmitCompare(VMFunctionBuilder *build, bool invert, TArray<size_t> &patchspots_yes, TArray<size_t> &patchspots_no)
|
||||||
|
{
|
||||||
|
Operand->EmitCompare(build, !invert, patchspots_yes, patchspots_no);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
FxSizeAlign::FxSizeAlign(FxExpression *operand, int which)
|
FxSizeAlign::FxSizeAlign(FxExpression *operand, int which)
|
||||||
: FxExpression(EFX_SizeAlign, operand->ScriptPosition)
|
: FxExpression(EFX_SizeAlign, operand->ScriptPosition)
|
||||||
{
|
{
|
||||||
|
@ -3124,7 +3184,7 @@ FxExpression *FxCompareRel::Resolve(FCompileContext& ctx)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
ExpEmit FxCompareRel::Emit(VMFunctionBuilder *build)
|
ExpEmit FxCompareRel::EmitCommon(VMFunctionBuilder *build, bool forcompare, bool invert)
|
||||||
{
|
{
|
||||||
ExpEmit op1 = left->Emit(build);
|
ExpEmit op1 = left->Emit(build);
|
||||||
ExpEmit op2 = right->Emit(build);
|
ExpEmit op2 = right->Emit(build);
|
||||||
|
@ -3154,11 +3214,15 @@ ExpEmit FxCompareRel::Emit(VMFunctionBuilder *build)
|
||||||
{
|
{
|
||||||
op2.Free(build);
|
op2.Free(build);
|
||||||
}
|
}
|
||||||
|
if (invert) a ^= CMP_CHECK;
|
||||||
|
|
||||||
build->Emit(OP_LI, to.RegNum, 0, 0);
|
if (!forcompare) build->Emit(OP_LI, to.RegNum, 0, 0);
|
||||||
build->Emit(OP_CMPS, a, op1.RegNum, op2.RegNum);
|
build->Emit(OP_CMPS, a, op1.RegNum, op2.RegNum);
|
||||||
|
if (!forcompare)
|
||||||
|
{
|
||||||
build->Emit(OP_JMP, 1);
|
build->Emit(OP_JMP, 1);
|
||||||
build->Emit(OP_LI, to.RegNum, 1);
|
build->Emit(OP_LI, to.RegNum, 1);
|
||||||
|
}
|
||||||
return to;
|
return to;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -3197,16 +3261,32 @@ ExpEmit FxCompareRel::Emit(VMFunctionBuilder *build)
|
||||||
{
|
{
|
||||||
op1.Free(build);
|
op1.Free(build);
|
||||||
}
|
}
|
||||||
|
if (invert) check ^= 1;
|
||||||
|
|
||||||
// See FxBoolCast for comments, since it's the same thing.
|
// See FxBoolCast for comments, since it's the same thing.
|
||||||
build->Emit(OP_LI, to.RegNum, 0, 0);
|
if (!forcompare) build->Emit(OP_LI, to.RegNum, 0, 0);
|
||||||
build->Emit(instr, check, op1.RegNum, op2.RegNum);
|
build->Emit(instr, check, op1.RegNum, op2.RegNum);
|
||||||
|
if (!forcompare)
|
||||||
|
{
|
||||||
build->Emit(OP_JMP, 1);
|
build->Emit(OP_JMP, 1);
|
||||||
build->Emit(OP_LI, to.RegNum, 1);
|
build->Emit(OP_LI, to.RegNum, 1);
|
||||||
|
}
|
||||||
return to;
|
return to;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExpEmit FxCompareRel::Emit(VMFunctionBuilder *build)
|
||||||
|
{
|
||||||
|
return EmitCommon(build, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FxCompareRel::EmitCompare(VMFunctionBuilder *build, bool invert, TArray<size_t> &patchspots_yes, TArray<size_t> &patchspots_no)
|
||||||
|
{
|
||||||
|
ExpEmit emit = EmitCommon(build, true, invert);
|
||||||
|
emit.Free(build);
|
||||||
|
patchspots_no.Push(build->Emit(OP_JMP, 0));
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
@ -3404,7 +3484,7 @@ error:
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
ExpEmit FxCompareEq::Emit(VMFunctionBuilder *build)
|
ExpEmit FxCompareEq::EmitCommon(VMFunctionBuilder *build, bool forcompare, bool invert)
|
||||||
{
|
{
|
||||||
ExpEmit op1 = left->Emit(build);
|
ExpEmit op1 = left->Emit(build);
|
||||||
ExpEmit op2 = right->Emit(build);
|
ExpEmit op2 = right->Emit(build);
|
||||||
|
@ -3418,13 +3498,17 @@ ExpEmit FxCompareEq::Emit(VMFunctionBuilder *build)
|
||||||
int a = Operator == TK_Eq ? CMP_EQ :
|
int a = Operator == TK_Eq ? CMP_EQ :
|
||||||
Operator == TK_Neq ? CMP_EQ | CMP_CHECK : CMP_EQ | CMP_APPROX;
|
Operator == TK_Neq ? CMP_EQ | CMP_CHECK : CMP_EQ | CMP_APPROX;
|
||||||
|
|
||||||
if (op1.Konst) a|= CMP_BK;
|
if (op1.Konst) a |= CMP_BK;
|
||||||
if (op2.Konst) a |= CMP_CK;
|
if (op2.Konst) a |= CMP_CK;
|
||||||
|
if (invert) a ^= CMP_CHECK;
|
||||||
|
|
||||||
build->Emit(OP_LI, to.RegNum, 0, 0);
|
if (!forcompare) build->Emit(OP_LI, to.RegNum, 0, 0);
|
||||||
build->Emit(OP_CMPS, a, op1.RegNum, op2.RegNum);
|
build->Emit(OP_CMPS, a, op1.RegNum, op2.RegNum);
|
||||||
|
if (!forcompare)
|
||||||
|
{
|
||||||
build->Emit(OP_JMP, 1);
|
build->Emit(OP_JMP, 1);
|
||||||
build->Emit(OP_LI, to.RegNum, 1);
|
build->Emit(OP_LI, to.RegNum, 1);
|
||||||
|
}
|
||||||
op1.Free(build);
|
op1.Free(build);
|
||||||
op2.Free(build);
|
op2.Free(build);
|
||||||
return to;
|
return to;
|
||||||
|
@ -3457,14 +3541,29 @@ ExpEmit FxCompareEq::Emit(VMFunctionBuilder *build)
|
||||||
}
|
}
|
||||||
|
|
||||||
// See FxUnaryNotBoolean for comments, since it's the same thing.
|
// See FxUnaryNotBoolean for comments, since it's the same thing.
|
||||||
build->Emit(OP_LI, to.RegNum, 0, 0);
|
if (!forcompare) build->Emit(OP_LI, to.RegNum, 0, 0);
|
||||||
build->Emit(instr, Operator == TK_ApproxEq ? CMP_APPROX : ((Operator != TK_Eq) ? CMP_CHECK : 0), op1.RegNum, op2.RegNum);
|
build->Emit(instr, int(invert) ^ (Operator == TK_ApproxEq ? CMP_APPROX : ((Operator != TK_Eq) ? CMP_CHECK : 0)), op1.RegNum, op2.RegNum);
|
||||||
|
if (!forcompare)
|
||||||
|
{
|
||||||
build->Emit(OP_JMP, 1);
|
build->Emit(OP_JMP, 1);
|
||||||
build->Emit(OP_LI, to.RegNum, 1);
|
build->Emit(OP_LI, to.RegNum, 1);
|
||||||
|
}
|
||||||
return to;
|
return to;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExpEmit FxCompareEq::Emit(VMFunctionBuilder *build)
|
||||||
|
{
|
||||||
|
return EmitCommon(build, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FxCompareEq::EmitCompare(VMFunctionBuilder *build, bool invert, TArray<size_t> &patchspots_yes, TArray<size_t> &patchspots_no)
|
||||||
|
{
|
||||||
|
ExpEmit emit = EmitCommon(build, true, invert);
|
||||||
|
emit.Free(build);
|
||||||
|
patchspots_no.Push(build->Emit(OP_JMP, 0));
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
@ -4447,21 +4546,17 @@ FxExpression *FxConditional::Resolve(FCompileContext& ctx)
|
||||||
|
|
||||||
ExpEmit FxConditional::Emit(VMFunctionBuilder *build)
|
ExpEmit FxConditional::Emit(VMFunctionBuilder *build)
|
||||||
{
|
{
|
||||||
size_t truejump, falsejump;
|
size_t truejump;
|
||||||
ExpEmit out;
|
ExpEmit out, falseout;
|
||||||
|
|
||||||
// The true and false expressions ought to be assigned to the
|
// The true and false expressions ought to be assigned to the
|
||||||
// same temporary instead of being copied to it. Oh well; good enough
|
// same temporary instead of being copied to it. Oh well; good enough
|
||||||
// for now.
|
// for now.
|
||||||
ExpEmit cond = condition->Emit(build);
|
TArray<size_t> yes, no;
|
||||||
assert(cond.RegType == REGT_INT && !cond.Konst);
|
condition->EmitCompare(build, false, yes, no);
|
||||||
|
|
||||||
// Test condition.
|
build->BackpatchListToHere(yes);
|
||||||
build->Emit(OP_EQ_K, 1, cond.RegNum, build->GetConstantInt(0));
|
|
||||||
falsejump = build->Emit(OP_JMP, 0);
|
|
||||||
cond.Free(build);
|
|
||||||
|
|
||||||
// Evaluate true expression.
|
|
||||||
if (truex->isConstant() && truex->ValueType->GetRegType() == REGT_INT)
|
if (truex->isConstant() && truex->ValueType->GetRegType() == REGT_INT)
|
||||||
{
|
{
|
||||||
out = ExpEmit(build, REGT_INT);
|
out = ExpEmit(build, REGT_INT);
|
||||||
|
@ -4501,7 +4596,7 @@ ExpEmit FxConditional::Emit(VMFunctionBuilder *build)
|
||||||
truejump = build->Emit(OP_JMP, 0);
|
truejump = build->Emit(OP_JMP, 0);
|
||||||
|
|
||||||
// Evaluate false expression.
|
// Evaluate false expression.
|
||||||
build->BackpatchToHere(falsejump);
|
build->BackpatchListToHere(no);
|
||||||
if (falsex->isConstant() && falsex->ValueType->GetRegType() == REGT_INT)
|
if (falsex->isConstant() && falsex->ValueType->GetRegType() == REGT_INT)
|
||||||
{
|
{
|
||||||
build->EmitLoadInt(out.RegNum, static_cast<FxConstant *>(falsex)->GetValue().GetInt());
|
build->EmitLoadInt(out.RegNum, static_cast<FxConstant *>(falsex)->GetValue().GetInt());
|
||||||
|
@ -8858,68 +8953,28 @@ FxExpression *FxIfStatement::Resolve(FCompileContext &ctx)
|
||||||
ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build)
|
ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build)
|
||||||
{
|
{
|
||||||
ExpEmit v;
|
ExpEmit v;
|
||||||
size_t jumpspot;
|
size_t jumpspot = ~0u;
|
||||||
FxExpression *path1, *path2;
|
|
||||||
int condcheck;
|
|
||||||
|
|
||||||
// This is pretty much copied from FxConditional, except we don't
|
TArray<size_t> yes, no;
|
||||||
// keep any results.
|
Condition->EmitCompare(build, false, yes, no);
|
||||||
ExpEmit cond = Condition->Emit(build);
|
|
||||||
assert(cond.RegType != REGT_STRING && !cond.Konst);
|
|
||||||
|
|
||||||
if (WhenTrue != nullptr)
|
if (WhenTrue != nullptr)
|
||||||
{
|
{
|
||||||
path1 = WhenTrue;
|
build->BackpatchListToHere(yes);
|
||||||
path2 = WhenFalse;
|
WhenTrue->Emit(build);
|
||||||
condcheck = 1;
|
}
|
||||||
|
if (WhenFalse != nullptr)
|
||||||
|
{
|
||||||
|
if (!WhenTrue->CheckReturn()) jumpspot = build->Emit(OP_JMP, 0); // no need to emit a jump if the block returns.
|
||||||
|
build->BackpatchListToHere(no);
|
||||||
|
WhenFalse->Emit(build);
|
||||||
|
if (jumpspot != ~0u) build->BackpatchToHere(jumpspot);
|
||||||
|
if (WhenTrue == nullptr) build->BackpatchListToHere(yes);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// When there is only a false path, reverse the condition so we can
|
build->BackpatchListToHere(no);
|
||||||
// treat it as a true path.
|
|
||||||
assert(WhenFalse != nullptr);
|
|
||||||
path1 = WhenFalse;
|
|
||||||
path2 = nullptr;
|
|
||||||
condcheck = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test condition.
|
|
||||||
|
|
||||||
switch (cond.RegType)
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
case REGT_INT:
|
|
||||||
build->Emit(OP_EQ_K, condcheck, cond.RegNum, build->GetConstantInt(0));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case REGT_FLOAT:
|
|
||||||
build->Emit(OP_EQF_K, condcheck, cond.RegNum, build->GetConstantFloat(0));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case REGT_POINTER:
|
|
||||||
build->Emit(OP_EQA_K, condcheck, cond.RegNum, build->GetConstantAddress(nullptr, ATAG_GENERIC));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
jumpspot = build->Emit(OP_JMP, 0);
|
|
||||||
cond.Free(build);
|
|
||||||
|
|
||||||
// Evaluate first path
|
|
||||||
v = path1->Emit(build);
|
|
||||||
v.Free(build);
|
|
||||||
if (path2 != nullptr)
|
|
||||||
{
|
|
||||||
size_t path1jump;
|
|
||||||
|
|
||||||
// if the branch ends with a return we do not need a terminating jmp.
|
|
||||||
if (!path1->CheckReturn()) path1jump = build->Emit(OP_JMP, 0);
|
|
||||||
else path1jump = 0xffffffff;
|
|
||||||
// Evaluate second path
|
|
||||||
build->BackpatchToHere(jumpspot);
|
|
||||||
v = path2->Emit(build);
|
|
||||||
v.Free(build);
|
|
||||||
jumpspot = path1jump;
|
|
||||||
}
|
|
||||||
if (jumpspot != 0xffffffff) build->BackpatchToHere(jumpspot);
|
|
||||||
return ExpEmit();
|
return ExpEmit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9027,19 +9082,17 @@ ExpEmit FxWhileLoop::Emit(VMFunctionBuilder *build)
|
||||||
assert(Condition->ValueType == TypeBool);
|
assert(Condition->ValueType == TypeBool);
|
||||||
|
|
||||||
size_t loopstart, loopend;
|
size_t loopstart, loopend;
|
||||||
size_t jumpspot;
|
TArray<size_t> yes, no;
|
||||||
|
|
||||||
// Evaluate the condition and execute/break out of the loop.
|
// Evaluate the condition and execute/break out of the loop.
|
||||||
loopstart = build->GetAddress();
|
loopstart = build->GetAddress();
|
||||||
if (!Condition->isConstant())
|
if (!Condition->isConstant())
|
||||||
{
|
{
|
||||||
ExpEmit cond = Condition->Emit(build);
|
Condition->EmitCompare(build, false, yes, no);
|
||||||
build->Emit(OP_TEST, cond.RegNum, 0);
|
|
||||||
jumpspot = build->Emit(OP_JMP, 0);
|
|
||||||
cond.Free(build);
|
|
||||||
}
|
}
|
||||||
else assert(static_cast<FxConstant *>(Condition)->GetValue().GetBool() == true);
|
else assert(static_cast<FxConstant *>(Condition)->GetValue().GetBool() == true);
|
||||||
|
|
||||||
|
build->BackpatchListToHere(yes);
|
||||||
// Execute the loop's content.
|
// Execute the loop's content.
|
||||||
if (Code != nullptr)
|
if (Code != nullptr)
|
||||||
{
|
{
|
||||||
|
@ -9049,13 +9102,8 @@ ExpEmit FxWhileLoop::Emit(VMFunctionBuilder *build)
|
||||||
|
|
||||||
// Loop back.
|
// Loop back.
|
||||||
build->Backpatch(build->Emit(OP_JMP, 0), loopstart);
|
build->Backpatch(build->Emit(OP_JMP, 0), loopstart);
|
||||||
|
build->BackpatchListToHere(no);
|
||||||
loopend = build->GetAddress();
|
loopend = build->GetAddress();
|
||||||
|
|
||||||
if (!Condition->isConstant())
|
|
||||||
{
|
|
||||||
build->Backpatch(jumpspot, loopend);
|
|
||||||
}
|
|
||||||
|
|
||||||
Backpatch(build, loopstart, loopend);
|
Backpatch(build, loopstart, loopend);
|
||||||
return ExpEmit();
|
return ExpEmit();
|
||||||
}
|
}
|
||||||
|
@ -9132,17 +9180,16 @@ ExpEmit FxDoWhileLoop::Emit(VMFunctionBuilder *build)
|
||||||
loopstart = build->GetAddress();
|
loopstart = build->GetAddress();
|
||||||
if (!Condition->isConstant())
|
if (!Condition->isConstant())
|
||||||
{
|
{
|
||||||
ExpEmit cond = Condition->Emit(build);
|
TArray<size_t> yes, no;
|
||||||
build->Emit(OP_TEST, cond.RegNum, 1);
|
Condition->EmitCompare(build, true, yes, no);
|
||||||
cond.Free(build);
|
build->BackpatchList(no, codestart);
|
||||||
build->Backpatch(build->Emit(OP_JMP, 0), codestart);
|
build->BackpatchListToHere(yes);
|
||||||
}
|
}
|
||||||
else if (static_cast<FxConstant *>(Condition)->GetValue().GetBool() == true)
|
else if (static_cast<FxConstant *>(Condition)->GetValue().GetBool() == true)
|
||||||
{ // Always looping
|
{ // Always looping
|
||||||
build->Backpatch(build->Emit(OP_JMP, 0), codestart);
|
build->Backpatch(build->Emit(OP_JMP, 0), codestart);
|
||||||
}
|
}
|
||||||
loopend = build->GetAddress();
|
loopend = build->GetAddress();
|
||||||
|
|
||||||
Backpatch(build, loopstart, loopend);
|
Backpatch(build, loopstart, loopend);
|
||||||
|
|
||||||
return ExpEmit();
|
return ExpEmit();
|
||||||
|
|
|
@ -328,6 +328,7 @@ public:
|
||||||
bool IsObject() const { return ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && !ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)) && ValueType != TypeNullPtr && static_cast<PPointer*>(ValueType)->PointedType->IsKindOf(RUNTIME_CLASS(PClass)); }
|
bool IsObject() const { return ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && !ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)) && ValueType != TypeNullPtr && static_cast<PPointer*>(ValueType)->PointedType->IsKindOf(RUNTIME_CLASS(PClass)); }
|
||||||
|
|
||||||
virtual ExpEmit Emit(VMFunctionBuilder *build);
|
virtual ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
|
virtual void EmitCompare(VMFunctionBuilder *build, bool invert, TArray<size_t> &patchspots_yes, TArray<size_t> &patchspots_no);
|
||||||
|
|
||||||
FScriptPosition ScriptPosition;
|
FScriptPosition ScriptPosition;
|
||||||
PType *ValueType = nullptr;
|
PType *ValueType = nullptr;
|
||||||
|
@ -565,6 +566,7 @@ public:
|
||||||
FxExpression *Resolve(FCompileContext&);
|
FxExpression *Resolve(FCompileContext&);
|
||||||
|
|
||||||
ExpEmit Emit(VMFunctionBuilder *build);
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
|
void EmitCompare(VMFunctionBuilder *build, bool invert, TArray<size_t> &patchspots_yes, TArray<size_t> &patchspots_no);
|
||||||
};
|
};
|
||||||
|
|
||||||
class FxIntCast : public FxExpression
|
class FxIntCast : public FxExpression
|
||||||
|
@ -734,6 +736,7 @@ public:
|
||||||
~FxUnaryNotBoolean();
|
~FxUnaryNotBoolean();
|
||||||
FxExpression *Resolve(FCompileContext&);
|
FxExpression *Resolve(FCompileContext&);
|
||||||
ExpEmit Emit(VMFunctionBuilder *build);
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
|
void EmitCompare(VMFunctionBuilder *build, bool invert, TArray<size_t> &patchspots_yes, TArray<size_t> &patchspots_no);
|
||||||
};
|
};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -934,7 +937,9 @@ public:
|
||||||
|
|
||||||
FxCompareRel(int, FxExpression*, FxExpression*);
|
FxCompareRel(int, FxExpression*, FxExpression*);
|
||||||
FxExpression *Resolve(FCompileContext&);
|
FxExpression *Resolve(FCompileContext&);
|
||||||
|
ExpEmit EmitCommon(VMFunctionBuilder *build, bool forcompare, bool invert);
|
||||||
ExpEmit Emit(VMFunctionBuilder *build);
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
|
void EmitCompare(VMFunctionBuilder *build, bool invert, TArray<size_t> &patchspots_yes, TArray<size_t> &patchspots_no);
|
||||||
};
|
};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -949,7 +954,9 @@ public:
|
||||||
|
|
||||||
FxCompareEq(int, FxExpression*, FxExpression*);
|
FxCompareEq(int, FxExpression*, FxExpression*);
|
||||||
FxExpression *Resolve(FCompileContext&);
|
FxExpression *Resolve(FCompileContext&);
|
||||||
|
ExpEmit EmitCommon(VMFunctionBuilder *build, bool forcompare, bool invert);
|
||||||
ExpEmit Emit(VMFunctionBuilder *build);
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
|
void EmitCompare(VMFunctionBuilder *build, bool invert, TArray<size_t> &patchspots_yes, TArray<size_t> &patchspots_no);
|
||||||
};
|
};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
|
@ -734,6 +734,13 @@ void VMFunctionBuilder::Backpatch(size_t loc, size_t target)
|
||||||
Code[loc].i24 = offset;
|
Code[loc].i24 = offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VMFunctionBuilder::BackpatchList(TArray<size_t> &locs, size_t target)
|
||||||
|
{
|
||||||
|
for (auto loc : locs)
|
||||||
|
Backpatch(loc, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// VMFunctionBuilder :: BackpatchToHere
|
// VMFunctionBuilder :: BackpatchToHere
|
||||||
|
@ -748,6 +755,12 @@ void VMFunctionBuilder::BackpatchToHere(size_t loc)
|
||||||
Backpatch(loc, Code.Size());
|
Backpatch(loc, Code.Size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VMFunctionBuilder::BackpatchListToHere(TArray<size_t> &locs)
|
||||||
|
{
|
||||||
|
for (auto loc : locs)
|
||||||
|
Backpatch(loc, Code.Size());
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// FFunctionBuildList
|
// FFunctionBuildList
|
||||||
|
|
|
@ -69,6 +69,8 @@ public:
|
||||||
|
|
||||||
void Backpatch(size_t addr, size_t target);
|
void Backpatch(size_t addr, size_t target);
|
||||||
void BackpatchToHere(size_t addr);
|
void BackpatchToHere(size_t addr);
|
||||||
|
void BackpatchList(TArray<size_t> &addrs, size_t target);
|
||||||
|
void BackpatchListToHere(TArray<size_t> &addrs);
|
||||||
|
|
||||||
// Write out complete constant tables.
|
// Write out complete constant tables.
|
||||||
void FillIntConstants(int *konst);
|
void FillIntConstants(int *konst);
|
||||||
|
|
Loading…
Reference in a new issue