blob: b7479456ad4aeda2f319c1493d7af46f6acc5782 [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//
Zhenyao Moe40d1e92014-07-16 17:40:36 -070047TIntermTyped *TIntermediate::addIndex(
48 TOperator op, TIntermTyped *base, TIntermTyped *index, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000049{
Zhenyao Moe40d1e92014-07-16 17:40:36 -070050 TIntermBinary *node = new TIntermBinary(op);
alokp@chromium.org2cf17712010-03-30 20:33:18 +000051 node->setLine(line);
52 node->setLeft(base);
53 node->setRight(index);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000054
alokp@chromium.org2cf17712010-03-30 20:33:18 +000055 // caller should set the type
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000056
alokp@chromium.org2cf17712010-03-30 20:33:18 +000057 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000058}
59
60//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000061// This is the safe way to change the operator on an aggregate, as it
62// does lots of error checking and fixing. Especially for establishing
63// a function call's operation on it's set of parameters. Sequences
64// of instructions are also aggregates, but they just direnctly set
65// their operator to EOpSequence.
66//
67// Returns an aggregate node, which could be the one passed in if
daniel@transgaming.com978702d2012-04-04 15:05:58 +000068// it was already an aggregate but no operator was set.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000069//
Zhenyao Moe40d1e92014-07-16 17:40:36 -070070TIntermAggregate *TIntermediate::setAggregateOperator(
71 TIntermNode *node, TOperator op, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000072{
Zhenyao Moe40d1e92014-07-16 17:40:36 -070073 TIntermAggregate *aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000074
alokp@chromium.org2cf17712010-03-30 20:33:18 +000075 //
76 // Make sure we have an aggregate. If not turn it into one.
77 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -070078 if (node)
79 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +000080 aggNode = node->getAsAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -070081 if (aggNode == NULL || aggNode->getOp() != EOpNull)
82 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +000083 //
84 // Make an aggregate containing this node.
85 //
86 aggNode = new TIntermAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -070087 aggNode->getSequence()->push_back(node);
alokp@chromium.org2cf17712010-03-30 20:33:18 +000088 }
Zhenyao Moe40d1e92014-07-16 17:40:36 -070089 }
90 else
91 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +000092 aggNode = new TIntermAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -070093 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000094
alokp@chromium.org2cf17712010-03-30 20:33:18 +000095 //
96 // Set the operator.
97 //
alokp@chromium.org58e54292010-08-24 21:40:03 +000098 aggNode->setOp(op);
Jamie Madill075edd82013-07-08 13:30:19 -040099 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000100
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000101 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000102}
103
104//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000105// Safe way to combine two nodes into an aggregate. Works with null pointers,
106// a node that's not a aggregate yet, etc.
107//
108// Returns the resulting aggregate, unless 0 was passed in for
109// both existing nodes.
110//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700111TIntermAggregate *TIntermediate::growAggregate(
112 TIntermNode *left, TIntermNode *right, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000113{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700114 if (left == NULL && right == NULL)
115 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000116
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700117 TIntermAggregate *aggNode = NULL;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000118 if (left)
119 aggNode = left->getAsAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700120 if (!aggNode || aggNode->getOp() != EOpNull)
121 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000122 aggNode = new TIntermAggregate;
123 if (left)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700124 aggNode->getSequence()->push_back(left);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000125 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000126
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000127 if (right)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700128 aggNode->getSequence()->push_back(right);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000129
Jamie Madill075edd82013-07-08 13:30:19 -0400130 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000131
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000132 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000133}
134
135//
136// Turn an existing node into an aggregate.
137//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700138// Returns an aggregate, unless NULL was passed in for the existing node.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000139//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700140TIntermAggregate *TIntermediate::makeAggregate(
141 TIntermNode *node, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000142{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700143 if (node == NULL)
144 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000145
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700146 TIntermAggregate *aggNode = new TIntermAggregate;
147 aggNode->getSequence()->push_back(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000148
Jamie Madill075edd82013-07-08 13:30:19 -0400149 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000150
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000151 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000152}
153
Olli Etuaho7d7f8c42015-05-19 18:38:49 +0300154// If the input node is nullptr, return nullptr.
155// If the input node is a sequence (block) node, return it.
156// If the input node is not a sequence node, put it inside a sequence node and return that.
157TIntermAggregate *TIntermediate::ensureSequence(TIntermNode *node)
158{
159 if (node == nullptr)
160 return nullptr;
161 TIntermAggregate *aggNode = node->getAsAggregate();
162 if (aggNode != nullptr && aggNode->getOp() == EOpSequence)
163 return aggNode;
164
165 aggNode = makeAggregate(node, node->getLine());
166 aggNode->setOp(EOpSequence);
167 return aggNode;
168}
169
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000170//
171// For "if" test nodes. There are three children; a condition,
172// a true path, and a false path. The two paths are in the
173// nodePair.
174//
175// Returns the selection node created.
176//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700177TIntermNode *TIntermediate::addSelection(
178 TIntermTyped *cond, TIntermNodePair nodePair, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000179{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000180 //
181 // For compile time constant selections, prune the code and
182 // test now.
183 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000184
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200185 if (cond->getAsConstantUnion())
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700186 {
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +0000187 if (cond->getAsConstantUnion()->getBConst(0) == true)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700188 {
189 return nodePair.node1 ? setAggregateOperator(
190 nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL;
191 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000192 else
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700193 {
194 return nodePair.node2 ? setAggregateOperator(
195 nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL;
196 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000197 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000198
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700199 TIntermSelection *node = new TIntermSelection(
Olli Etuaho7d7f8c42015-05-19 18:38:49 +0300200 cond, ensureSequence(nodePair.node1), ensureSequence(nodePair.node2));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000201 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000202
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000203 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000204}
205
Olli Etuaho15200042015-11-04 16:56:31 +0200206TIntermTyped *TIntermediate::addComma(TIntermTyped *left,
207 TIntermTyped *right,
208 const TSourceLoc &line,
209 int shaderVersion)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000210{
Olli Etuaho15200042015-11-04 16:56:31 +0200211 TQualifier resultQualifier = EvqConst;
212 // ESSL3.00 section 12.43: The result of a sequence operator is not a constant-expression.
213 if (shaderVersion >= 300 || left->getQualifier() != EvqConst ||
214 right->getQualifier() != EvqConst)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700215 {
Olli Etuaho15200042015-11-04 16:56:31 +0200216 resultQualifier = EvqTemporary;
217 }
218
219 TIntermTyped *commaNode = nullptr;
220 if (!left->hasSideEffects())
221 {
222 commaNode = right;
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700223 }
224 else
225 {
Olli Etuaho15200042015-11-04 16:56:31 +0200226 commaNode = growAggregate(left, right, line);
227 commaNode->getAsAggregate()->setOp(EOpComma);
228 commaNode->setType(right->getType());
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000229 }
Olli Etuaho15200042015-11-04 16:56:31 +0200230 commaNode->getTypePointer()->setQualifier(resultQualifier);
231 return commaNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000232}
233
234//
235// For "?:" test nodes. There are three children; a condition,
236// a true path, and a false path. The two paths are specified
237// as separate parameters.
238//
Olli Etuaho52901742015-04-15 13:42:45 +0300239// 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 +0000240//
Olli Etuaho52901742015-04-15 13:42:45 +0300241TIntermTyped *TIntermediate::addSelection(TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock,
242 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000243{
Olli Etuahob1edc4f2015-11-02 17:20:03 +0200244 TQualifier resultQualifier = EvqTemporary;
245 if (cond->getQualifier() == EvqConst && trueBlock->getQualifier() == EvqConst &&
246 falseBlock->getQualifier() == EvqConst)
247 {
248 resultQualifier = EvqConst;
249 }
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200250 // Note that the node resulting from here can be a constant union without being qualified as
251 // constant.
252 if (cond->getAsConstantUnion())
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700253 {
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +0000254 if (cond->getAsConstantUnion()->getBConst(0))
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200255 {
256 trueBlock->getTypePointer()->setQualifier(resultQualifier);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000257 return trueBlock;
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200258 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000259 else
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200260 {
261 falseBlock->getTypePointer()->setQualifier(resultQualifier);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000262 return falseBlock;
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200263 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000264 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000265
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000266 //
267 // Make a selection node.
268 //
Olli Etuaho52901742015-04-15 13:42:45 +0300269 TIntermSelection *node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
Olli Etuahob1edc4f2015-11-02 17:20:03 +0200270 node->getTypePointer()->setQualifier(resultQualifier);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000271 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000272
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000273 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000274}
275
Olli Etuahoa3a36662015-02-17 13:46:51 +0200276TIntermSwitch *TIntermediate::addSwitch(
277 TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &line)
278{
Olli Etuaho3c1dfb52015-02-20 11:34:03 +0200279 TIntermSwitch *node = new TIntermSwitch(init, statementList);
280 node->setLine(line);
281
282 return node;
Olli Etuahoa3a36662015-02-17 13:46:51 +0200283}
284
285TIntermCase *TIntermediate::addCase(
286 TIntermTyped *condition, const TSourceLoc &line)
287{
Olli Etuaho3c1dfb52015-02-20 11:34:03 +0200288 TIntermCase *node = new TIntermCase(condition);
289 node->setLine(line);
290
291 return node;
Olli Etuahoa3a36662015-02-17 13:46:51 +0200292}
293
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000294//
295// Constant terminal nodes. Has a union that contains bool, float or int constants
296//
297// Returns the constant union node created.
298//
299
Olli Etuaho5c0e0232015-11-11 15:55:59 +0200300TIntermConstantUnion *TIntermediate::addConstantUnion(const TConstantUnion *constantUnion,
301 const TType &type,
302 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000303{
Jamie Madillb11e2482015-05-04 14:21:22 -0400304 TIntermConstantUnion *node = new TIntermConstantUnion(constantUnion, type);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000305 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000306
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000307 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000308}
309
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700310TIntermTyped *TIntermediate::addSwizzle(
311 TVectorFields &fields, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000312{
313
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700314 TIntermAggregate *node = new TIntermAggregate(EOpSequence);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000315
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000316 node->setLine(line);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700317 TIntermConstantUnion *constIntNode;
318 TIntermSequence *sequenceVector = node->getSequence();
Jamie Madill6ba6ead2015-05-04 14:21:21 -0400319 TConstantUnion *unionArray;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000320
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700321 for (int i = 0; i < fields.num; i++)
322 {
Jamie Madill6ba6ead2015-05-04 14:21:21 -0400323 unionArray = new TConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000324 unionArray->setIConst(fields.offsets[i]);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700325 constIntNode = addConstantUnion(
326 unionArray, TType(EbtInt, EbpUndefined, EvqConst), line);
327 sequenceVector->push_back(constIntNode);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000328 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000329
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000330 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000331}
332
333//
334// Create loop nodes.
335//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700336TIntermNode *TIntermediate::addLoop(
337 TLoopType type, TIntermNode *init, TIntermTyped *cond, TIntermTyped *expr,
338 TIntermNode *body, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000339{
Olli Etuaho7d7f8c42015-05-19 18:38:49 +0300340 TIntermNode *node = new TIntermLoop(type, init, cond, expr, ensureSequence(body));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000341 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000342
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000343 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000344}
345
346//
347// Add branches.
348//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700349TIntermBranch* TIntermediate::addBranch(
350 TOperator branchOp, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000351{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000352 return addBranch(branchOp, 0, line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000353}
354
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700355TIntermBranch* TIntermediate::addBranch(
356 TOperator branchOp, TIntermTyped *expression, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000357{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700358 TIntermBranch *node = new TIntermBranch(branchOp, expression);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000359 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000360
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000361 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000362}
363
364//
365// This is to be executed once the final root is put on top by the parsing
366// process.
367//
Olli Etuahof119a262016-08-19 15:54:22 +0300368TIntermAggregate *TIntermediate::PostProcess(TIntermNode *root)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000369{
Olli Etuaho43613b02015-08-04 11:02:21 +0300370 if (root == nullptr)
371 return nullptr;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000372
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000373 //
Olli Etuaho43613b02015-08-04 11:02:21 +0300374 // Finish off the top level sequence, if any
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000375 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700376 TIntermAggregate *aggRoot = root->getAsAggregate();
Olli Etuaho43613b02015-08-04 11:02:21 +0300377 if (aggRoot != nullptr && aggRoot->getOp() == EOpNull)
378 {
alokp@chromium.org58e54292010-08-24 21:40:03 +0000379 aggRoot->setOp(EOpSequence);
Olli Etuaho43613b02015-08-04 11:02:21 +0300380 }
381 else if (aggRoot == nullptr || aggRoot->getOp() != EOpSequence)
382 {
383 aggRoot = new TIntermAggregate(EOpSequence);
384 aggRoot->setLine(root->getLine());
385 aggRoot->getSequence()->push_back(root);
386 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000387
Olli Etuaho43613b02015-08-04 11:02:21 +0300388 return aggRoot;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000389}
Arun Patole274f0702015-05-05 13:33:30 +0530390
Olli Etuahof119a262016-08-19 15:54:22 +0300391TIntermTyped *TIntermediate::foldAggregateBuiltIn(TIntermAggregate *aggregate,
392 TDiagnostics *diagnostics)
Arun Patole274f0702015-05-05 13:33:30 +0530393{
Olli Etuahob43846e2015-06-02 18:18:57 +0300394 switch (aggregate->getOp())
Arun Patole274f0702015-05-05 13:33:30 +0530395 {
Olli Etuaho1d122782015-11-06 15:35:17 +0200396 case EOpAtan:
397 case EOpPow:
398 case EOpMod:
399 case EOpMin:
400 case EOpMax:
401 case EOpClamp:
402 case EOpMix:
403 case EOpStep:
404 case EOpSmoothStep:
405 case EOpMul:
406 case EOpOuterProduct:
407 case EOpLessThan:
408 case EOpLessThanEqual:
409 case EOpGreaterThan:
410 case EOpGreaterThanEqual:
411 case EOpVectorEqual:
412 case EOpVectorNotEqual:
413 case EOpDistance:
414 case EOpDot:
415 case EOpCross:
416 case EOpFaceForward:
417 case EOpReflect:
418 case EOpRefract:
Olli Etuahof119a262016-08-19 15:54:22 +0300419 return aggregate->fold(diagnostics);
Olli Etuaho1d122782015-11-06 15:35:17 +0200420 default:
421 // TODO: Add support for folding array constructors
422 if (aggregate->isConstructor() && !aggregate->isArray())
423 {
Olli Etuahof119a262016-08-19 15:54:22 +0300424 return aggregate->fold(diagnostics);
Olli Etuaho1d122782015-11-06 15:35:17 +0200425 }
426 // Constant folding not supported for the built-in.
427 return nullptr;
Arun Patole274f0702015-05-05 13:33:30 +0530428 }
Arun Patole274f0702015-05-05 13:33:30 +0530429}