Support multiple destination operands

This commit is contained in:
gdkchan 2019-07-27 22:17:31 -03:00
commit 36be15fe6c
9 changed files with 244 additions and 188 deletions

View file

@ -695,19 +695,24 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{ {
Node operation = GetOperationNode(usePosition).Value; Node operation = GetOperationNode(usePosition).Value;
for (int srcIndex = 0; srcIndex < operation.SourcesCount; srcIndex++) for (int index = 0; index < operation.SourcesCount; index++)
{ {
Operand source = operation.GetSource(srcIndex); Operand source = operation.GetSource(index);
if (source == current.Local) if (source == current.Local)
{ {
operation.SetSource(srcIndex, register); operation.SetSource(index, register);
} }
} }
if (operation.Dest == current.Local) for (int index = 0; index < operation.DestinationsCount; index++)
{ {
operation.Dest = register; Operand dest = operation.GetDestination(index);
if (dest == current.Local)
{
operation.SetDestination(index, register);
}
} }
} }
} }
@ -753,13 +758,14 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
Node operation = node.Value; Node operation = node.Value;
Operand dest = operation.Dest; foreach (Operand dest in Destinations(operation))
if (dest != null && dest.Kind == OperandKind.LocalVariable && visited.Add(dest))
{ {
dest.NumberLocal(_intervals.Count); if (dest.Kind == OperandKind.LocalVariable && visited.Add(dest))
{
dest.NumberLocal(_intervals.Count);
_intervals.Add(new LiveInterval(dest)); _intervals.Add(new LiveInterval(dest));
}
} }
} }
@ -794,7 +800,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
foreach (Node node in block.Operations) foreach (Node node in block.Operations)
{ {
foreach (Operand source in Operands(node)) foreach (Operand source in Sources(node))
{ {
int id = GetOperandId(source); int id = GetOperandId(source);
@ -804,9 +810,9 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
} }
} }
if (node.Dest != null && IsLocalOrRegister(node.Dest.Kind)) foreach (Operand dest in Destinations(node))
{ {
liveKill.Set(GetOperandId(node.Dest)); liveKill.Set(GetOperandId(dest));
} }
} }
@ -894,9 +900,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{ {
operationPos -= InstructionGap; operationPos -= InstructionGap;
Operand dest = node.Dest; foreach (Operand dest in Destinations(node))
if (dest != null && IsLocalOrRegister(dest.Kind))
{ {
LiveInterval interval = _intervals[GetOperandId(dest)]; LiveInterval interval = _intervals[GetOperandId(dest)];
@ -904,7 +908,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
interval.AddUsePosition(operationPos + 1); interval.AddUsePosition(operationPos + 1);
} }
foreach (Operand source in Operands(node)) foreach (Operand source in Sources(node))
{ {
LiveInterval interval = _intervals[GetOperandId(source)]; LiveInterval interval = _intervals[GetOperandId(source)];
@ -983,7 +987,15 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
} }
} }
private static IEnumerable<Operand> Operands(Node node) private static IEnumerable<Operand> Destinations(Node node)
{
for (int index = 0; index < node.DestinationsCount; index++)
{
yield return node.GetDestination(index);
}
}
private static IEnumerable<Operand> Sources(Node node)
{ {
for (int index = 0; index < node.SourcesCount; index++) for (int index = 0; index < node.SourcesCount; index++)
{ {

View file

@ -700,6 +700,10 @@ namespace ARMeilleure.CodeGen.X86
if (dest.Type.IsInteger()) if (dest.Type.IsInteger())
{ {
divisor = operation.GetSource(2);
EnsureSameType(dest, divisor);
if (divisor.Type == OperandType.I32) if (divisor.Type == OperandType.I32)
{ {
context.Assembler.Cdq(); context.Assembler.Cdq();
@ -723,7 +727,7 @@ namespace ARMeilleure.CodeGen.X86
private static void GenerateDivideUI(CodeGenContext context, Operation operation) private static void GenerateDivideUI(CodeGenContext context, Operation operation)
{ {
Operand divisor = operation.GetSource(1); Operand divisor = operation.GetSource(2);
Operand rdx = Register(X86Register.Rdx); Operand rdx = Register(X86Register.Rdx);

View file

@ -79,7 +79,7 @@ namespace ARMeilleure.CodeGen.X86
{ {
HandleLoadArgumentWindowsAbi(cctx, node, preservedArgs, operation); HandleLoadArgumentWindowsAbi(cctx, node, preservedArgs, operation);
} }
else else /* if (callConv == CallConvName.SystemV) */
{ {
HandleLoadArgumentSystemVAbi(cctx, node, preservedArgs, operation); HandleLoadArgumentSystemVAbi(cctx, node, preservedArgs, operation);
} }
@ -209,28 +209,26 @@ namespace ARMeilleure.CodeGen.X86
// - The expected value should be in RDX:RAX. // - The expected value should be in RDX:RAX.
// - The new value to be written should be in RCX:RBX. // - The new value to be written should be in RCX:RBX.
// - The value at the memory location is loaded to RDX:RAX. // - The value at the memory location is loaded to RDX:RAX.
void SplitOperand(Operand source, X86Register lowReg, X86Register highReg) void SplitOperand(Operand source, Operand lr, Operand hr)
{ {
Operand lr = Gpr(lowReg, OperandType.I64);
Operand hr = Gpr(highReg, OperandType.I64);
nodes.AddBefore(node, new Operation(Instruction.VectorExtract, lr, source, Const(0))); nodes.AddBefore(node, new Operation(Instruction.VectorExtract, lr, source, Const(0)));
nodes.AddBefore(node, new Operation(Instruction.VectorExtract, hr, source, Const(1))); nodes.AddBefore(node, new Operation(Instruction.VectorExtract, hr, source, Const(1)));
} }
SplitOperand(operation.GetSource(1), X86Register.Rax, X86Register.Rdx);
SplitOperand(operation.GetSource(2), X86Register.Rbx, X86Register.Rcx);
Operand rax = Gpr(X86Register.Rax, OperandType.I64); Operand rax = Gpr(X86Register.Rax, OperandType.I64);
Operand rbx = Gpr(X86Register.Rbx, OperandType.I64);
Operand rcx = Gpr(X86Register.Rcx, OperandType.I64);
Operand rdx = Gpr(X86Register.Rdx, OperandType.I64); Operand rdx = Gpr(X86Register.Rdx, OperandType.I64);
SplitOperand(operation.GetSource(1), rax, rdx);
SplitOperand(operation.GetSource(2), rbx, rcx);
node = nodes.AddAfter(node, new Operation(Instruction.VectorCreateScalar, dest, rax)); node = nodes.AddAfter(node, new Operation(Instruction.VectorCreateScalar, dest, rax));
node = nodes.AddAfter(node, new Operation(Instruction.VectorInsert, dest, dest, rdx, Const(1))); node = nodes.AddAfter(node, new Operation(Instruction.VectorInsert, dest, dest, rdx, Const(1)));
operation.SetSource(1, Undef()); operation.SetDestinations(new Operand[] { rdx, rax });
operation.SetSource(2, Undef());
operation.Dest = null; operation.SetSources(new Operand[] { operation.GetSource(0), rdx, rax, rcx, rbx });
break; break;
} }
@ -245,25 +243,24 @@ namespace ARMeilleure.CodeGen.X86
Operand eax = Gpr(X86Register.Rax, OperandType.I32); Operand eax = Gpr(X86Register.Rax, OperandType.I32);
Operand ebx = Gpr(X86Register.Rbx, OperandType.I32); Operand ebx = Gpr(X86Register.Rbx, OperandType.I32);
Operand rcx = Gpr(X86Register.Rcx, OperandType.I64); Operand ecx = Gpr(X86Register.Rcx, OperandType.I32);
Operand edx = Gpr(X86Register.Rdx, OperandType.I32); Operand edx = Gpr(X86Register.Rdx, OperandType.I32);
// Value 0x01 = Version, family and feature information. // Value 0x01 = Version, family and feature information.
nodes.AddBefore(node, new Operation(Instruction.Copy, eax, Const(1))); nodes.AddBefore(node, new Operation(Instruction.Copy, eax, Const(1)));
// We don't care about those two, but their values are overwritten,
// so we need to take that into account.
node = nodes.AddAfter(node, new Operation(Instruction.Clobber, eax));
node = nodes.AddAfter(node, new Operation(Instruction.Clobber, ebx));
// Copy results to the destination register. // Copy results to the destination register.
// The values are split into 2 32-bits registers, we merge them // The values are split into 2 32-bits registers, we merge them
// into a single 64-bits register. // into a single 64-bits register.
Operand rcx = Gpr(X86Register.Rcx, OperandType.I64);
node = nodes.AddAfter(node, new Operation(Instruction.ZeroExtend32, dest, edx)); node = nodes.AddAfter(node, new Operation(Instruction.ZeroExtend32, dest, edx));
node = nodes.AddAfter(node, new Operation(Instruction.ShiftLeft, dest, dest, Const(32))); node = nodes.AddAfter(node, new Operation(Instruction.ShiftLeft, dest, dest, Const(32)));
node = nodes.AddAfter(node, new Operation(Instruction.BitwiseOr, dest, dest, rcx)); node = nodes.AddAfter(node, new Operation(Instruction.BitwiseOr, dest, dest, rcx));
operation.Dest = null; operation.SetDestinations(new Operand[] { eax, ebx, ecx, edx });
operation.SetSources(new Operand[] { eax });
break; break;
} }
@ -280,14 +277,15 @@ namespace ARMeilleure.CodeGen.X86
Operand rax = Gpr(X86Register.Rax, src1.Type); Operand rax = Gpr(X86Register.Rax, src1.Type);
Operand rdx = Gpr(X86Register.Rdx, src1.Type); Operand rdx = Gpr(X86Register.Rdx, src1.Type);
nodes.AddBefore(node, new Operation(Instruction.Copy, rax, src1)); nodes.AddBefore(node, new Operation(Instruction.Copy, rax, src1));
operation.SetSource(0, rax);
nodes.AddBefore(node, new Operation(Instruction.Clobber, rdx)); nodes.AddBefore(node, new Operation(Instruction.Clobber, rdx));
node = nodes.AddAfter(node, new Operation(Instruction.Copy, dest, rax)); node = nodes.AddAfter(node, new Operation(Instruction.Copy, dest, rax));
operation.SetDestinations(new Operand[] { rdx, rax });
operation.SetSources(new Operand[] { rdx, rax, operation.GetSource(1) });
operation.Dest = rax; operation.Dest = rax;
break; break;
@ -328,7 +326,7 @@ namespace ARMeilleure.CodeGen.X86
node = nodes.AddAfter(node, new Operation(Instruction.Copy, dest, rdx)); node = nodes.AddAfter(node, new Operation(Instruction.Copy, dest, rdx));
operation.Dest = rdx; operation.SetDestinations(new Operand[] { rdx, rax });
break; break;
} }
@ -571,11 +569,13 @@ namespace ARMeilleure.CodeGen.X86
return offset; return offset;
} }
Operand arg0Reg = null;
if (dest != null && dest.Type == OperandType.V128) if (dest != null && dest.Type == OperandType.V128)
{ {
int stackOffset = AllocateOnStack(dest.Type.GetSizeInBytes()); int stackOffset = AllocateOnStack(dest.Type.GetSizeInBytes());
Operand arg0Reg = Gpr(CallingConvention.GetIntArgumentRegister(0), OperandType.I64); arg0Reg = Gpr(CallingConvention.GetIntArgumentRegister(0), OperandType.I64);
Operation allocOp = new Operation(Instruction.StackAlloc, arg0Reg, Const(stackOffset)); Operation allocOp = new Operation(Instruction.StackAlloc, arg0Reg, Const(stackOffset));
@ -584,6 +584,24 @@ namespace ARMeilleure.CodeGen.X86
retArgs = 1; retArgs = 1;
} }
int argsCount = operation.SourcesCount - 1;
int maxArgs = CallingConvention.GetArgumentsOnRegsCount() - retArgs;
if (argsCount > maxArgs)
{
argsCount = maxArgs;
}
Operand[] sources = new Operand[1 + retArgs + argsCount];
sources[0] = operation.GetSource(0);
if (arg0Reg != null)
{
sources[1] = arg0Reg;
}
for (int index = 1; index < operation.SourcesCount; index++) for (int index = 1; index < operation.SourcesCount; index++)
{ {
Operand source = operation.GetSource(index); Operand source = operation.GetSource(index);
@ -602,35 +620,29 @@ namespace ARMeilleure.CodeGen.X86
HandleConstantCopy(nodes.AddBefore(node, storeOp), storeOp); HandleConstantCopy(nodes.AddBefore(node, storeOp), storeOp);
operation.SetSource(index, stackAddr); sources[retArgs + index] = stackAddr;
} }
} }
// Handle arguments passed on registers. // Handle arguments passed on registers.
int argsCount = operation.SourcesCount - 1;
int maxArgs = CallingConvention.GetArgumentsOnRegsCount() - retArgs;
if (argsCount > maxArgs)
{
argsCount = maxArgs;
}
for (int index = 0; index < argsCount; index++) for (int index = 0; index < argsCount; index++)
{ {
Operand source = operation.GetSource(index + 1); Operand source = operation.GetSource(index + 1);
RegisterType regType = source.Type.ToRegisterType(); if (source.Type == OperandType.V128)
{
source = sources[1 + retArgs + index];
}
Operand argReg; Operand argReg;
int argIndex = index + retArgs; int argIndex = index + retArgs;
if (regType == RegisterType.Integer) if (source.Type.IsInteger())
{ {
argReg = Gpr(CallingConvention.GetIntArgumentRegister(argIndex), source.Type); argReg = Gpr(CallingConvention.GetIntArgumentRegister(argIndex), source.Type);
} }
else /* if (regType == RegisterType.Vector) */ else
{ {
argReg = Xmm(CallingConvention.GetVecArgumentRegister(argIndex), source.Type); argReg = Xmm(CallingConvention.GetVecArgumentRegister(argIndex), source.Type);
} }
@ -639,7 +651,7 @@ namespace ARMeilleure.CodeGen.X86
HandleConstantCopy(nodes.AddBefore(node, copyOp), copyOp); HandleConstantCopy(nodes.AddBefore(node, copyOp), copyOp);
operation.SetSource(index + 1, argReg); sources[1 + retArgs + index] = argReg;
} }
// The remaining arguments (those that are not passed on registers) // The remaining arguments (those that are not passed on registers)
@ -653,8 +665,6 @@ namespace ARMeilleure.CodeGen.X86
Operation spillOp = new Operation(Instruction.SpillArg, null, offset, source); Operation spillOp = new Operation(Instruction.SpillArg, null, offset, source);
HandleConstantCopy(nodes.AddBefore(node, spillOp), spillOp); HandleConstantCopy(nodes.AddBefore(node, spillOp), spillOp);
operation.SetSource(index + 1, new Operand(OperandKind.Undefined));
} }
if (dest != null) if (dest != null)
@ -663,8 +673,6 @@ namespace ARMeilleure.CodeGen.X86
{ {
Operand retValueAddr = Local(OperandType.I64); Operand retValueAddr = Local(OperandType.I64);
Operand arg0Reg = Gpr(CallingConvention.GetIntArgumentRegister(0), OperandType.I64);
Operation copyOp = new Operation(Instruction.Copy, retValueAddr, arg0Reg); Operation copyOp = new Operation(Instruction.Copy, retValueAddr, arg0Reg);
nodes.AddBefore(node, copyOp); nodes.AddBefore(node, copyOp);
@ -677,9 +685,7 @@ namespace ARMeilleure.CodeGen.X86
} }
else else
{ {
RegisterType regType = dest.Type.ToRegisterType(); Operand retReg = dest.Type.IsInteger()
Operand retReg = regType == RegisterType.Integer
? Gpr(CallingConvention.GetIntReturnRegister(), dest.Type) ? Gpr(CallingConvention.GetIntReturnRegister(), dest.Type)
: Xmm(CallingConvention.GetVecReturnRegister(), dest.Type); : Xmm(CallingConvention.GetVecReturnRegister(), dest.Type);
@ -691,6 +697,8 @@ namespace ARMeilleure.CodeGen.X86
} }
} }
operation.SetSources(sources);
return node; return node;
} }
@ -700,7 +708,10 @@ namespace ARMeilleure.CodeGen.X86
LinkedList<Node> nodes = node.List; LinkedList<Node> nodes = node.List;
// Handle arguments passed on registers. List<Operand> sources = new List<Operand>();
sources.Add(operation.GetSource(0));
int argsCount = operation.SourcesCount - 1; int argsCount = operation.SourcesCount - 1;
int intMax = CallingConvention.GetIntArgumentsOnRegsCount(); int intMax = CallingConvention.GetIntArgumentsOnRegsCount();
@ -739,8 +750,6 @@ namespace ARMeilleure.CodeGen.X86
nodes.AddBefore(node, new Operation(Instruction.VectorExtract, argReg, source, Const(0))); nodes.AddBefore(node, new Operation(Instruction.VectorExtract, argReg, source, Const(0)));
nodes.AddBefore(node, new Operation(Instruction.VectorExtract, argReg2, source, Const(1))); nodes.AddBefore(node, new Operation(Instruction.VectorExtract, argReg2, source, Const(1)));
operation.SetSource(index + 1, Undef());
continue; continue;
} }
@ -754,7 +763,7 @@ namespace ARMeilleure.CodeGen.X86
HandleConstantCopy(nodes.AddBefore(node, copyOp), copyOp); HandleConstantCopy(nodes.AddBefore(node, copyOp), copyOp);
operation.SetSource(index + 1, argReg); sources.Add(argReg);
} }
else else
{ {
@ -765,8 +774,6 @@ namespace ARMeilleure.CodeGen.X86
HandleConstantCopy(nodes.AddBefore(node, spillOp), spillOp); HandleConstantCopy(nodes.AddBefore(node, spillOp), spillOp);
stackOffset += source.Type.GetSizeInBytes(); stackOffset += source.Type.GetSizeInBytes();
operation.SetSource(index + 1, Undef());
} }
} }
@ -784,9 +791,7 @@ namespace ARMeilleure.CodeGen.X86
} }
else else
{ {
RegisterType regType = dest.Type.ToRegisterType(); Operand retReg = dest.Type.IsInteger()
Operand retReg = regType == RegisterType.Integer
? Gpr(CallingConvention.GetIntReturnRegister(), dest.Type) ? Gpr(CallingConvention.GetIntReturnRegister(), dest.Type)
: Xmm(CallingConvention.GetVecReturnRegister(), dest.Type); : Xmm(CallingConvention.GetVecReturnRegister(), dest.Type);
@ -798,6 +803,8 @@ namespace ARMeilleure.CodeGen.X86
} }
} }
operation.SetSources(sources.ToArray());
return node; return node;
} }

