Allow LocalVariable to be assigned more than once (#2288)

* Allow `LocalVariable` to be assigned more than once

This allows us to write flow controls like loops and if-elses with
LocalVariables participating in phi nodes.

* Add `GetLocalNumber` to operand
This commit is contained in:
FICTURE7 2021-05-17 03:54:53 +04:00 committed by GitHub
parent 212e472c9f
commit c805542b29
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 47 additions and 16 deletions

View file

@ -12,6 +12,8 @@ namespace ARMeilleure.Translation
{
class EmitterContext
{
private int _localsCount;
private readonly Dictionary<Operand, BasicBlock> _irLabels;
private readonly IntrusiveList<BasicBlock> _irBlocks;
@ -23,6 +25,8 @@ namespace ARMeilleure.Translation
public EmitterContext()
{
_localsCount = 0;
_irLabels = new Dictionary<Operand, BasicBlock>();
_irBlocks = new IntrusiveList<BasicBlock>();
@ -30,6 +34,15 @@ namespace ARMeilleure.Translation
_nextBlockFreq = BasicBlockFrequency.Default;
}
public Operand AllocateLocal(OperandType type)
{
Operand local = Local(type);
local.NumberLocal(++_localsCount);
return local;
}
public Operand Add(Operand op1, Operand op2)
{
return Add(Instruction.Add, Local(op1.Type), op1, op2);
@ -223,9 +236,10 @@ namespace ARMeilleure.Translation
public Operand Copy(Operand dest, Operand op1)
{
if (dest.Kind != OperandKind.Register)
if (dest.Kind != OperandKind.Register &&
(dest.Kind != OperandKind.LocalVariable || dest.GetLocalNumber() == 0))
{
throw new ArgumentException($"Invalid dest operand kind \"{dest.Kind}\".");
throw new ArgumentException($"Destination operand must be a Register or a numbered LocalVariable.");
}
return Add(Instruction.Copy, dest, op1);
@ -670,7 +684,7 @@ namespace ARMeilleure.Translation
public ControlFlowGraph GetControlFlowGraph()
{
return new ControlFlowGraph(_irBlocks.First, _irBlocks);
return new ControlFlowGraph(_irBlocks.First, _irBlocks, _localsCount);
}
}
}