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  }