View file

@ -76,21 +76,4 @@ namespace ARMeilleure.IntermediateRepresentation
SpillArg, SpillArg,
StoreToContext StoreToContext
} }
static class InstructionExtensions
{
public static bool IsShift(this Instruction inst)
{
switch (inst)
{
case Instruction.RotateRight:
case Instruction.ShiftLeft:
case Instruction.ShiftRightSI:
case Instruction.ShiftRightUI:
return true;
}
return false;
}
}
} }

View file

@ -4,63 +4,129 @@ namespace ARMeilleure.IntermediateRepresentation
{ {
class Node class Node
{ {
private Operand _dest;
private LinkedListNode<Node> _asgUseNode;
public Operand Dest public Operand Dest
{ {
get get
{ {
return _dest; return _destinations.Length != 0 ? GetDestination(0) : null;
} }
set set
{ {
if (_dest != null && _dest.Kind == OperandKind.LocalVariable) if (value != null)
{ {
_dest.Assignments.Remove(_asgUseNode); SetDestinations(new Operand[] { value });
} }
else
if (value != null && value.Kind == OperandKind.LocalVariable)
{ {
_asgUseNode = value.Assignments.AddLast(this); SetDestinations(new Operand[0]);
} }
_dest = value;
} }
} }
protected Operand[] Sources; private Operand[] _destinations;
private Operand[] _sources;
public int SourcesCount => Sources.Length; private LinkedListNode<Node>[] _asgUseNodes;
private LinkedListNode<Node>[] _srcUseNodes;
protected LinkedListNode<Node>[] SrcUseNodes; public int DestinationsCount => _destinations.Length;
public int SourcesCount => _sources.Length;
public Node(int sourcesCount) public Node(Operand destination, int sourcesCount)
{ {
SrcUseNodes = new LinkedListNode<Node>[sourcesCount]; Dest = destination;
_sources = new Operand[sourcesCount];
_srcUseNodes = new LinkedListNode<Node>[sourcesCount];
}
public Node(Operand[] destinations, int sourcesCount)
{
SetDestinations(destinations);
_sources = new Operand[sourcesCount];
_srcUseNodes = new LinkedListNode<Node>[sourcesCount];
}
public Operand GetDestination(int index)
{
return _destinations[index];
} }
public Operand GetSource(int index) public Operand GetSource(int index)
{ {
return Sources[index]; return _sources[index];
}
public void SetDestination(int index, Operand destination)
{
Set(_destinations, _asgUseNodes, index, destination);
} }
public void SetSource(int index, Operand source) public void SetSource(int index, Operand source)
{ {
Operand oldSrc = Sources[index]; Set(_sources, _srcUseNodes, index, source);
}
if (oldSrc != null && oldSrc.Kind == OperandKind.LocalVariable) private void Set(Operand[] ops, LinkedListNode<Node>[] uses, int index, Operand newOp)
{
Operand oldOp = ops[index];
if (oldOp != null && oldOp.Kind == OperandKind.LocalVariable)
{ {
oldSrc.Uses.Remove(SrcUseNodes[index]); oldOp.Uses.Remove(uses[index]);
} }
if (source != null && source.Kind == OperandKind.LocalVariable) if (newOp != null && newOp.Kind == OperandKind.LocalVariable)
{ {
SrcUseNodes[index] = source.Uses.AddLast(this); uses[index] = newOp.Uses.AddLast(this);
} }
Sources[index] = source; ops[index] = newOp;
}
public void SetDestinations(Operand[] destinations)
{
Set(ref _destinations, ref _asgUseNodes, destinations);
}
public void SetSources(Operand[] sources)
{
Set(ref _sources, ref _srcUseNodes, sources);
}
private void Set(ref Operand[] ops, ref LinkedListNode<Node>[] uses, Operand[] newOps)
{
if (ops != null)
{
for (int index = 0; index < ops.Length; index++)
{
Operand oldOp = ops[index];
if (oldOp != null && oldOp.Kind == OperandKind.LocalVariable)
{
oldOp.Uses.Remove(uses[index]);
}
}
}
ops = new Operand[newOps.Length];
uses = new LinkedListNode<Node>[newOps.Length];
for (int index = 0; index < newOps.Length; index++)
{
Operand newOp = newOps[index];
ops[index] = newOp;
if (newOp.Kind == OperandKind.LocalVariable)
{
uses[index] = newOp.Uses.AddLast(this);
}
}
} }
} }
} }

