blob: dd2054f68f07c953fe97111aab89e0939447ec69 [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
Jamie Madill666f65a2016-08-26 01:34:37 +000051bool 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 ASSERT((mMask & kDynamicIndexingOfVectorOrMatrixInLValue) == 0);
57 return matchInternal(node, parentNode);
58}
59
60bool IntermNodePatternMatcher::match(TIntermBinary *node,
61 TIntermNode *parentNode,
62 bool isLValueRequiredHere)
63{
64 if (matchInternal(node, parentNode))
65 {
66 return true;
67 }
68 if ((mMask & kDynamicIndexingOfVectorOrMatrixInLValue) != 0)
69 {
70 if (isLValueRequiredHere && IsDynamicIndexingOfVectorOrMatrix(node))
71 {
72 return true;
73 }
74 }
75 return false;
76}
77
Olli Etuaho00f6fbb2016-07-20 16:32:29 +030078bool IntermNodePatternMatcher::match(TIntermAggregate *node, TIntermNode *parentNode)
79{
80 if ((mMask & kExpressionReturningArray) != 0)
81 {
82 if (parentNode != nullptr)
83 {
84 TIntermBinary *parentBinary = parentNode->getAsBinaryNode();
85 bool parentIsAssignment =
86 (parentBinary != nullptr &&
87 (parentBinary->getOp() == EOpAssign || parentBinary->getOp() == EOpInitialize));
88
89 if (node->getType().isArray() && !parentIsAssignment &&
90 (node->isConstructor() || node->getOp() == EOpFunctionCall) &&
Olli Etuaho6d40bbd2016-09-30 13:49:38 +010091 !parentNode->getAsBlock())
Olli Etuaho00f6fbb2016-07-20 16:32:29 +030092 {
93 return true;
94 }
95 }
96 }
97 return false;
98}
99
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300100bool IntermNodePatternMatcher::match(TIntermTernary *node)
Olli Etuaho00f6fbb2016-07-20 16:32:29 +0300101{
102 if ((mMask & kUnfoldedShortCircuitExpression) != 0)
103 {
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300104 return true;
Olli Etuaho00f6fbb2016-07-20 16:32:29 +0300105 }
106 return false;
107}
Jamie Madill45bcc782016-11-07 13:58:48 -0500108
109} // namespace sh