Generalize tail continues (#1298)

* Generalize tail continues

* Fix DecodeBasicBlock

`Next` and `Branch` would be null, which is not the state expected by
the branch instructions. They end up branching or falling into a block
which is never populated by the `Translator`. This causes an assert to
be fired when building the CFG.

* Clean up Decode overloads

* Do not synchronize when branching into exit block

If we're branching into an exit block, that exit block will tail
continue into another translation which already has a synchronization.

* Remove A32 predicate tail continue

If `block` is not an exit block then the `block.Next` must exist (as
per the last instruction of `block`).

* Throw if decoded 0 blocks

Address gdkchan's feedback

* Rebuild block list instead of setting to null

Address gdkchan's feedback
This commit is contained in:
Ficture Seven 2020-06-18 07:37:21 +04:00 committed by GitHub
parent 5e724cf24e
commit 2421186d97
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 178 additions and 240 deletions

View file

@ -15,14 +15,7 @@ namespace ARMeilleure.Instructions
{
OpCodeBImmAl op = (OpCodeBImmAl)context.CurrOp;
if (context.CurrBlock.Branch != null)
{
context.Branch(context.GetLabel((ulong)op.Immediate));
}
else
{
EmitTailContinue(context, Const(op.Immediate), context.CurrBlock.TailCall);
}
context.Branch(context.GetLabel((ulong)op.Immediate));
}
public static void B_Cond(ArmEmitterContext context)
@ -92,69 +85,22 @@ namespace ARMeilleure.Instructions
{
OpCodeBImm op = (OpCodeBImm)context.CurrOp;
if (context.CurrBlock.Branch != null)
{
EmitCondBranch(context, context.GetLabel((ulong)op.Immediate), cond);
if (context.CurrBlock.Next == null)
{
EmitTailContinue(context, Const(op.Address + 4));
}
}
else
{
Operand lblTaken = Label();
EmitCondBranch(context, lblTaken, cond);
EmitTailContinue(context, Const(op.Address + 4));
context.MarkLabel(lblTaken);
EmitTailContinue(context, Const(op.Immediate));
}
EmitCondBranch(context, context.GetLabel((ulong)op.Immediate), cond);
}
private static void EmitBranch(ArmEmitterContext context, Operand value, bool onNotZero)
{
OpCodeBImm op = (OpCodeBImm)context.CurrOp;
if (context.CurrBlock.Branch != null)
Operand lblTarget = context.GetLabel((ulong)op.Immediate);
if (onNotZero)
{
Operand lblTarget = context.GetLabel((ulong)op.Immediate);
if (onNotZero)
{
context.BranchIfTrue(lblTarget, value);
}
else
{
context.BranchIfFalse(lblTarget, value);
}
if (context.CurrBlock.Next == null)
{
EmitTailContinue(context, Const(op.Address + 4));
}
context.BranchIfTrue(lblTarget, value);
}
else
{
Operand lblTaken = Label();
if (onNotZero)
{
context.BranchIfTrue(lblTaken, value);
}
else
{
context.BranchIfFalse(lblTaken, value);
}
EmitTailContinue(context, Const(op.Address + 4));
context.MarkLabel(lblTaken);
EmitTailContinue(context, Const(op.Immediate));
context.BranchIfFalse(lblTarget, value);
}
}
}