diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2019-04-26 01:55:12 -0300 |
|---|---|---|
| committer | jduncanator <1518948+jduncanator@users.noreply.github.com> | 2019-04-26 14:55:12 +1000 |
| commit | 8a7d99cdeae2355511d4eb43aefb76d0d886bcf8 (patch) | |
| tree | 655d33f4db5dc3eb21c9c4ff5867b1179913585a /ChocolArm64/IntermediateRepresentation | |
| parent | 2b8eac1bcec6d4870776b4f302d9dd7794223642 (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')
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); + } + } +} |
