blob: b614d836521956ca60ed55dc23d4a86e53273da6 [file] [log] [blame]
Olli Etuaho00f6fbb2016-07-20 16:32:29 +03001//
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
15namespace
16{
17
18bool IsNodeBlock(TIntermNode *node)
19{
20 ASSERT(node != nullptr);
21 return (node->getAsAggregate() && node->getAsAggregate()->getOp() == EOpSequence);
22}
23
24} // anonymous namespace
25
26IntermNodePatternMatcher::IntermNodePatternMatcher(const unsigned int mask) : mMask(mask)
27{
28}
29
Jamie Madill666f65a2016-08-26 01:34:37 +000030// static
31bool IntermNodePatternMatcher::IsDynamicIndexingOfVectorOrMatrix(TIntermBinary *node)
32{
33 return node->getOp() == EOpIndexIndirect && !node->getLeft()->isArray() &&
34 node->getLeft()->getBasicType() != EbtStruct;
35}
36
37bool IntermNodePatternMatcher::matchInternal(TIntermBinary *node, TIntermNode *parentNode)
Olli Etuaho00f6fbb2016-07-20 16:32:29 +030038{
39 if ((mMask & kExpressionReturningArray) != 0)
40 {
41 if (node->isArray() && node->getOp() == EOpAssign && parentNode != nullptr &&
42 !IsNodeBlock(parentNode))
43 {
44 return true;
45 }
46 }
47
48 if ((mMask & kUnfoldedShortCircuitExpression) != 0)
49 {
50 if (node->getRight()->hasSideEffects() &&
51 (node->getOp() == EOpLogicalOr || node->getOp() == EOpLogicalAnd))
52 {
53 return true;
54 }
55 }
56 return false;
57}
58
Jamie Madill666f65a2016-08-26 01:34:37 +000059bool IntermNodePatternMatcher::match(TIntermBinary *node, TIntermNode *parentNode)
60{
61 // L-value tracking information is needed to check for dynamic indexing in L-value.
62 // Traversers that don't track l-values can still use this class and match binary nodes with
63 // this variation of this method if they don't need to check for dynamic indexing in l-values.
64 ASSERT((mMask & kDynamicIndexingOfVectorOrMatrixInLValue) == 0);
65 return matchInternal(node, parentNode);
66}
67
68bool IntermNodePatternMatcher::match(TIntermBinary *node,
69 TIntermNode *parentNode,
70 bool isLValueRequiredHere)
71{
72 if (matchInternal(node, parentNode))
73 {
74 return true;
75 }
76 if ((mMask & kDynamicIndexingOfVectorOrMatrixInLValue) != 0)
77 {
78 if (isLValueRequiredHere && IsDynamicIndexingOfVectorOrMatrix(node))
79 {
80 return true;
81 }
82 }
83 return false;
84}
85
Olli Etuaho00f6fbb2016-07-20 16:32:29 +030086bool IntermNodePatternMatcher::match(TIntermAggregate *node, TIntermNode *parentNode)
87{
88 if ((mMask & kExpressionReturningArray) != 0)
89 {
90 if (parentNode != nullptr)
91 {
92 TIntermBinary *parentBinary = parentNode->getAsBinaryNode();
93 bool parentIsAssignment =
94 (parentBinary != nullptr &&
95 (parentBinary->getOp() == EOpAssign || parentBinary->getOp() == EOpInitialize));
96
97 if (node->getType().isArray() && !parentIsAssignment &&
98 (node->isConstructor() || node->getOp() == EOpFunctionCall) &&
99 !IsNodeBlock(parentNode))
100 {
101 return true;
102 }
103 }
104 }
105 return false;
106}
107
108bool IntermNodePatternMatcher::match(TIntermSelection *node)
109{
110 if ((mMask & kUnfoldedShortCircuitExpression) != 0)
111 {
112 if (node->usesTernaryOperator())
113 {
114 return true;
115 }
116 }
117 return false;
118}