diff --git a/ARMeilleure/IntermediateRepresentation/Operand.cs b/ARMeilleure/IntermediateRepresentation/Operand.cs index 74b1c71eff..b3aafa7aed 100644 --- a/ARMeilleure/IntermediateRepresentation/Operand.cs +++ b/ARMeilleure/IntermediateRepresentation/Operand.cs @@ -14,10 +14,11 @@ namespace ARMeilleure.IntermediateRepresentation public byte Kind; public byte Type; public byte SymbolType; + public byte Padding; // Unused space. public ushort AssignmentsCount; public ushort AssignmentsCapacity; - public ushort UsesCount; - public ushort UsesCapacity; + public uint UsesCount; + public uint UsesCapacity; public Operation* Assignments; public Operation* Uses; public ulong Value; @@ -84,11 +85,11 @@ namespace ARMeilleure.IntermediateRepresentation { Debug.Assert(Kind != OperandKind.Memory); - return new ReadOnlySpan(_data->Uses, _data->UsesCount); + return new ReadOnlySpan(_data->Uses, (int)_data->UsesCount); } } - public int UsesCount => _data->UsesCount; + public int UsesCount => (int)_data->UsesCount; public int AssignmentsCount => _data->AssignmentsCount; public bool Relocatable => Symbol.Type != SymbolType.None; @@ -178,7 +179,7 @@ namespace ARMeilleure.IntermediateRepresentation { Add(operation, ref addr._data->Assignments, ref addr._data->AssignmentsCount, ref addr._data->AssignmentsCapacity); } - + if (index != default) { Add(operation, ref index._data->Assignments, ref index._data->AssignmentsCount, ref index._data->AssignmentsCapacity); @@ -265,6 +266,13 @@ namespace ARMeilleure.IntermediateRepresentation data = Allocators.References.Allocate(initialCapacity); } + private static void New(ref T* data, ref uint count, ref uint capacity, uint initialCapacity) where T : unmanaged + { + count = 0; + capacity = initialCapacity; + data = Allocators.References.Allocate(initialCapacity); + } + private static void Add(T item, ref T* data, ref ushort count, ref ushort capacity) where T : unmanaged { if (count < capacity) @@ -294,6 +302,40 @@ namespace ARMeilleure.IntermediateRepresentation } } + private static void Add(T item, ref T* data, ref uint count, ref uint capacity) where T : unmanaged + { + if (count < capacity) + { + data[count++] = item; + + return; + } + + // Could not add item in the fast path, fallback onto the slow path. + ExpandAdd(item, ref data, ref count, ref capacity); + + static void ExpandAdd(T item, ref T* data, ref uint count, ref uint capacity) + { + uint newCount = checked(count + 1); + uint newCapacity = (uint)Math.Min(capacity * 2, int.MaxValue); + + if (newCapacity <= capacity) + { + throw new OverflowException(); + } + + var oldSpan = new Span(data, (int)count); + + capacity = newCapacity; + data = Allocators.References.Allocate(capacity); + + oldSpan.CopyTo(new Span(data, (int)count)); + + data[count] = item; + count = newCount; + } + } + private static void Remove(in T item, ref T* data, ref ushort count) where T : unmanaged { var span = new Span(data, count); @@ -314,6 +356,26 @@ namespace ARMeilleure.IntermediateRepresentation } } + private static void Remove(in T item, ref T* data, ref uint count) where T : unmanaged + { + var span = new Span(data, (int)count); + + for (int i = 0; i < span.Length; i++) + { + if (EqualityComparer.Default.Equals(span[i], item)) + { + if (i + 1 < count) + { + span.Slice(i + 1).CopyTo(span.Slice(i)); + } + + count--; + + return; + } + } + } + public override int GetHashCode() { if (Kind == OperandKind.LocalVariable)