Line data Source code
1 : //
2 : // Copyright (c) 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/IntermNodePatternMatcher.h"
12 :
13 : #include "compiler/translator/IntermNode.h"
14 :
15 : namespace sh
16 : {
17 :
18 0 : IntermNodePatternMatcher::IntermNodePatternMatcher(const unsigned int mask) : mMask(mask)
19 : {
20 0 : }
21 :
22 : // static
23 0 : bool IntermNodePatternMatcher::IsDynamicIndexingOfVectorOrMatrix(TIntermBinary *node)
24 : {
25 0 : return node->getOp() == EOpIndexIndirect && !node->getLeft()->isArray() &&
26 0 : node->getLeft()->getBasicType() != EbtStruct;
27 : }
28 :
29 0 : bool IntermNodePatternMatcher::matchInternal(TIntermBinary *node, TIntermNode *parentNode)
30 : {
31 0 : if ((mMask & kExpressionReturningArray) != 0)
32 : {
33 0 : if (node->isArray() && node->getOp() == EOpAssign && parentNode != nullptr &&
34 0 : !parentNode->getAsBlock())
35 : {
36 0 : return true;
37 : }
38 : }
39 :
40 0 : if ((mMask & kUnfoldedShortCircuitExpression) != 0)
41 : {
42 0 : if (node->getRight()->hasSideEffects() &&
43 0 : (node->getOp() == EOpLogicalOr || node->getOp() == EOpLogicalAnd))
44 : {
45 0 : return true;
46 : }
47 : }
48 0 : return false;
49 : }
50 :
51 0 : bool IntermNodePatternMatcher::match(TIntermBinary *node, TIntermNode *parentNode)
52 : {
53 : // L-value tracking information is needed to check for dynamic indexing in L-value.
54 : // Traversers that don't track l-values can still use this class and match binary nodes with
55 : // this variation of this method if they don't need to check for dynamic indexing in l-values.
56 0 : ASSERT((mMask & kDynamicIndexingOfVectorOrMatrixInLValue) == 0);
57 0 : return matchInternal(node, parentNode);
58 : }
59 :
60 0 : bool IntermNodePatternMatcher::match(TIntermBinary *node,
61 : TIntermNode *parentNode,
62 : bool isLValueRequiredHere)
63 : {
64 0 : if (matchInternal(node, parentNode))
65 : {
66 0 : return true;
67 : }
68 0 : if ((mMask & kDynamicIndexingOfVectorOrMatrixInLValue) != 0)
69 : {
70 0 : if (isLValueRequiredHere && IsDynamicIndexingOfVectorOrMatrix(node))
71 : {
72 0 : return true;
73 : }
74 : }
75 0 : return false;
76 : }
77 :
78 0 : bool IntermNodePatternMatcher::match(TIntermAggregate *node, TIntermNode *parentNode)
79 : {
80 0 : if ((mMask & kExpressionReturningArray) != 0)
81 : {
82 0 : if (parentNode != nullptr)
83 : {
84 0 : TIntermBinary *parentBinary = parentNode->getAsBinaryNode();
85 : bool parentIsAssignment =
86 0 : (parentBinary != nullptr &&
87 0 : (parentBinary->getOp() == EOpAssign || parentBinary->getOp() == EOpInitialize));
88 :
89 0 : if (node->getType().isArray() && !parentIsAssignment &&
90 0 : (node->isConstructor() || node->getOp() == EOpFunctionCall) &&
91 0 : !parentNode->getAsBlock())
92 : {
93 0 : return true;
94 : }
95 : }
96 : }
97 0 : return false;
98 : }
99 :
100 0 : bool IntermNodePatternMatcher::match(TIntermTernary *node)
101 : {
102 0 : if ((mMask & kUnfoldedShortCircuitExpression) != 0)
103 : {
104 0 : return true;
105 : }
106 0 : return false;
107 : }
108 :
109 0 : bool IntermNodePatternMatcher::match(TIntermDeclaration *node)
110 : {
111 0 : if ((mMask & kMultiDeclaration) != 0)
112 : {
113 0 : return node->getSequence()->size() > 1;
114 : }
115 0 : return false;
116 : }
117 :
118 : } // namespace sh
|