blob: 4177b05acb786c4cb21c35c3d4dd4d35639392b2 [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
Olli Etuaho00f6fbb2016-07-20 16:32:29 +030015IntermNodePatternMatcher::IntermNodePatternMatcher(const unsigned int mask) : mMask(mask)
16{
17}
18
Jamie Madill666f65a2016-08-26 01:34:37 +000019// static
20bool IntermNodePatternMatcher::IsDynamicIndexingOfVectorOrMatrix(TIntermBinary *node)
21{
22 return node->getOp() == EOpIndexIndirect && !node->getLeft()->isArray() &&
23 node->getLeft()->getBasicType() != EbtStruct;
24}
25
26bool IntermNodePatternMatcher::matchInternal(TIntermBinary *node, TIntermNode *parentNode)
Olli Etuaho00f6fbb2016-07-20 16:32:29 +030027{
28 if ((mMask & kExpressionReturningArray) != 0)
29 {
30 if (node->isArray() && node->getOp() == EOpAssign && parentNode != nullptr &&
Olli Etuaho6d40bbd2016-09-30 13:49:38 +010031 !parentNode->getAsBlock())
Olli Etuaho00f6fbb2016-07-20 16:32:29 +030032 {
33 return true;
34 }
35 }
36
37 if ((mMask & kUnfoldedShortCircuitExpression) != 0)
38 {
39 if (node->getRight()->hasSideEffects() &&
40 (node->getOp() == EOpLogicalOr || node->getOp() == EOpLogicalAnd))
41 {
42 return true;
43 }
44 }
45 return false;
46}
47
Jamie Madill666f65a2016-08-26 01:34:37 +000048bool IntermNodePatternMatcher::match(TIntermBinary *node, TIntermNode *parentNode)
49{
50 // L-value tracking information is needed to check for dynamic indexing in L-value.
51 // Traversers that don't track l-values can still use this class and match binary nodes with
52 // this variation of this method if they don't need to check for dynamic indexing in l-values.
53 ASSERT((mMask & kDynamicIndexingOfVectorOrMatrixInLValue) == 0);
54 return matchInternal(node, parentNode);
55}
56
57bool IntermNodePatternMatcher::match(TIntermBinary *node,
58 TIntermNode *parentNode,
59 bool isLValueRequiredHere)
60{
61 if (matchInternal(node, parentNode))
62 {
63 return true;
64 }
65 if ((mMask & kDynamicIndexingOfVectorOrMatrixInLValue) != 0)
66 {
67 if (isLValueRequiredHere && IsDynamicIndexingOfVectorOrMatrix(node))
68 {
69 return true;
70 }
71 }
72 return false;
73}
74
Olli Etuaho00f6fbb2016-07-20 16:32:29 +030075bool IntermNodePatternMatcher::match(TIntermAggregate *node, TIntermNode *parentNode)
76{
77 if ((mMask & kExpressionReturningArray) != 0)
78 {
79 if (parentNode != nullptr)
80 {
81 TIntermBinary *parentBinary = parentNode->getAsBinaryNode();
82 bool parentIsAssignment =
83 (parentBinary != nullptr &&
84 (parentBinary->getOp() == EOpAssign || parentBinary->getOp() == EOpInitialize));
85
86 if (node->getType().isArray() && !parentIsAssignment &&
87 (node->isConstructor() || node->getOp() == EOpFunctionCall) &&
Olli Etuaho6d40bbd2016-09-30 13:49:38 +010088 !parentNode->getAsBlock())
Olli Etuaho00f6fbb2016-07-20 16:32:29 +030089 {
90 return true;
91 }
92 }
93 }
94 return false;
95}
96
Olli Etuahod0bad2c2016-09-09 18:01:16 +030097bool IntermNodePatternMatcher::match(TIntermTernary *node)
Olli Etuaho00f6fbb2016-07-20 16:32:29 +030098{
99 if ((mMask & kUnfoldedShortCircuitExpression) != 0)
100 {
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300101 return true;
Olli Etuaho00f6fbb2016-07-20 16:32:29 +0300102 }
103 return false;
104}