View file

@ -6,22 +6,29 @@ namespace ARMeilleure.IntermediateRepresentation
{ {
public Instruction Inst { get; private set; } public Instruction Inst { get; private set; }
public Operation(Instruction inst, Operand dest, params Operand[] sources) : base(sources.Length) public Operation(
Instruction inst,
Operand destination,
params Operand[] sources) : base(destination, sources.Length)
{ {
Inst = inst; Inst = inst;
Dest = dest;
//The array may be modified externally, so we store a copy. for (int index = 0; index < sources.Length; index++)
Sources = (Operand[])sources.Clone();
for (int index = 0; index < Sources.Length; index++)
{ {
Operand source = Sources[index]; SetSource(index, sources[index]);
}
}
if (source.Kind == OperandKind.LocalVariable) public Operation(
{ Instruction inst,
SrcUseNodes[index] = source.Uses.AddLast(this); Operand[] destinations,
} Operand[] sources) : base(destinations, sources.Length)
{
Inst = inst;
for (int index = 0; index < sources.Length; index++)
{
SetSource(index, sources[index]);
} }
} }
@ -29,24 +36,7 @@ namespace ARMeilleure.IntermediateRepresentation
{ {
Inst = Instruction.Copy; Inst = Instruction.Copy;
for (int index = 0; index < Sources.Length; index++) SetSources(new Operand[] { source });
{
if (Sources[index].Kind != OperandKind.LocalVariable)
{
continue;
}
Sources[index].Uses.Remove(SrcUseNodes[index]);
}
Sources = new Operand[] { source };
SrcUseNodes = new LinkedListNode<Node>[1];
if (source.Kind == OperandKind.LocalVariable)
{
SrcUseNodes[0] = source.Uses.AddLast(this);
}
} }
} }
} }

