BasicBlock.cs
1 using System; 2 using System.Collections.Generic; 3 using System.Runtime.CompilerServices; 4 5 namespace ARMeilleure.IntermediateRepresentation 6 { 7 class BasicBlock : IEquatable<BasicBlock>, IIntrusiveListNode<BasicBlock> 8 { 9 private const uint MaxSuccessors = 2; 10 11 private int _succCount; 12 private BasicBlock _succ0; 13 private readonly BasicBlock _succ1; 14 private HashSet<BasicBlock> _domFrontiers; 15 16 public int Index { get; set; } 17 public BasicBlockFrequency Frequency { get; set; } 18 public BasicBlock ListPrevious { get; set; } 19 public BasicBlock ListNext { get; set; } 20 public IntrusiveList<Operation> Operations { get; } 21 public List<BasicBlock> Predecessors { get; } 22 public BasicBlock ImmediateDominator { get; set; } 23 24 public int SuccessorsCount => _succCount; 25 26 public HashSet<BasicBlock> DominanceFrontiers 27 { 28 get 29 { 30 _domFrontiers ??= new HashSet<BasicBlock>(); 31 32 return _domFrontiers; 33 } 34 } 35 36 public BasicBlock() : this(index: -1) { } 37 38 public BasicBlock(int index) 39 { 40 Operations = new IntrusiveList<Operation>(); 41 Predecessors = new List<BasicBlock>(); 42 43 Index = index; 44 } 45 46 public void AddSuccessor(BasicBlock block) 47 { 48 ArgumentNullException.ThrowIfNull(block); 49 50 if ((uint)_succCount + 1 > MaxSuccessors) 51 { 52 ThrowSuccessorOverflow(); 53 } 54 55 block.Predecessors.Add(this); 56 57 GetSuccessorUnsafe(_succCount++) = block; 58 } 59 60 public void RemoveSuccessor(int index) 61 { 62 if ((uint)index >= (uint)_succCount) 63 { 64 ThrowOutOfRange(nameof(index)); 65 } 66 67 ref BasicBlock oldBlock = ref GetSuccessorUnsafe(index); 68 69 oldBlock.Predecessors.Remove(this); 70 oldBlock = null; 71 72 if (index == 0) 73 { 74 _succ0 = _succ1; 75 } 76 77 _succCount--; 78 } 79 80 public BasicBlock GetSuccessor(int index) 81 { 82 if ((uint)index >= (uint)_succCount) 83 { 84 ThrowOutOfRange(nameof(index)); 85 } 86 87 return GetSuccessorUnsafe(index); 88 } 89 90 private ref BasicBlock GetSuccessorUnsafe(int index) 91 { 92 return ref Unsafe.Add(ref _succ0, index); 93 } 94 95 public void SetSuccessor(int index, BasicBlock block) 96 { 97 ArgumentNullException.ThrowIfNull(block); 98 99 if ((uint)index >= (uint)_succCount) 100 { 101 ThrowOutOfRange(nameof(index)); 102 } 103 104 ref BasicBlock oldBlock = ref GetSuccessorUnsafe(index); 105 106 oldBlock.Predecessors.Remove(this); 107 block.Predecessors.Add(this); 108 109 oldBlock = block; 110 } 111 112 public void Append(Operation node) 113 { 114 Operation last = Operations.Last; 115 116 // Append node before terminal or to end if no terminal. 117 if (last == default) 118 { 119 Operations.AddLast(node); 120 121 return; 122 } 123 124 switch (last.Instruction) 125 { 126 case Instruction.Return: 127 case Instruction.Tailcall: 128 case Instruction.BranchIf: 129 Operations.AddBefore(last, node); 130 break; 131 132 default: 133 Operations.AddLast(node); 134 break; 135 } 136 } 137 138 private static void ThrowOutOfRange(string name) => throw new ArgumentOutOfRangeException(name); 139 private static void ThrowSuccessorOverflow() => throw new OverflowException($"BasicBlock can only have {MaxSuccessors} successors."); 140 141 public bool Equals(BasicBlock other) 142 { 143 return other == this; 144 } 145 146 public override bool Equals(object obj) 147 { 148 return Equals(obj as BasicBlock); 149 } 150 151 public override int GetHashCode() 152 { 153 return base.GetHashCode(); 154 } 155 } 156 }