PhiNode.cs
1 using System; 2 using System.Collections.Generic; 3 4 namespace Ryujinx.Graphics.Shader.IntermediateRepresentation 5 { 6 class PhiNode : INode 7 { 8 private Operand _dest; 9 10 public Operand Dest 11 { 12 get => _dest; 13 set => _dest = AssignDest(value); 14 } 15 16 public int DestsCount => _dest != null ? 1 : 0; 17 18 private readonly HashSet<BasicBlock> _blocks; 19 20 private class PhiSource 21 { 22 public BasicBlock Block { get; } 23 public Operand Operand { get; set; } 24 25 public PhiSource(BasicBlock block, Operand operand) 26 { 27 Block = block; 28 Operand = operand; 29 } 30 } 31 32 private readonly List<PhiSource> _sources; 33 34 public int SourcesCount => _sources.Count; 35 36 public PhiNode(Operand dest) 37 { 38 _blocks = new HashSet<BasicBlock>(); 39 40 _sources = new List<PhiSource>(); 41 42 dest.AsgOp = this; 43 44 Dest = dest; 45 } 46 47 private Operand AssignDest(Operand dest) 48 { 49 if (dest != null && dest.Type == OperandType.LocalVariable) 50 { 51 dest.AsgOp = this; 52 } 53 54 return dest; 55 } 56 57 public void AddSource(BasicBlock block, Operand operand) 58 { 59 if (_blocks.Add(block)) 60 { 61 if (operand.Type == OperandType.LocalVariable) 62 { 63 operand.UseOps.Add(this); 64 } 65 66 _sources.Add(new PhiSource(block, operand)); 67 } 68 } 69 70 public Operand GetDest(int index) 71 { 72 ArgumentOutOfRangeException.ThrowIfNotEqual(index, 0); 73 74 return _dest; 75 } 76 77 public Operand GetSource(int index) 78 { 79 return _sources[index].Operand; 80 } 81 82 public BasicBlock GetBlock(int index) 83 { 84 return _sources[index].Block; 85 } 86 87 public void SetSource(int index, Operand source) 88 { 89 Operand oldSrc = _sources[index].Operand; 90 91 if (oldSrc != null && oldSrc.Type == OperandType.LocalVariable) 92 { 93 oldSrc.UseOps.Remove(this); 94 } 95 96 if (source.Type == OperandType.LocalVariable) 97 { 98 source.UseOps.Add(this); 99 } 100 101 _sources[index].Operand = source; 102 } 103 } 104 }