blob: 567e8f744055064b0db9457f79af3076082a2f83 [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
Jamie Madill45bcc782016-11-07 13:58:48 -050015namespace sh
16{
17
Olli Etuaho00f6fbb2016-07-20 16:32:29 +030018IntermNodePatternMatcher::IntermNodePatternMatcher(const unsigned int mask) : mMask(mask)
19{
20}
21
Jamie Madill666f65a2016-08-26 01:34:37 +000022// static
23bool IntermNodePatternMatcher::IsDynamicIndexingOfVectorOrMatrix(TIntermBinary *node)
24{
25 return node->getOp() == EOpIndexIndirect && !node->getLeft()->isArray() &&
26 node->getLeft()->getBasicType() != EbtStruct;
27}
28
29bool IntermNodePatternMatcher::matchInternal(TIntermBinary *node, TIntermNode *parentNode)
Olli Etuaho00f6fbb2016-07-20 16:32:29 +030030{
31 if ((mMask & kExpressionReturningArray) != 0)
32 {
33 if (node->isArray() && node->getOp() == EOpAssign && parentNode != nullptr &&
Olli Etuaho6d40bbd2016-09-30 13:49:38 +010034 !parentNode->getAsBlock())
Olli Etuaho00f6fbb2016-07-20 16:32:29 +030035 {
36 return true;
37 }
38 }
39
40 if ((mMask & kUnfoldedShortCircuitExpression) != 0)
41 {
42 if (node->getRight()->hasSideEffects() &&
43 (node->getOp() == EOpLogicalOr || node->getOp() == EOpLogicalAnd))
44 {
45 return true;
46 }
47 }
48 return false;
49}
50
Olli Etuahobb5a7e22017-08-30 13:03:12 +030051bool IntermNodePatternMatcher::match(TIntermUnary *node)
52{
53 if ((mMask & kArrayLengthMethod) != 0)
54 {
55 if (node->getOp() == EOpArrayLength)
56 {
57 return true;
58 }
59 }
60 return false;
61}
62
Jamie Madill666f65a2016-08-26 01:34:37 +000063bool IntermNodePatternMatcher::match(TIntermBinary *node, TIntermNode *parentNode)
64{
65 // L-value tracking information is needed to check for dynamic indexing in L-value.
66 // Traversers that don't track l-values can still use this class and match binary nodes with
67 // this variation of this method if they don't need to check for dynamic indexing in l-values.
68 ASSERT((mMask & kDynamicIndexingOfVectorOrMatrixInLValue) == 0);
69 return matchInternal(node, parentNode);
70}
71
72bool IntermNodePatternMatcher::match(TIntermBinary *node,
73 TIntermNode *parentNode,
74 bool isLValueRequiredHere)
75{
76 if (matchInternal(node, parentNode))
77 {
78 return true;
79 }
80 if ((mMask & kDynamicIndexingOfVectorOrMatrixInLValue) != 0)
81 {
82 if (isLValueRequiredHere && IsDynamicIndexingOfVectorOrMatrix(node))
83 {
84 return true;
85 }
86 }
87 return false;
88}
89
Olli Etuaho00f6fbb2016-07-20 16:32:29 +030090bool IntermNodePatternMatcher::match(TIntermAggregate *node, TIntermNode *parentNode)
91{
92 if ((mMask & kExpressionReturningArray) != 0)
93 {
94 if (parentNode != nullptr)
95 {
96 TIntermBinary *parentBinary = parentNode->getAsBinaryNode();
97 bool parentIsAssignment =
98 (parentBinary != nullptr &&
99 (parentBinary->getOp() == EOpAssign || parentBinary->getOp() == EOpInitialize));
100
101 if (node->getType().isArray() && !parentIsAssignment &&
Olli Etuaho1ecd14b2017-01-26 13:54:15 -0800102 (node->isConstructor() || node->isFunctionCall()) && !parentNode->getAsBlock())
Olli Etuaho00f6fbb2016-07-20 16:32:29 +0300103 {
104 return true;
105 }
106 }
107 }
108 return false;
109}
110
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300111bool IntermNodePatternMatcher::match(TIntermTernary *node)
Olli Etuaho00f6fbb2016-07-20 16:32:29 +0300112{
113 if ((mMask & kUnfoldedShortCircuitExpression) != 0)
114 {
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300115 return true;
Olli Etuaho00f6fbb2016-07-20 16:32:29 +0300116 }
117 return false;
118}
Jamie Madill45bcc782016-11-07 13:58:48 -0500119
Corentin Wallez1212bca2016-11-23 13:44:05 -0500120bool IntermNodePatternMatcher::match(TIntermDeclaration *node)
121{
122 if ((mMask & kMultiDeclaration) != 0)
123 {
Olli Etuaho9733cee2017-05-11 19:14:35 +0300124 if (node->getSequence()->size() > 1)
125 {
126 return true;
127 }
128 }
129 if ((mMask & kArrayDeclaration) != 0)
130 {
131 if (node->getSequence()->front()->getAsTyped()->getType().isStructureContainingArrays())
132 {
133 return true;
134 }
135 // Need to check from all declarators whether they are arrays since that may vary between
136 // declarators.
137 for (TIntermNode *declarator : *node->getSequence())
138 {
139 if (declarator->getAsTyped()->isArray())
140 {
141 return true;
142 }
143 }
144 }
145 if ((mMask & kNamelessStructDeclaration) != 0)
146 {
147 TIntermTyped *declarator = node->getSequence()->front()->getAsTyped();
148 if (declarator->getBasicType() == EbtStruct &&
149 declarator->getType().getStruct()->name() == "")
150 {
151 return true;
152 }
Corentin Wallez1212bca2016-11-23 13:44:05 -0500153 }
154 return false;
155}
156
Jamie Madill45bcc782016-11-07 13:58:48 -0500157} // namespace sh