View file

@ -4,13 +4,9 @@ namespace ARMeilleure.IntermediateRepresentation
{ {
private BasicBlock[] _blocks; private BasicBlock[] _blocks;
public PhiNode(Operand dest, int predecessorsCount) : base(predecessorsCount) public PhiNode(Operand destination, int predecessorsCount) : base(destination, predecessorsCount)
{ {
Sources = new Operand[predecessorsCount];
_blocks = new BasicBlock[predecessorsCount]; _blocks = new BasicBlock[predecessorsCount];
Dest = dest;
} }
public BasicBlock GetBlock(int index) public BasicBlock GetBlock(int index)

View file

@ -3,6 +3,7 @@ using ARMeilleure.Instructions;
using ARMeilleure.IntermediateRepresentation; using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Memory; using ARMeilleure.Memory;
using ARMeilleure.State; using ARMeilleure.State;
using System.Collections.Generic;
using static ARMeilleure.IntermediateRepresentation.OperandHelper; using static ARMeilleure.IntermediateRepresentation.OperandHelper;
@ -10,6 +11,8 @@ namespace ARMeilleure.Translation
{ {
class ArmEmitterContext : EmitterContext class ArmEmitterContext : EmitterContext
{ {
private Dictionary<ulong, Operand> _labels;
private OpCode _optOpLastCompare; private OpCode _optOpLastCompare;
private OpCode _optOpLastFlagSet; private OpCode _optOpLastFlagSet;
@ -42,6 +45,20 @@ namespace ARMeilleure.Translation
{ {
Memory = memory; Memory = memory;
Mode = mode; Mode = mode;
_labels = new Dictionary<ulong, Operand>();
}
public Operand GetLabel(ulong address)
{
if (!_labels.TryGetValue(address, out Operand label))
{
label = Label();
_labels.Add(address, label);
}
return label;
} }
public void MarkComparison(Operand n, Operand m) public void MarkComparison(Operand n, Operand m)

View file

@ -10,8 +10,6 @@ namespace ARMeilleure.Translation
{ {
class EmitterContext class EmitterContext
{ {
private Dictionary<ulong, Operand> _labels;
private Dictionary<Operand, BasicBlock> _irLabels; private Dictionary<Operand, BasicBlock> _irLabels;
private LinkedList<BasicBlock> _irBlocks; private LinkedList<BasicBlock> _irBlocks;
@ -22,8 +20,6 @@ namespace ARMeilleure.Translation
public EmitterContext() public EmitterContext()
{ {
_labels = new Dictionary<ulong, Operand>();
_irLabels = new Dictionary<Operand, BasicBlock>(); _irLabels = new Dictionary<Operand, BasicBlock>();
_irBlocks = new LinkedList<BasicBlock>(); _irBlocks = new LinkedList<BasicBlock>();
@ -94,37 +90,34 @@ namespace ARMeilleure.Translation
return Call(Const(ptr.ToInt64()), returnType, callArgs); return Call(Const(ptr.ToInt64()), returnType, callArgs);
} }
private static Dictionary<TypeCode, OperandType> _typeCodeToOperandTypeMap =
new Dictionary<TypeCode, OperandType>()
{
{ TypeCode.Boolean, OperandType.I32 },
{ TypeCode.Byte, OperandType.I32 },
{ TypeCode.Char, OperandType.I32 },
{ TypeCode.Double, OperandType.FP64 },
{ TypeCode.Int16, OperandType.I32 },
{ TypeCode.Int32, OperandType.I32 },
{ TypeCode.Int64, OperandType.I64 },
{ TypeCode.SByte, OperandType.I32 },
{ TypeCode.Single, OperandType.FP32 },
{ TypeCode.UInt16, OperandType.I32 },
{ TypeCode.UInt32, OperandType.I32 },
{ TypeCode.UInt64, OperandType.I64 }
};
private static OperandType GetOperandType(Type type) private static OperandType GetOperandType(Type type)
{ {
switch (Type.GetTypeCode(type)) if (_typeCodeToOperandTypeMap.TryGetValue(Type.GetTypeCode(type), out OperandType ot))
{ {
case TypeCode.Boolean: return ot;
case TypeCode.Char:
case TypeCode.Byte:
case TypeCode.SByte:
case TypeCode.UInt16:
case TypeCode.Int16:
case TypeCode.UInt32:
case TypeCode.Int32:
return OperandType.I32;
case TypeCode.UInt64:
case TypeCode.Int64:
return OperandType.I64;
case TypeCode.Single:
return OperandType.FP32;
case TypeCode.Double:
return OperandType.FP64;
} }
else if (type == typeof(V128))
if (type == typeof(V128))
{ {
return OperandType.V128; return OperandType.V128;
} }
else if (type == typeof(void))
if (type == typeof(void))
{ {
return OperandType.None; return OperandType.None;
} }
@ -527,18 +520,6 @@ namespace ARMeilleure.Translation
} }
} }
public Operand GetLabel(ulong address)
{
if (!_labels.TryGetValue(address, out Operand label))
{
label = Label();
_labels.Add(address, label);
}
return label;
}
private void NewNextBlock() private void NewNextBlock()
{ {
BasicBlock block = new BasicBlock(_irBlocks.Count); BasicBlock block = new BasicBlock(_irBlocks.Count);