aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Graphics.Shader/StructuredIr/AstBlock.cs
blob: 2f34bee832bfd266f8bad6c4b142eabc5dd9cc16 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using System;
using System.Collections;
using System.Collections.Generic;

using static Ryujinx.Graphics.Shader.StructuredIr.AstHelper;

namespace Ryujinx.Graphics.Shader.StructuredIr
{
    class AstBlock : AstNode, IEnumerable<IAstNode>
    {
        public AstBlockType Type { get; private set; }

        private IAstNode _condition;

        public IAstNode Condition
        {
            get
            {
                return _condition;
            }
            set
            {
                RemoveUse(_condition, this);

                AddUse(value, this);

                _condition = value;
            }
        }

        private LinkedList<IAstNode> _nodes;

        public IAstNode First => _nodes.First?.Value;
        public IAstNode Last => _nodes.Last?.Value;

        public int Count => _nodes.Count;

        public AstBlock(AstBlockType type, IAstNode condition = null)
        {
            Type      = type;
            Condition = condition;

            _nodes = new LinkedList<IAstNode>();
        }

        public void Add(IAstNode node)
        {
            Add(node, _nodes.AddLast(node));
        }

        public void AddFirst(IAstNode node)
        {
            Add(node, _nodes.AddFirst(node));
        }

        public void AddBefore(IAstNode next, IAstNode node)
        {
            Add(node, _nodes.AddBefore(next.LLNode, node));
        }

        public void AddAfter(IAstNode prev, IAstNode node)
        {
            Add(node, _nodes.AddAfter(prev.LLNode, node));
        }

        private void Add(IAstNode node, LinkedListNode<IAstNode> newNode)
        {
            if (node.Parent != null)
            {
                throw new ArgumentException("Node already belongs to a block.");
            }

            node.Parent = this;
            node.LLNode = newNode;
        }

        public void Remove(IAstNode node)
        {
            _nodes.Remove(node.LLNode);

            node.Parent = null;
            node.LLNode = null;
        }

        public void AndCondition(IAstNode cond)
        {
            Condition = new AstOperation(Instruction.LogicalAnd, Condition, cond);
        }

        public void OrCondition(IAstNode cond)
        {
            Condition = new AstOperation(Instruction.LogicalOr, Condition, cond);
        }
        public void TurnIntoIf(IAstNode cond)
        {
            Condition = cond;

            Type = AstBlockType.If;
        }

        public void TurnIntoElseIf()
        {
            Type = AstBlockType.ElseIf;
        }

        public IEnumerator<IAstNode> GetEnumerator()
        {
            return _nodes.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }
}