aboutsummaryrefslogtreecommitdiff
path: root/ChocolArm64/IntermediateRepresentation
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2019-04-26 01:55:12 -0300
committerjduncanator <1518948+jduncanator@users.noreply.github.com>2019-04-26 14:55:12 +1000
commit8a7d99cdeae2355511d4eb43aefb76d0d886bcf8 (patch)
tree655d33f4db5dc3eb21c9c4ff5867b1179913585a /ChocolArm64/IntermediateRepresentation
parent2b8eac1bcec6d4870776b4f302d9dd7794223642 (diff)
Refactoring and optimization on CPU translation (#661)
* Refactoring and optimization on CPU translation * Remove now unused property * Rename ilBlock -> block (local) * Change equality comparison on RegisterMask for consistency Co-Authored-By: gdkchan <gab.dark.100@gmail.com> * Add back the aggressive inlining attribute to the Synchronize method * Implement IEquatable on the Register struct * Fix identation
Diffstat (limited to 'ChocolArm64/IntermediateRepresentation')
-rw-r--r--ChocolArm64/IntermediateRepresentation/BasicBlock.cs122
-rw-r--r--ChocolArm64/IntermediateRepresentation/ILLabel.cs4
-rw-r--r--ChocolArm64/IntermediateRepresentation/Operation.cs112
-rw-r--r--ChocolArm64/IntermediateRepresentation/OperationType.cs18
-rw-r--r--ChocolArm64/IntermediateRepresentation/RegisterMask.cs56
5 files changed, 312 insertions, 0 deletions
diff --git a/ChocolArm64/IntermediateRepresentation/BasicBlock.cs b/ChocolArm64/IntermediateRepresentation/BasicBlock.cs
new file mode 100644
index 00000000..ce39fddb
--- /dev/null
+++ b/ChocolArm64/IntermediateRepresentation/BasicBlock.cs
@@ -0,0 +1,122 @@
+using ChocolArm64.State;
+using System;
+using System.Collections.Generic;
+
+using static ChocolArm64.State.RegisterConsts;
+
+namespace ChocolArm64.IntermediateRepresentation
+{
+ class BasicBlock
+ {
+ public int Index { get; set; }
+
+ public RegisterMask RegInputs { get; private set; }
+ public RegisterMask RegOutputs { get; private set; }
+
+ public bool HasStateLoad { get; private set; }
+
+ private List<Operation> _operations;
+
+ public int Count => _operations.Count;
+
+ 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 BasicBlock(int index = 0)
+ {
+ Index = index;
+
+ _operations = new List<Operation>();
+
+ Predecessors = new List<BasicBlock>();
+ }
+
+ private BasicBlock AddSuccessor(BasicBlock oldBlock, BasicBlock newBlock)
+ {
+ oldBlock?.Predecessors.Remove(this);
+ newBlock?.Predecessors.Add(this);
+
+ return newBlock;
+ }
+
+ public void Add(Operation operation)
+ {
+ if (operation.Type == OperationType.LoadLocal ||
+ operation.Type == OperationType.StoreLocal)
+ {
+ int index = operation.GetArg<int>(0);
+
+ if (IsRegIndex(index))
+ {
+ long intMask = 0;
+ long vecMask = 0;
+
+ switch (operation.GetArg<RegisterType>(1))
+ {
+ case RegisterType.Flag: intMask = (1L << RegsCount) << index; break;
+ case RegisterType.Int: intMask = 1L << index; break;
+ case RegisterType.Vector: vecMask = 1L << index; break;
+ }
+
+ RegisterMask mask = new RegisterMask(intMask, vecMask);
+
+ if (operation.Type == OperationType.LoadLocal)
+ {
+ RegInputs |= mask & ~RegOutputs;
+ }
+ else
+ {
+ RegOutputs |= mask;
+ }
+ }
+ }
+ else if (operation.Type == OperationType.LoadContext)
+ {
+ HasStateLoad = true;
+ }
+
+ operation.Parent = this;
+
+ _operations.Add(operation);
+ }
+
+ public static bool IsRegIndex(int index)
+ {
+ return (uint)index < RegsCount;
+ }
+
+ public Operation GetOperation(int index)
+ {
+ if ((uint)index >= _operations.Count)
+ {
+ throw new ArgumentOutOfRangeException(nameof(index));
+ }
+
+ return _operations[index];
+ }
+
+ public Operation GetLastOp()
+ {
+ if (Count == 0)
+ {
+ return null;
+ }
+
+ return _operations[Count - 1];
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/IntermediateRepresentation/ILLabel.cs b/ChocolArm64/IntermediateRepresentation/ILLabel.cs
new file mode 100644
index 00000000..70c576cd
--- /dev/null
+++ b/ChocolArm64/IntermediateRepresentation/ILLabel.cs
@@ -0,0 +1,4 @@
+namespace ChocolArm64.IntermediateRepresentation
+{
+ class ILLabel { }
+} \ No newline at end of file
diff --git a/ChocolArm64/IntermediateRepresentation/Operation.cs b/ChocolArm64/IntermediateRepresentation/Operation.cs
new file mode 100644
index 00000000..dcd01bcd
--- /dev/null
+++ b/ChocolArm64/IntermediateRepresentation/Operation.cs
@@ -0,0 +1,112 @@
+using ChocolArm64.State;
+using System;
+using System.Reflection;
+using System.Reflection.Emit;
+
+namespace ChocolArm64.IntermediateRepresentation
+{
+ class Operation
+ {
+ public BasicBlock Parent { get; set; }
+
+ public OperationType Type { get; }
+
+ private object[] _arguments { get; }
+
+ private Operation(OperationType type, params object[] arguments)
+ {
+ Type = type;
+ _arguments = arguments;
+ }
+
+ public T GetArg<T>(int index)
+ {
+ return (T)GetArg(index);
+ }
+
+ public object GetArg(int index)
+ {
+ if ((uint)index >= _arguments.Length)
+ {
+ throw new ArgumentOutOfRangeException(nameof(index));
+ }
+
+ return _arguments[index];
+ }
+
+ public static Operation Call(MethodInfo info)
+ {
+ return new Operation(OperationType.Call, info);
+ }
+
+ public static Operation CallVirtual(MethodInfo info)
+ {
+ return new Operation(OperationType.CallVirtual, info);
+ }
+
+ public static Operation IL(OpCode ilOp)
+ {
+ return new Operation(OperationType.IL, ilOp);
+ }
+
+ public static Operation ILBranch(OpCode ilOp, ILLabel target)
+ {
+ return new Operation(OperationType.ILBranch, ilOp, target);
+ }
+
+ public static Operation LoadArgument(int index)
+ {
+ return new Operation(OperationType.LoadArgument, index);
+ }
+
+ public static Operation LoadConstant(int value)
+ {
+ return new Operation(OperationType.LoadConstant, value);
+ }
+
+ public static Operation LoadConstant(long value)
+ {
+ return new Operation(OperationType.LoadConstant, value);
+ }
+
+ public static Operation LoadConstant(float value)
+ {
+ return new Operation(OperationType.LoadConstant, value);
+ }
+
+ public static Operation LoadConstant(double value)
+ {
+ return new Operation(OperationType.LoadConstant, value);
+ }
+
+ public static Operation LoadContext()
+ {
+ return new Operation(OperationType.LoadContext);
+ }
+
+ public static Operation LoadField(FieldInfo info)
+ {
+ return new Operation(OperationType.LoadField, info);
+ }
+
+ public static Operation LoadLocal(int index, RegisterType type, RegisterSize size)
+ {
+ return new Operation(OperationType.LoadLocal, index, type, size);
+ }
+
+ public static Operation MarkLabel(ILLabel label)
+ {
+ return new Operation(OperationType.MarkLabel, label);
+ }
+
+ public static Operation StoreContext()
+ {
+ return new Operation(OperationType.StoreContext);
+ }
+
+ public static Operation StoreLocal(int index, RegisterType type, RegisterSize size)
+ {
+ return new Operation(OperationType.StoreLocal, index, type, size);
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/IntermediateRepresentation/OperationType.cs b/ChocolArm64/IntermediateRepresentation/OperationType.cs
new file mode 100644
index 00000000..644f1716
--- /dev/null
+++ b/ChocolArm64/IntermediateRepresentation/OperationType.cs
@@ -0,0 +1,18 @@
+namespace ChocolArm64.IntermediateRepresentation
+{
+ enum OperationType
+ {
+ Call,
+ CallVirtual,
+ IL,
+ ILBranch,
+ LoadArgument,
+ LoadConstant,
+ LoadContext,
+ LoadField,
+ LoadLocal,
+ MarkLabel,
+ StoreContext,
+ StoreLocal
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/IntermediateRepresentation/RegisterMask.cs b/ChocolArm64/IntermediateRepresentation/RegisterMask.cs
new file mode 100644
index 00000000..aea6ab36
--- /dev/null
+++ b/ChocolArm64/IntermediateRepresentation/RegisterMask.cs
@@ -0,0 +1,56 @@
+using System;
+
+namespace ChocolArm64.IntermediateRepresentation
+{
+ struct RegisterMask : IEquatable<RegisterMask>
+ {
+ public long IntMask { get; set; }
+ public long VecMask { get; set; }
+
+ public RegisterMask(long intMask, long vecMask)
+ {
+ IntMask = intMask;
+ VecMask = vecMask;
+ }
+
+ public static RegisterMask operator &(RegisterMask x, RegisterMask y)
+ {
+ return new RegisterMask(x.IntMask & y.IntMask, x.VecMask & y.VecMask);
+ }
+
+ public static RegisterMask operator |(RegisterMask x, RegisterMask y)
+ {
+ return new RegisterMask(x.IntMask | y.IntMask, x.VecMask | y.VecMask);
+ }
+
+ public static RegisterMask operator ~(RegisterMask x)
+ {
+ return new RegisterMask(~x.IntMask, ~x.VecMask);
+ }
+
+ public static bool operator ==(RegisterMask x, RegisterMask y)
+ {
+ return x.Equals(y);
+ }
+
+ public static bool operator !=(RegisterMask x, RegisterMask y)
+ {
+ return !x.Equals(y);
+ }
+
+ public override bool Equals(object obj)
+ {
+ return obj is RegisterMask regMask && Equals(regMask);
+ }
+
+ public bool Equals(RegisterMask other)
+ {
+ return IntMask == other.IntMask && VecMask == other.VecMask;
+ }
+
+ public override int GetHashCode()
+ {
+ return HashCode.Combine(IntMask, VecMask);
+ }
+ }
+}