using System; using System.Collections.Generic; namespace ARMeilleure.IntermediateRepresentation { class BasicBlock : IIntrusiveListNode { private readonly List _successors = new List(); public int Index { get; set; } public BasicBlock ListPrevious { get; set; } public BasicBlock ListNext { get; set; } public IntrusiveList Operations { get; } public List Predecessors { get; } public HashSet DominanceFrontiers { get; } public BasicBlock ImmediateDominator { get; set; } public int SuccessorCount => _successors.Count; public BasicBlock() : this(index: -1) { } public BasicBlock(int index) { Operations = new IntrusiveList(); Predecessors = new List(); DominanceFrontiers = new HashSet(); Index = index; } public void AddSuccessor(BasicBlock block) { if (block == null) { throw new ArgumentNullException(nameof(block)); } block.Predecessors.Add(this); _successors.Add(block); } public void RemoveSuccessor(int index) { BasicBlock oldBlock = _successors[index]; oldBlock.Predecessors.Remove(this); _successors.RemoveAt(index); } public BasicBlock GetSuccessor(int index) { return _successors[index]; } public void SetSuccessor(int index, BasicBlock block) { if (block == null) { throw new ArgumentNullException(nameof(block)); } BasicBlock oldBlock = _successors[index]; oldBlock.Predecessors.Remove(this); block.Predecessors.Add(this); _successors[index] = block; } public void Append(Node node) { var lastOp = Operations.Last as Operation; // Append node before terminal or to end if no terminal. switch (lastOp?.Instruction) { case Instruction.Return: case Instruction.Tailcall: case Instruction.BranchIf: Operations.AddBefore(lastOp, node); break; default: Operations.AddLast(node); break; } } public Node GetLastOp() { return Operations.Last; } } }