• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2016 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // IntermNodePatternMatcher is a helper class for matching node trees to given patterns.
7 // It can be used whenever the same checks for certain node structures are common to multiple AST
8 // traversers.
9 //
10 
11 #include "compiler/translator/tree_util/IntermNodePatternMatcher.h"
12 
13 #include "compiler/translator/IntermNode.h"
14 #include "compiler/translator/SymbolTable.h"
15 #include "compiler/translator/util.h"
16 
17 namespace sh
18 {
19 
20 namespace
21 {
22 
ContainsMatrixNode(const TIntermSequence & sequence)23 bool ContainsMatrixNode(const TIntermSequence &sequence)
24 {
25     for (size_t ii = 0; ii < sequence.size(); ++ii)
26     {
27         TIntermTyped *node = sequence[ii]->getAsTyped();
28         if (node && node->isMatrix())
29             return true;
30     }
31     return false;
32 }
33 
ContainsVectorNode(const TIntermSequence & sequence)34 bool ContainsVectorNode(const TIntermSequence &sequence)
35 {
36     for (size_t ii = 0; ii < sequence.size(); ++ii)
37     {
38         TIntermTyped *node = sequence[ii]->getAsTyped();
39         if (node && node->isVector())
40             return true;
41     }
42     return false;
43 }
44 
45 }  // anonymous namespace
46 
IntermNodePatternMatcher(const unsigned int mask)47 IntermNodePatternMatcher::IntermNodePatternMatcher(const unsigned int mask) : mMask(mask) {}
48 
49 // static
IsDynamicIndexingOfNonSSBOVectorOrMatrix(TIntermBinary * node)50 bool IntermNodePatternMatcher::IsDynamicIndexingOfNonSSBOVectorOrMatrix(TIntermBinary *node)
51 {
52     return IsDynamicIndexingOfVectorOrMatrix(node) && !IsInShaderStorageBlock(node->getLeft());
53 }
54 
55 // static
IsDynamicIndexingOfVectorOrMatrix(TIntermBinary * node)56 bool IntermNodePatternMatcher::IsDynamicIndexingOfVectorOrMatrix(TIntermBinary *node)
57 {
58     return node->getOp() == EOpIndexIndirect && !node->getLeft()->isArray() &&
59            node->getLeft()->getBasicType() != EbtStruct;
60 }
61 
matchInternal(TIntermBinary * node,TIntermNode * parentNode)62 bool IntermNodePatternMatcher::matchInternal(TIntermBinary *node, TIntermNode *parentNode)
63 {
64     if ((mMask & kExpressionReturningArray) != 0)
65     {
66         if (node->isArray() && node->getOp() == EOpAssign && parentNode != nullptr &&
67             !parentNode->getAsBlock())
68         {
69             return true;
70         }
71     }
72 
73     if ((mMask & kUnfoldedShortCircuitExpression) != 0)
74     {
75         if (node->getRight()->hasSideEffects() &&
76             (node->getOp() == EOpLogicalOr || node->getOp() == EOpLogicalAnd))
77         {
78             return true;
79         }
80     }
81     return false;
82 }
83 
match(TIntermUnary * node)84 bool IntermNodePatternMatcher::match(TIntermUnary *node)
85 {
86     if ((mMask & kArrayLengthMethod) != 0)
87     {
88         if (node->getOp() == EOpArrayLength)
89         {
90             return true;
91         }
92     }
93     return false;
94 }
95 
match(TIntermBinary * node,TIntermNode * parentNode)96 bool IntermNodePatternMatcher::match(TIntermBinary *node, TIntermNode *parentNode)
97 {
98     // L-value tracking information is needed to check for dynamic indexing in L-value.
99     // Traversers that don't track l-values can still use this class and match binary nodes with
100     // this variation of this method if they don't need to check for dynamic indexing in l-values.
101     ASSERT((mMask & kDynamicIndexingOfVectorOrMatrixInLValue) == 0);
102     return matchInternal(node, parentNode);
103 }
104 
match(TIntermBinary * node,TIntermNode * parentNode,bool isLValueRequiredHere)105 bool IntermNodePatternMatcher::match(TIntermBinary *node,
106                                      TIntermNode *parentNode,
107                                      bool isLValueRequiredHere)
108 {
109     if (matchInternal(node, parentNode))
110     {
111         return true;
112     }
113     if ((mMask & kDynamicIndexingOfVectorOrMatrixInLValue) != 0)
114     {
115         if (isLValueRequiredHere && IsDynamicIndexingOfVectorOrMatrix(node))
116         {
117             return true;
118         }
119     }
120     return false;
121 }
122 
match(TIntermAggregate * node,TIntermNode * parentNode)123 bool IntermNodePatternMatcher::match(TIntermAggregate *node, TIntermNode *parentNode)
124 {
125     if ((mMask & kExpressionReturningArray) != 0)
126     {
127         if (parentNode != nullptr)
128         {
129             TIntermBinary *parentBinary = parentNode->getAsBinaryNode();
130             bool parentIsAssignment =
131                 (parentBinary != nullptr &&
132                  (parentBinary->getOp() == EOpAssign || parentBinary->getOp() == EOpInitialize));
133 
134             if (node->getType().isArray() && !parentIsAssignment &&
135                 (node->isConstructor() || node->isFunctionCall()) && !parentNode->getAsBlock())
136             {
137                 return true;
138             }
139         }
140     }
141     if ((mMask & kScalarizedVecOrMatConstructor) != 0)
142     {
143         if (node->getOp() == EOpConstruct)
144         {
145             if (node->getType().isVector() && ContainsMatrixNode(*(node->getSequence())))
146             {
147                 return true;
148             }
149             else if (node->getType().isMatrix() && ContainsVectorNode(*(node->getSequence())))
150             {
151                 return true;
152             }
153         }
154     }
155     return false;
156 }
157 
match(TIntermTernary * node)158 bool IntermNodePatternMatcher::match(TIntermTernary *node)
159 {
160     if ((mMask & kUnfoldedShortCircuitExpression) != 0)
161     {
162         return true;
163     }
164     return false;
165 }
166 
match(TIntermDeclaration * node)167 bool IntermNodePatternMatcher::match(TIntermDeclaration *node)
168 {
169     if ((mMask & kMultiDeclaration) != 0)
170     {
171         if (node->getSequence()->size() > 1)
172         {
173             return true;
174         }
175     }
176     if ((mMask & kArrayDeclaration) != 0)
177     {
178         if (node->getSequence()->front()->getAsTyped()->getType().isStructureContainingArrays())
179         {
180             return true;
181         }
182         // Need to check from all declarators whether they are arrays since that may vary between
183         // declarators.
184         for (TIntermNode *declarator : *node->getSequence())
185         {
186             if (declarator->getAsTyped()->isArray())
187             {
188                 return true;
189             }
190         }
191     }
192     if ((mMask & kNamelessStructDeclaration) != 0)
193     {
194         TIntermTyped *declarator = node->getSequence()->front()->getAsTyped();
195         if (declarator->getBasicType() == EbtStruct &&
196             declarator->getType().getStruct()->symbolType() == SymbolType::Empty)
197         {
198             return true;
199         }
200     }
201     return false;
202 }
203 
204 }  // namespace sh
205