blob: 4e2b8b5790e0803a5572c05c5954bae964104984 [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -04002// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7//
8// Build the intermediate representation.
9//
10
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000011#include <float.h>
alokp@chromium.org1bcc3fd2010-05-19 17:08:44 +000012#include <limits.h>
alokp@chromium.org32cfaf42010-08-23 21:01:13 +000013#include <algorithm>
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000014
Jamie Madillb1a85f42014-08-19 15:23:24 -040015#include "compiler/translator/Intermediate.h"
Geoff Lang17732822013-08-29 13:46:49 -040016#include "compiler/translator/SymbolTable.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000017
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000018////////////////////////////////////////////////////////////////////////////
19//
20// First set of functions are to help build the intermediate representation.
21// These functions are not member functions of the nodes.
22// They are called from parser productions.
23//
24/////////////////////////////////////////////////////////////////////////////
25
26//
27// Add a terminal node for an identifier in an expression.
28//
29// Returns the added node.
30//
Zhenyao Moe40d1e92014-07-16 17:40:36 -070031TIntermSymbol *TIntermediate::addSymbol(
32 int id, const TString &name, const TType &type, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000033{
Zhenyao Moe40d1e92014-07-16 17:40:36 -070034 TIntermSymbol *node = new TIntermSymbol(id, name, type);
alokp@chromium.org2cf17712010-03-30 20:33:18 +000035 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000036
alokp@chromium.org2cf17712010-03-30 20:33:18 +000037 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000038}
39
40//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000041// Connect two nodes through an index operator, where the left node is the base
42// of an array or struct, and the right node is a direct or indirect offset.
43//
44// Returns the added node.
45// The caller should set the type of the returned node.
46//
Olli Etuaho3272a6d2016-08-29 17:54:50 +030047TIntermTyped *TIntermediate::addIndex(TOperator op,
48 TIntermTyped *base,
49 TIntermTyped *index,
50 const TSourceLoc &line,
51 TDiagnostics *diagnostics)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000052{
Olli Etuaho3272a6d2016-08-29 17:54:50 +030053 TIntermBinary *node = new TIntermBinary(op, base, index);
alokp@chromium.org2cf17712010-03-30 20:33:18 +000054 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000055
Olli Etuaho3272a6d2016-08-29 17:54:50 +030056 TIntermTyped *folded = node->fold(diagnostics);
57 if (folded)
58 {
59 return folded;
60 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000061
alokp@chromium.org2cf17712010-03-30 20:33:18 +000062 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000063}
64
65//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000066// This is the safe way to change the operator on an aggregate, as it
67// does lots of error checking and fixing. Especially for establishing
68// a function call's operation on it's set of parameters. Sequences
69// of instructions are also aggregates, but they just direnctly set
70// their operator to EOpSequence.
71//
72// Returns an aggregate node, which could be the one passed in if
daniel@transgaming.com978702d2012-04-04 15:05:58 +000073// it was already an aggregate but no operator was set.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000074//
Zhenyao Moe40d1e92014-07-16 17:40:36 -070075TIntermAggregate *TIntermediate::setAggregateOperator(
76 TIntermNode *node, TOperator op, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000077{
Zhenyao Moe40d1e92014-07-16 17:40:36 -070078 TIntermAggregate *aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000079
alokp@chromium.org2cf17712010-03-30 20:33:18 +000080 //
81 // Make sure we have an aggregate. If not turn it into one.
82 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -070083 if (node)
84 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +000085 aggNode = node->getAsAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -070086 if (aggNode == NULL || aggNode->getOp() != EOpNull)
87 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +000088 //
89 // Make an aggregate containing this node.
90 //
91 aggNode = new TIntermAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -070092 aggNode->getSequence()->push_back(node);
alokp@chromium.org2cf17712010-03-30 20:33:18 +000093 }
Zhenyao Moe40d1e92014-07-16 17:40:36 -070094 }
95 else
96 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +000097 aggNode = new TIntermAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -070098 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000099
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000100 //
101 // Set the operator.
102 //
alokp@chromium.org58e54292010-08-24 21:40:03 +0000103 aggNode->setOp(op);
Jamie Madill075edd82013-07-08 13:30:19 -0400104 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000105
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000106 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000107}
108
109//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000110// Safe way to combine two nodes into an aggregate. Works with null pointers,
111// a node that's not a aggregate yet, etc.
112//
113// Returns the resulting aggregate, unless 0 was passed in for
114// both existing nodes.
115//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700116TIntermAggregate *TIntermediate::growAggregate(
117 TIntermNode *left, TIntermNode *right, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000118{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700119 if (left == NULL && right == NULL)
120 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000121
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700122 TIntermAggregate *aggNode = NULL;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000123 if (left)
124 aggNode = left->getAsAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700125 if (!aggNode || aggNode->getOp() != EOpNull)
126 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000127 aggNode = new TIntermAggregate;
128 if (left)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700129 aggNode->getSequence()->push_back(left);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000130 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000131
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000132 if (right)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700133 aggNode->getSequence()->push_back(right);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000134
Jamie Madill075edd82013-07-08 13:30:19 -0400135 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000136
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000137 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000138}
139
140//
141// Turn an existing node into an aggregate.
142//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700143// Returns an aggregate, unless NULL was passed in for the existing node.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000144//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700145TIntermAggregate *TIntermediate::makeAggregate(
146 TIntermNode *node, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000147{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700148 if (node == NULL)
149 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000150
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700151 TIntermAggregate *aggNode = new TIntermAggregate;
152 aggNode->getSequence()->push_back(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000153
Jamie Madill075edd82013-07-08 13:30:19 -0400154 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000155
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000156 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000157}
158
Olli Etuaho7d7f8c42015-05-19 18:38:49 +0300159// If the input node is nullptr, return nullptr.
160// If the input node is a sequence (block) node, return it.
161// If the input node is not a sequence node, put it inside a sequence node and return that.
162TIntermAggregate *TIntermediate::ensureSequence(TIntermNode *node)
163{
164 if (node == nullptr)
165 return nullptr;
166 TIntermAggregate *aggNode = node->getAsAggregate();
167 if (aggNode != nullptr && aggNode->getOp() == EOpSequence)
168 return aggNode;
169
170 aggNode = makeAggregate(node, node->getLine());
171 aggNode->setOp(EOpSequence);
172 return aggNode;
173}
174
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000175//
176// For "if" test nodes. There are three children; a condition,
177// a true path, and a false path. The two paths are in the
178// nodePair.
179//
180// Returns the selection node created.
181//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700182TIntermNode *TIntermediate::addSelection(
183 TIntermTyped *cond, TIntermNodePair nodePair, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000184{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000185 //
186 // For compile time constant selections, prune the code and
187 // test now.
188 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000189
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200190 if (cond->getAsConstantUnion())
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700191 {
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +0000192 if (cond->getAsConstantUnion()->getBConst(0) == true)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700193 {
194 return nodePair.node1 ? setAggregateOperator(
195 nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL;
196 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000197 else
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700198 {
199 return nodePair.node2 ? setAggregateOperator(
200 nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL;
201 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000202 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000203
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700204 TIntermSelection *node = new TIntermSelection(
Olli Etuaho7d7f8c42015-05-19 18:38:49 +0300205 cond, ensureSequence(nodePair.node1), ensureSequence(nodePair.node2));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000206 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000207
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000208 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000209}
210
Olli Etuaho15200042015-11-04 16:56:31 +0200211TIntermTyped *TIntermediate::addComma(TIntermTyped *left,
212 TIntermTyped *right,
213 const TSourceLoc &line,
214 int shaderVersion)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000215{
Olli Etuaho15200042015-11-04 16:56:31 +0200216 TQualifier resultQualifier = EvqConst;
217 // ESSL3.00 section 12.43: The result of a sequence operator is not a constant-expression.
218 if (shaderVersion >= 300 || left->getQualifier() != EvqConst ||
219 right->getQualifier() != EvqConst)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700220 {
Olli Etuaho15200042015-11-04 16:56:31 +0200221 resultQualifier = EvqTemporary;
222 }
223
224 TIntermTyped *commaNode = nullptr;
225 if (!left->hasSideEffects())
226 {
227 commaNode = right;
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700228 }
229 else
230 {
Olli Etuaho15200042015-11-04 16:56:31 +0200231 commaNode = growAggregate(left, right, line);
232 commaNode->getAsAggregate()->setOp(EOpComma);
233 commaNode->setType(right->getType());
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000234 }
Olli Etuaho15200042015-11-04 16:56:31 +0200235 commaNode->getTypePointer()->setQualifier(resultQualifier);
236 return commaNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000237}
238
239//
240// For "?:" test nodes. There are three children; a condition,
241// a true path, and a false path. The two paths are specified
242// as separate parameters.
243//
Olli Etuaho52901742015-04-15 13:42:45 +0300244// Returns the selection node created, or one of trueBlock and falseBlock if the expression could be folded.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000245//
Olli Etuaho52901742015-04-15 13:42:45 +0300246TIntermTyped *TIntermediate::addSelection(TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock,
247 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000248{
Olli Etuahob1edc4f2015-11-02 17:20:03 +0200249 TQualifier resultQualifier = EvqTemporary;
250 if (cond->getQualifier() == EvqConst && trueBlock->getQualifier() == EvqConst &&
251 falseBlock->getQualifier() == EvqConst)
252 {
253 resultQualifier = EvqConst;
254 }
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200255 // Note that the node resulting from here can be a constant union without being qualified as
256 // constant.
257 if (cond->getAsConstantUnion())
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700258 {
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +0000259 if (cond->getAsConstantUnion()->getBConst(0))
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200260 {
261 trueBlock->getTypePointer()->setQualifier(resultQualifier);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000262 return trueBlock;
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200263 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000264 else
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200265 {
266 falseBlock->getTypePointer()->setQualifier(resultQualifier);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000267 return falseBlock;
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200268 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000269 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000270
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000271 //
272 // Make a selection node.
273 //
Olli Etuaho52901742015-04-15 13:42:45 +0300274 TIntermSelection *node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
Olli Etuahob1edc4f2015-11-02 17:20:03 +0200275 node->getTypePointer()->setQualifier(resultQualifier);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000276 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000277
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000278 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000279}
280
Olli Etuahoa3a36662015-02-17 13:46:51 +0200281TIntermSwitch *TIntermediate::addSwitch(
282 TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &line)
283{
Olli Etuaho3c1dfb52015-02-20 11:34:03 +0200284 TIntermSwitch *node = new TIntermSwitch(init, statementList);
285 node->setLine(line);
286
287 return node;
Olli Etuahoa3a36662015-02-17 13:46:51 +0200288}
289
290TIntermCase *TIntermediate::addCase(
291 TIntermTyped *condition, const TSourceLoc &line)
292{
Olli Etuaho3c1dfb52015-02-20 11:34:03 +0200293 TIntermCase *node = new TIntermCase(condition);
294 node->setLine(line);
295
296 return node;
Olli Etuahoa3a36662015-02-17 13:46:51 +0200297}
298
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000299//
300// Constant terminal nodes. Has a union that contains bool, float or int constants
301//
302// Returns the constant union node created.
303//
304
Olli Etuaho5c0e0232015-11-11 15:55:59 +0200305TIntermConstantUnion *TIntermediate::addConstantUnion(const TConstantUnion *constantUnion,
306 const TType &type,
307 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000308{
Jamie Madillb11e2482015-05-04 14:21:22 -0400309 TIntermConstantUnion *node = new TIntermConstantUnion(constantUnion, type);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000310 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000311
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000312 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000313}
314
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700315TIntermTyped *TIntermediate::addSwizzle(
316 TVectorFields &fields, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000317{
318
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700319 TIntermAggregate *node = new TIntermAggregate(EOpSequence);
Olli Etuaho3272a6d2016-08-29 17:54:50 +0300320 node->getTypePointer()->setQualifier(EvqConst);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000321
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000322 node->setLine(line);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700323 TIntermConstantUnion *constIntNode;
324 TIntermSequence *sequenceVector = node->getSequence();
Jamie Madill6ba6ead2015-05-04 14:21:21 -0400325 TConstantUnion *unionArray;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000326
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700327 for (int i = 0; i < fields.num; i++)
328 {
Jamie Madill6ba6ead2015-05-04 14:21:21 -0400329 unionArray = new TConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000330 unionArray->setIConst(fields.offsets[i]);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700331 constIntNode = addConstantUnion(
332 unionArray, TType(EbtInt, EbpUndefined, EvqConst), line);
333 sequenceVector->push_back(constIntNode);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000334 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000335
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000336 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000337}
338
339//
340// Create loop nodes.
341//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700342TIntermNode *TIntermediate::addLoop(
343 TLoopType type, TIntermNode *init, TIntermTyped *cond, TIntermTyped *expr,
344 TIntermNode *body, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000345{
Olli Etuaho7d7f8c42015-05-19 18:38:49 +0300346 TIntermNode *node = new TIntermLoop(type, init, cond, expr, ensureSequence(body));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000347 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000348
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000349 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000350}
351
352//
353// Add branches.
354//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700355TIntermBranch* TIntermediate::addBranch(
356 TOperator branchOp, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000357{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000358 return addBranch(branchOp, 0, line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000359}
360
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700361TIntermBranch* TIntermediate::addBranch(
362 TOperator branchOp, TIntermTyped *expression, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000363{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700364 TIntermBranch *node = new TIntermBranch(branchOp, expression);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000365 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000366
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000367 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000368}
369
370//
371// This is to be executed once the final root is put on top by the parsing
372// process.
373//
Olli Etuahof119a262016-08-19 15:54:22 +0300374TIntermAggregate *TIntermediate::PostProcess(TIntermNode *root)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000375{
Olli Etuaho43613b02015-08-04 11:02:21 +0300376 if (root == nullptr)
377 return nullptr;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000378
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000379 //
Olli Etuaho43613b02015-08-04 11:02:21 +0300380 // Finish off the top level sequence, if any
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000381 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700382 TIntermAggregate *aggRoot = root->getAsAggregate();
Olli Etuaho43613b02015-08-04 11:02:21 +0300383 if (aggRoot != nullptr && aggRoot->getOp() == EOpNull)
384 {
alokp@chromium.org58e54292010-08-24 21:40:03 +0000385 aggRoot->setOp(EOpSequence);
Olli Etuaho43613b02015-08-04 11:02:21 +0300386 }
387 else if (aggRoot == nullptr || aggRoot->getOp() != EOpSequence)
388 {
389 aggRoot = new TIntermAggregate(EOpSequence);
390 aggRoot->setLine(root->getLine());
391 aggRoot->getSequence()->push_back(root);
392 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000393
Olli Etuaho43613b02015-08-04 11:02:21 +0300394 return aggRoot;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000395}
Arun Patole274f0702015-05-05 13:33:30 +0530396
Olli Etuahof119a262016-08-19 15:54:22 +0300397TIntermTyped *TIntermediate::foldAggregateBuiltIn(TIntermAggregate *aggregate,
398 TDiagnostics *diagnostics)
Arun Patole274f0702015-05-05 13:33:30 +0530399{
Olli Etuahob43846e2015-06-02 18:18:57 +0300400 switch (aggregate->getOp())
Arun Patole274f0702015-05-05 13:33:30 +0530401 {
Olli Etuaho1d122782015-11-06 15:35:17 +0200402 case EOpAtan:
403 case EOpPow:
404 case EOpMod:
405 case EOpMin:
406 case EOpMax:
407 case EOpClamp:
408 case EOpMix:
409 case EOpStep:
410 case EOpSmoothStep:
411 case EOpMul:
412 case EOpOuterProduct:
413 case EOpLessThan:
414 case EOpLessThanEqual:
415 case EOpGreaterThan:
416 case EOpGreaterThanEqual:
417 case EOpVectorEqual:
418 case EOpVectorNotEqual:
419 case EOpDistance:
420 case EOpDot:
421 case EOpCross:
422 case EOpFaceForward:
423 case EOpReflect:
424 case EOpRefract:
Olli Etuahof119a262016-08-19 15:54:22 +0300425 return aggregate->fold(diagnostics);
Olli Etuaho1d122782015-11-06 15:35:17 +0200426 default:
427 // TODO: Add support for folding array constructors
428 if (aggregate->isConstructor() && !aggregate->isArray())
429 {
Olli Etuahof119a262016-08-19 15:54:22 +0300430 return aggregate->fold(diagnostics);
Olli Etuaho1d122782015-11-06 15:35:17 +0200431 }
432 // Constant folding not supported for the built-in.
433 return nullptr;
Arun Patole274f0702015-05-05 13:33:30 +0530434 }
Arun Patole274f0702015-05-05 13:33:30 +0530435}