aboutsummaryrefslogtreecommitdiff
path: root/ARMeilleure/IntermediateRepresentation
diff options
context:
space:
mode:
Diffstat (limited to 'ARMeilleure/IntermediateRepresentation')
-rw-r--r--ARMeilleure/IntermediateRepresentation/BasicBlock.cs83
-rw-r--r--ARMeilleure/IntermediateRepresentation/Instruction.cs79
-rw-r--r--ARMeilleure/IntermediateRepresentation/Intrinsic.cs138
-rw-r--r--ARMeilleure/IntermediateRepresentation/IntrinsicOperation.cs12
-rw-r--r--ARMeilleure/IntermediateRepresentation/MemoryOperand.cs25
-rw-r--r--ARMeilleure/IntermediateRepresentation/Multiplier.cs10
-rw-r--r--ARMeilleure/IntermediateRepresentation/Node.cs163
-rw-r--r--ARMeilleure/IntermediateRepresentation/Operand.cs124
-rw-r--r--ARMeilleure/IntermediateRepresentation/OperandHelper.cs68
-rw-r--r--ARMeilleure/IntermediateRepresentation/OperandKind.cs12
-rw-r--r--ARMeilleure/IntermediateRepresentation/OperandType.cs51
-rw-r--r--ARMeilleure/IntermediateRepresentation/Operation.cs40
-rw-r--r--ARMeilleure/IntermediateRepresentation/PhiNode.cs22
-rw-r--r--ARMeilleure/IntermediateRepresentation/Register.cs43
-rw-r--r--ARMeilleure/IntermediateRepresentation/RegisterType.cs9
15 files changed, 879 insertions, 0 deletions
diff --git a/ARMeilleure/IntermediateRepresentation/BasicBlock.cs b/ARMeilleure/IntermediateRepresentation/BasicBlock.cs
new file mode 100644
index 00000000..06839f30
--- /dev/null
+++ b/ARMeilleure/IntermediateRepresentation/BasicBlock.cs
@@ -0,0 +1,83 @@
+using System.Collections.Generic;
+
+namespace ARMeilleure.IntermediateRepresentation
+{
+ class BasicBlock
+ {
+ public int Index { get; set; }
+
+ public LinkedListNode<BasicBlock> Node { get; set; }
+
+ public LinkedList<Node> Operations { get; }
+
+ private BasicBlock _next;
+ private BasicBlock _branch;
+
+ public BasicBlock Next
+ {
+ get => _next;
+ set => _next = AddSuccessor(_next, value);
+ }
+
+ public BasicBlock Branch
+ {
+ get => _branch;
+ set => _branch = AddSuccessor(_branch, value);
+ }
+
+ public List<BasicBlock> Predecessors { get; }
+
+ public HashSet<BasicBlock> DominanceFrontiers { get; }
+
+ public BasicBlock ImmediateDominator { get; set; }
+
+ public BasicBlock()
+ {
+ Operations = new LinkedList<Node>();
+
+ Predecessors = new List<BasicBlock>();
+
+ DominanceFrontiers = new HashSet<BasicBlock>();
+
+ Index = -1;
+ }
+
+ public BasicBlock(int index) : this()
+ {
+ Index = index;
+ }
+
+ private BasicBlock AddSuccessor(BasicBlock oldBlock, BasicBlock newBlock)
+ {
+ oldBlock?.Predecessors.Remove(this);
+ newBlock?.Predecessors.Add(this);
+
+ return newBlock;
+ }
+
+ public void Append(Node node)
+ {
+ // If the branch block is not null, then the list of operations
+ // should end with a branch instruction. We insert the new operation
+ // before this branch.
+ if (_branch != null || (Operations.Last != null && IsLeafBlock()))
+ {
+ Operations.AddBefore(Operations.Last, node);
+ }
+ else
+ {
+ Operations.AddLast(node);
+ }
+ }
+
+ private bool IsLeafBlock()
+ {
+ return _branch == null && _next == null;
+ }
+
+ public Node GetLastOp()
+ {
+ return Operations.Last?.Value;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/IntermediateRepresentation/Instruction.cs b/ARMeilleure/IntermediateRepresentation/Instruction.cs
new file mode 100644
index 00000000..4c4ecb8f
--- /dev/null
+++ b/ARMeilleure/IntermediateRepresentation/Instruction.cs
@@ -0,0 +1,79 @@
+namespace ARMeilleure.IntermediateRepresentation
+{
+ enum Instruction
+ {
+ Add,
+ BitwiseAnd,
+ BitwiseExclusiveOr,
+ BitwiseNot,
+ BitwiseOr,
+ Branch,
+ BranchIfFalse,
+ BranchIfTrue,
+ ByteSwap,
+ Call,
+ CompareAndSwap128,
+ CompareEqual,
+ CompareGreater,
+ CompareGreaterOrEqual,
+ CompareGreaterOrEqualUI,
+ CompareGreaterUI,
+ CompareLess,
+ CompareLessOrEqual,
+ CompareLessOrEqualUI,
+ CompareLessUI,
+ CompareNotEqual,
+ ConditionalSelect,
+ ConvertI64ToI32,
+ ConvertToFP,
+ ConvertToFPUI,
+ Copy,
+ CountLeadingZeros,
+ Divide,
+ DivideUI,
+ Load,
+ Load16,
+ Load8,
+ LoadArgument,
+ Multiply,
+ Multiply64HighSI,
+ Multiply64HighUI,
+ Negate,
+ Return,
+ RotateRight,
+ ShiftLeft,
+ ShiftRightSI,
+ ShiftRightUI,
+ SignExtend16,
+ SignExtend32,
+ SignExtend8,
+ StackAlloc,
+ Store,
+ Store16,
+ Store8,
+ Subtract,
+ VectorCreateScalar,
+ VectorExtract,
+ VectorExtract16,
+ VectorExtract8,
+ VectorInsert,
+ VectorInsert16,
+ VectorInsert8,
+ VectorOne,
+ VectorZero,
+ VectorZeroUpper64,
+ VectorZeroUpper96,
+ ZeroExtend16,
+ ZeroExtend32,
+ ZeroExtend8,
+
+ Clobber,
+ CpuId,
+ Extended,
+ Fill,
+ LoadFromContext,
+ Spill,
+ SpillArg,
+ StoreToContext
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/IntermediateRepresentation/Intrinsic.cs b/ARMeilleure/IntermediateRepresentation/Intrinsic.cs
new file mode 100644
index 00000000..1fe29e85
--- /dev/null
+++ b/ARMeilleure/IntermediateRepresentation/Intrinsic.cs
@@ -0,0 +1,138 @@
+namespace ARMeilleure.IntermediateRepresentation
+{
+ enum Intrinsic
+ {
+ X86Addpd,
+ X86Addps,
+ X86Addsd,
+ X86Addss,
+ X86Andnpd,
+ X86Andnps,
+ X86Cmppd,
+ X86Cmpps,
+ X86Cmpsd,
+ X86Cmpss,
+ X86Comisdeq,
+ X86Comisdge,
+ X86Comisdlt,
+ X86Comisseq,
+ X86Comissge,
+ X86Comisslt,
+ X86Cvtdq2pd,
+ X86Cvtdq2ps,
+ X86Cvtpd2dq,
+ X86Cvtpd2ps,
+ X86Cvtps2dq,
+ X86Cvtps2pd,
+ X86Cvtsd2si,
+ X86Cvtsd2ss,
+ X86Cvtss2sd,
+ X86Divpd,
+ X86Divps,
+ X86Divsd,
+ X86Divss,
+ X86Haddpd,
+ X86Haddps,
+ X86Maxpd,
+ X86Maxps,
+ X86Maxsd,
+ X86Maxss,
+ X86Minpd,
+ X86Minps,
+ X86Minsd,
+ X86Minss,
+ X86Movhlps,
+ X86Movlhps,
+ X86Mulpd,
+ X86Mulps,
+ X86Mulsd,
+ X86Mulss,
+ X86Paddb,
+ X86Paddd,
+ X86Paddq,
+ X86Paddw,
+ X86Pand,
+ X86Pandn,
+ X86Pavgb,
+ X86Pavgw,
+ X86Pblendvb,
+ X86Pcmpeqb,
+ X86Pcmpeqd,
+ X86Pcmpeqq,
+ X86Pcmpeqw,
+ X86Pcmpgtb,
+ X86Pcmpgtd,
+ X86Pcmpgtq,
+ X86Pcmpgtw,
+ X86Pmaxsb,
+ X86Pmaxsd,
+ X86Pmaxsw,
+ X86Pmaxub,
+ X86Pmaxud,
+ X86Pmaxuw,
+ X86Pminsb,
+ X86Pminsd,
+ X86Pminsw,
+ X86Pminub,
+ X86Pminud,
+ X86Pminuw,
+ X86Pmovsxbw,
+ X86Pmovsxdq,
+ X86Pmovsxwd,
+ X86Pmovzxbw,
+ X86Pmovzxdq,
+ X86Pmovzxwd,
+ X86Pmulld,
+ X86Pmullw,
+ X86Popcnt,
+ X86Por,
+ X86Pshufb,
+ X86Pslld,
+ X86Pslldq,
+ X86Psllq,
+ X86Psllw,
+ X86Psrad,
+ X86Psraw,
+ X86Psrld,
+ X86Psrlq,
+ X86Psrldq,
+ X86Psrlw,
+ X86Psubb,
+ X86Psubd,
+ X86Psubq,
+ X86Psubw,
+ X86Punpckhbw,
+ X86Punpckhdq,
+ X86Punpckhqdq,
+ X86Punpckhwd,
+ X86Punpcklbw,
+ X86Punpckldq,
+ X86Punpcklqdq,
+ X86Punpcklwd,
+ X86Pxor,
+ X86Rcpps,
+ X86Rcpss,
+ X86Roundpd,
+ X86Roundps,
+ X86Roundsd,
+ X86Roundss,
+ X86Rsqrtps,
+ X86Rsqrtss,
+ X86Shufpd,
+ X86Shufps,
+ X86Sqrtpd,
+ X86Sqrtps,
+ X86Sqrtsd,
+ X86Sqrtss,
+ X86Subpd,
+ X86Subps,
+ X86Subsd,
+ X86Subss,
+ X86Unpckhpd,
+ X86Unpckhps,
+ X86Unpcklpd,
+ X86Unpcklps,
+ X86Xorpd,
+ X86Xorps
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/IntermediateRepresentation/IntrinsicOperation.cs b/ARMeilleure/IntermediateRepresentation/IntrinsicOperation.cs
new file mode 100644
index 00000000..34781b70
--- /dev/null
+++ b/ARMeilleure/IntermediateRepresentation/IntrinsicOperation.cs
@@ -0,0 +1,12 @@
+namespace ARMeilleure.IntermediateRepresentation
+{
+ class IntrinsicOperation : Operation
+ {
+ public Intrinsic Intrinsic { get; }
+
+ public IntrinsicOperation(Intrinsic intrin, Operand dest, params Operand[] sources) : base(Instruction.Extended, dest, sources)
+ {
+ Intrinsic = intrin;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/IntermediateRepresentation/MemoryOperand.cs b/ARMeilleure/IntermediateRepresentation/MemoryOperand.cs
new file mode 100644
index 00000000..742842fa
--- /dev/null
+++ b/ARMeilleure/IntermediateRepresentation/MemoryOperand.cs
@@ -0,0 +1,25 @@
+namespace ARMeilleure.IntermediateRepresentation
+{
+ class MemoryOperand : Operand
+ {
+ public Operand BaseAddress { get; set; }
+ public Operand Index { get; set; }
+
+ public Multiplier Scale { get; }
+
+ public int Displacement { get; }
+
+ public MemoryOperand(
+ OperandType type,
+ Operand baseAddress,
+ Operand index = null,
+ Multiplier scale = Multiplier.x1,
+ int displacement = 0) : base(OperandKind.Memory, type)
+ {
+ BaseAddress = baseAddress;
+ Index = index;
+ Scale = scale;
+ Displacement = displacement;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/IntermediateRepresentation/Multiplier.cs b/ARMeilleure/IntermediateRepresentation/Multiplier.cs
new file mode 100644
index 00000000..23582072
--- /dev/null
+++ b/ARMeilleure/IntermediateRepresentation/Multiplier.cs
@@ -0,0 +1,10 @@
+namespace ARMeilleure.IntermediateRepresentation
+{
+ enum Multiplier
+ {
+ x1 = 0,
+ x2 = 1,
+ x4 = 2,
+ x8 = 3
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/IntermediateRepresentation/Node.cs b/ARMeilleure/IntermediateRepresentation/Node.cs
new file mode 100644
index 00000000..167acd07
--- /dev/null
+++ b/ARMeilleure/IntermediateRepresentation/Node.cs
@@ -0,0 +1,163 @@
+using System;
+using System.Collections.Generic;
+
+namespace ARMeilleure.IntermediateRepresentation
+{
+ class Node
+ {
+ public Operand Destination
+ {
+ get
+ {
+ return _destinations.Length != 0 ? GetDestination(0) : null;
+ }
+ set
+ {
+ if (value != null)
+ {
+ SetDestinations(new Operand[] { value });
+ }
+ else
+ {
+ SetDestinations(new Operand[0]);
+ }
+ }
+ }
+
+ private Operand[] _destinations;
+ private Operand[] _sources;
+
+ private LinkedListNode<Node>[] _asgUseNodes;
+ private LinkedListNode<Node>[] _srcUseNodes;
+
+ public int DestinationsCount => _destinations.Length;
+ public int SourcesCount => _sources.Length;
+
+ public Node(Operand destination, int sourcesCount)
+ {
+ Destination = destination;
+
+ _sources = new Operand[sourcesCount];
+
+ _srcUseNodes = new LinkedListNode<Node>[sourcesCount];
+ }
+
+ public Node(Operand[] destinations, int sourcesCount)
+ {
+ SetDestinations(destinations ?? throw new ArgumentNullException(nameof(destinations)));
+
+ _sources = new Operand[sourcesCount];
+
+ _srcUseNodes = new LinkedListNode<Node>[sourcesCount];
+ }
+
+ public Operand GetDestination(int index)
+ {
+ return _destinations[index];
+ }
+
+ public Operand GetSource(int index)
+ {
+ return _sources[index];
+ }
+
+ public void SetDestination(int index, Operand destination)
+ {
+ Operand oldOp = _destinations[index];
+
+ if (oldOp != null && oldOp.Kind == OperandKind.LocalVariable)
+ {
+ oldOp.Assignments.Remove(_asgUseNodes[index]);
+ }
+
+ if (destination != null && destination.Kind == OperandKind.LocalVariable)
+ {
+ _asgUseNodes[index] = destination.Assignments.AddLast(this);
+ }
+
+ _destinations[index] = destination;
+ }
+
+ public void SetSource(int index, Operand source)
+ {
+ Operand oldOp = _sources[index];
+
+ if (oldOp != null && oldOp.Kind == OperandKind.LocalVariable)
+ {
+ oldOp.Uses.Remove(_srcUseNodes[index]);
+ }
+
+ if (source != null && source.Kind == OperandKind.LocalVariable)
+ {
+ _srcUseNodes[index] = source.Uses.AddLast(this);
+ }
+
+ _sources[index] = source;
+ }
+
+ public void SetDestinations(Operand[] destinations)
+ {
+ if (_destinations != null)
+ {
+ for (int index = 0; index < _destinations.Length; index++)
+ {
+ Operand oldOp = _destinations[index];
+
+ if (oldOp != null && oldOp.Kind == OperandKind.LocalVariable)
+ {
+ oldOp.Assignments.Remove(_asgUseNodes[index]);
+ }
+ }
+
+ _destinations = destinations;
+ }
+ else
+ {
+ _destinations = new Operand[destinations.Length];
+ }
+
+ _asgUseNodes = new LinkedListNode<Node>[destinations.Length];
+
+ for (int index = 0; index < destinations.Length; index++)
+ {
+ Operand newOp = destinations[index];
+
+ _destinations[index] = newOp;
+
+ if (newOp.Kind == OperandKind.LocalVariable)
+ {
+ _asgUseNodes[index] = newOp.Assignments.AddLast(this);
+ }
+ }
+ }
+
+ public void SetSources(Operand[] sources)
+ {
+ for (int index = 0; index < _sources.Length; index++)
+ {
+ Operand oldOp = _sources[index];
+
+ if (oldOp != null && oldOp.Kind == OperandKind.LocalVariable)
+ {
+ oldOp.Uses.Remove(_srcUseNodes[index]);
+ }
+ }
+
+ _sources = new Operand[sources.Length];
+
+ _srcUseNodes = new LinkedListNode<Node>[sources.Length];
+
+ for (int index = 0; index < sources.Length; index++)
+ {
+ Operand newOp = sources[index];
+
+ _sources[index] = newOp;
+
+ if (newOp.Kind == OperandKind.LocalVariable)
+ {
+ _srcUseNodes[index] = newOp.Uses.AddLast(this);
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/IntermediateRepresentation/Operand.cs b/ARMeilleure/IntermediateRepresentation/Operand.cs
new file mode 100644
index 00000000..2df6256f
--- /dev/null
+++ b/ARMeilleure/IntermediateRepresentation/Operand.cs
@@ -0,0 +1,124 @@
+using System;
+using System.Collections.Generic;
+
+namespace ARMeilleure.IntermediateRepresentation
+{
+ class Operand
+ {
+ public OperandKind Kind { get; }
+
+ public OperandType Type { get; }
+
+ public ulong Value { get; private set; }
+
+ public LinkedList<Node> Assignments { get; }
+ public LinkedList<Node> Uses { get; }
+
+ private Operand()
+ {
+ Assignments = new LinkedList<Node>();
+ Uses = new LinkedList<Node>();
+ }
+
+ public Operand(OperandKind kind, OperandType type = OperandType.None) : this()
+ {
+ Kind = kind;
+ Type = type;
+ }
+
+ public Operand(int value) : this(OperandKind.Constant, OperandType.I32)
+ {
+ Value = (uint)value;
+ }
+
+ public Operand(uint value) : this(OperandKind.Constant, OperandType.I32)
+ {
+ Value = (uint)value;
+ }
+
+ public Operand(long value) : this(OperandKind.Constant, OperandType.I64)
+ {
+ Value = (ulong)value;
+ }
+
+ public Operand(ulong value) : this(OperandKind.Constant, OperandType.I64)
+ {
+ Value = value;
+ }
+
+ public Operand(float value) : this(OperandKind.Constant, OperandType.FP32)
+ {
+ Value = (ulong)BitConverter.SingleToInt32Bits(value);
+ }
+
+ public Operand(double value) : this(OperandKind.Constant, OperandType.FP64)
+ {
+ Value = (ulong)BitConverter.DoubleToInt64Bits(value);
+ }
+
+ public Operand(int index, RegisterType regType, OperandType type) : this()
+ {
+ Kind = OperandKind.Register;
+ Type = type;
+
+ Value = (ulong)((int)regType << 24 | index);
+ }
+
+ public Register GetRegister()
+ {
+ return new Register((int)Value & 0xffffff, (RegisterType)(Value >> 24));
+ }
+
+ public byte AsByte()
+ {
+ return (byte)Value;
+ }
+
+ public short AsInt16()
+ {
+ return (short)Value;
+ }
+
+ public int AsInt32()
+ {
+ return (int)Value;
+ }
+
+ public long AsInt64()
+ {
+ return (long)Value;
+ }
+
+ public float AsFloat()
+ {
+ return BitConverter.Int32BitsToSingle((int)Value);
+ }
+
+ public double AsDouble()
+ {
+ return BitConverter.Int64BitsToDouble((long)Value);
+ }
+
+ internal void NumberLocal(int number)
+ {
+ if (Kind != OperandKind.LocalVariable)
+ {
+ throw new InvalidOperationException("The operand is not a local variable.");
+ }
+
+ Value = (ulong)number;
+ }
+
+ public override int GetHashCode()
+ {
+ if (Kind == OperandKind.LocalVariable)
+ {
+ return base.GetHashCode();
+ }
+ else
+ {
+ return (int)Value ^ ((int)Kind << 16) ^ ((int)Type << 20);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/IntermediateRepresentation/OperandHelper.cs b/ARMeilleure/IntermediateRepresentation/OperandHelper.cs
new file mode 100644
index 00000000..4a930e03
--- /dev/null
+++ b/ARMeilleure/IntermediateRepresentation/OperandHelper.cs
@@ -0,0 +1,68 @@
+using ARMeilleure.State;
+using System;
+
+namespace ARMeilleure.IntermediateRepresentation
+{
+ static class OperandHelper
+ {
+ public static Operand Const(OperandType type, long value)
+ {
+ return type == OperandType.I32 ? new Operand((int)value) : new Operand(value);
+ }
+
+ public static Operand Const(bool value)
+ {
+ return new Operand(value ? 1 : 0);
+ }
+
+ public static Operand Const(int value)
+ {
+ return new Operand(value);
+ }
+
+ public static Operand Const(uint value)
+ {
+ return new Operand(value);
+ }
+
+ public static Operand Const(long value)
+ {
+ return new Operand(value);
+ }
+
+ public static Operand Const(ulong value)
+ {
+ return new Operand(value);
+ }
+
+ public static Operand ConstF(float value)
+ {
+ return new Operand(value);
+ }
+
+ public static Operand ConstF(double value)
+ {
+ return new Operand(value);
+ }
+
+ public static Operand Label()
+ {
+ return new Operand(OperandKind.Label);
+ }
+
+ public static Operand Local(OperandType type)
+ {
+ return new Operand(OperandKind.LocalVariable, type);
+ }
+
+ public static Operand Register(int index, RegisterType regType, OperandType type)
+ {
+ return new Operand(index, regType, type);
+ }
+
+ public static Operand Undef()
+ {
+ return new Operand(OperandKind.Undefined);
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/IntermediateRepresentation/OperandKind.cs b/ARMeilleure/IntermediateRepresentation/OperandKind.cs
new file mode 100644
index 00000000..57618353
--- /dev/null
+++ b/ARMeilleure/IntermediateRepresentation/OperandKind.cs
@@ -0,0 +1,12 @@
+namespace ARMeilleure.IntermediateRepresentation
+{
+ enum OperandKind
+ {
+ Constant,
+ Label,
+ LocalVariable,
+ Memory,
+ Register,
+ Undefined
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/IntermediateRepresentation/OperandType.cs b/ARMeilleure/IntermediateRepresentation/OperandType.cs
new file mode 100644
index 00000000..bfdf5130
--- /dev/null
+++ b/ARMeilleure/IntermediateRepresentation/OperandType.cs
@@ -0,0 +1,51 @@
+using System;
+
+namespace ARMeilleure.IntermediateRepresentation
+{
+ enum OperandType
+ {
+ None,
+ I32,
+ I64,
+ FP32,
+ FP64,
+ V128
+ }
+
+ static class OperandTypeExtensions
+ {
+ public static bool IsInteger(this OperandType type)
+ {
+ return type == OperandType.I32 ||
+ type == OperandType.I64;
+ }
+
+ public static RegisterType ToRegisterType(this OperandType type)
+ {
+ switch (type)
+ {
+ case OperandType.FP32: return RegisterType.Vector;
+ case OperandType.FP64: return RegisterType.Vector;
+ case OperandType.I32: return RegisterType.Integer;
+ case OperandType.I64: return RegisterType.Integer;
+ case OperandType.V128: return RegisterType.Vector;
+ }
+
+ throw new InvalidOperationException($"Invalid operand type \"{type}\".");
+ }
+
+ public static int GetSizeInBytes(this OperandType type)
+ {
+ switch (type)
+ {
+ case OperandType.FP32: return 4;
+ case OperandType.FP64: return 8;
+ case OperandType.I32: return 4;
+ case OperandType.I64: return 8;
+ case OperandType.V128: return 16;
+ }
+
+ throw new InvalidOperationException($"Invalid operand type \"{type}\".");
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/IntermediateRepresentation/Operation.cs b/ARMeilleure/IntermediateRepresentation/Operation.cs
new file mode 100644
index 00000000..620bf3f6
--- /dev/null
+++ b/ARMeilleure/IntermediateRepresentation/Operation.cs
@@ -0,0 +1,40 @@
+namespace ARMeilleure.IntermediateRepresentation
+{
+ class Operation : Node
+ {
+ public Instruction Instruction { get; private set; }
+
+ public Operation(
+ Instruction instruction,
+ Operand destination,
+ params Operand[] sources) : base(destination, sources.Length)
+ {
+ Instruction = instruction;
+
+ for (int index = 0; index < sources.Length; index++)
+ {
+ SetSource(index, sources[index]);
+ }
+ }
+
+ public Operation(
+ Instruction instruction,
+ Operand[] destinations,
+ Operand[] sources) : base(destinations, sources.Length)
+ {
+ Instruction = instruction;
+
+ for (int index = 0; index < sources.Length; index++)
+ {
+ SetSource(index, sources[index]);
+ }
+ }
+
+ public void TurnIntoCopy(Operand source)
+ {
+ Instruction = Instruction.Copy;
+
+ SetSources(new Operand[] { source });
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/IntermediateRepresentation/PhiNode.cs b/ARMeilleure/IntermediateRepresentation/PhiNode.cs
new file mode 100644
index 00000000..30fc4d38
--- /dev/null
+++ b/ARMeilleure/IntermediateRepresentation/PhiNode.cs
@@ -0,0 +1,22 @@
+namespace ARMeilleure.IntermediateRepresentation
+{
+ class PhiNode : Node
+ {
+ private BasicBlock[] _blocks;
+
+ public PhiNode(Operand destination, int predecessorsCount) : base(destination, predecessorsCount)
+ {
+ _blocks = new BasicBlock[predecessorsCount];
+ }
+
+ public BasicBlock GetBlock(int index)
+ {
+ return _blocks[index];
+ }
+
+ public void SetBlock(int index, BasicBlock block)
+ {
+ _blocks[index] = block;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/IntermediateRepresentation/Register.cs b/ARMeilleure/IntermediateRepresentation/Register.cs
new file mode 100644
index 00000000..745b3153
--- /dev/null
+++ b/ARMeilleure/IntermediateRepresentation/Register.cs
@@ -0,0 +1,43 @@
+using System;
+
+namespace ARMeilleure.IntermediateRepresentation
+{
+ struct Register : IEquatable<Register>
+ {
+ public int Index { get; }
+
+ public RegisterType Type { get; }
+
+ public Register(int index, RegisterType type)
+ {
+ Index = index;
+ Type = type;
+ }
+
+ public override int GetHashCode()
+ {
+ return (ushort)Index | ((int)Type << 16);
+ }
+
+ public static bool operator ==(Register x, Register y)
+ {
+ return x.Equals(y);
+ }
+
+ public static bool operator !=(Register x, Register y)
+ {
+ return !x.Equals(y);
+ }
+
+ public override bool Equals(object obj)
+ {
+ return obj is Register reg && Equals(reg);
+ }
+
+ public bool Equals(Register other)
+ {
+ return other.Index == Index &&
+ other.Type == Type;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/IntermediateRepresentation/RegisterType.cs b/ARMeilleure/IntermediateRepresentation/RegisterType.cs
new file mode 100644
index 00000000..e71795cb
--- /dev/null
+++ b/ARMeilleure/IntermediateRepresentation/RegisterType.cs
@@ -0,0 +1,9 @@
+namespace ARMeilleure.IntermediateRepresentation
+{
+ enum RegisterType
+ {
+ Integer,
+ Vector,
+ Flag
+ }
+} \ No newline at end of file