blob: b6fefa45e6f7394594a8239ed050579ed0f413f0 [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//
61// Add one node as the parent of another that it operates on.
62//
63// Returns the added node.
64//
Zhenyao Moe40d1e92014-07-16 17:40:36 -070065TIntermTyped *TIntermediate::addUnaryMath(
Olli Etuahof6c694b2015-03-26 14:50:53 +020066 TOperator op, TIntermTyped *child, const TSourceLoc &line, const TType *funcReturnType)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000067{
alokp@chromium.org2cf17712010-03-30 20:33:18 +000068 //
69 // Make a new node for the operator.
70 //
Olli Etuaho69c11b52015-03-26 12:59:00 +020071 TIntermUnary *node = new TIntermUnary(op);
alokp@chromium.org2cf17712010-03-30 20:33:18 +000072 node->setLine(line);
73 node->setOperand(child);
Olli Etuahof6c694b2015-03-26 14:50:53 +020074 node->promote(funcReturnType);
Olli Etuaho7700ff62015-01-15 12:16:29 +020075
Olli Etuaho95310b02015-06-02 17:43:38 +030076 TIntermTyped *foldedNode = node->fold(mInfoSink);
77 if (foldedNode)
78 return foldedNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000079
alokp@chromium.org2cf17712010-03-30 20:33:18 +000080 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000081}
82
83//
84// This is the safe way to change the operator on an aggregate, as it
85// does lots of error checking and fixing. Especially for establishing
86// a function call's operation on it's set of parameters. Sequences
87// of instructions are also aggregates, but they just direnctly set
88// their operator to EOpSequence.
89//
90// Returns an aggregate node, which could be the one passed in if
daniel@transgaming.com978702d2012-04-04 15:05:58 +000091// it was already an aggregate but no operator was set.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000092//
Zhenyao Moe40d1e92014-07-16 17:40:36 -070093TIntermAggregate *TIntermediate::setAggregateOperator(
94 TIntermNode *node, TOperator op, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000095{
Zhenyao Moe40d1e92014-07-16 17:40:36 -070096 TIntermAggregate *aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000097
alokp@chromium.org2cf17712010-03-30 20:33:18 +000098 //
99 // Make sure we have an aggregate. If not turn it into one.
100 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700101 if (node)
102 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000103 aggNode = node->getAsAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700104 if (aggNode == NULL || aggNode->getOp() != EOpNull)
105 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000106 //
107 // Make an aggregate containing this node.
108 //
109 aggNode = new TIntermAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700110 aggNode->getSequence()->push_back(node);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000111 }
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700112 }
113 else
114 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000115 aggNode = new TIntermAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700116 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000117
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000118 //
119 // Set the operator.
120 //
alokp@chromium.org58e54292010-08-24 21:40:03 +0000121 aggNode->setOp(op);
Jamie Madill075edd82013-07-08 13:30:19 -0400122 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000123
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000124 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000125}
126
127//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000128// Safe way to combine two nodes into an aggregate. Works with null pointers,
129// a node that's not a aggregate yet, etc.
130//
131// Returns the resulting aggregate, unless 0 was passed in for
132// both existing nodes.
133//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700134TIntermAggregate *TIntermediate::growAggregate(
135 TIntermNode *left, TIntermNode *right, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000136{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700137 if (left == NULL && right == NULL)
138 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000139
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700140 TIntermAggregate *aggNode = NULL;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000141 if (left)
142 aggNode = left->getAsAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700143 if (!aggNode || aggNode->getOp() != EOpNull)
144 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000145 aggNode = new TIntermAggregate;
146 if (left)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700147 aggNode->getSequence()->push_back(left);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000148 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000149
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000150 if (right)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700151 aggNode->getSequence()->push_back(right);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000152
Jamie Madill075edd82013-07-08 13:30:19 -0400153 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000154
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000155 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000156}
157
158//
159// Turn an existing node into an aggregate.
160//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700161// Returns an aggregate, unless NULL was passed in for the existing node.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000162//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700163TIntermAggregate *TIntermediate::makeAggregate(
164 TIntermNode *node, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000165{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700166 if (node == NULL)
167 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000168
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700169 TIntermAggregate *aggNode = new TIntermAggregate;
170 aggNode->getSequence()->push_back(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000171
Jamie Madill075edd82013-07-08 13:30:19 -0400172 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000173
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000174 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000175}
176
Olli Etuaho7d7f8c42015-05-19 18:38:49 +0300177// If the input node is nullptr, return nullptr.
178// If the input node is a sequence (block) node, return it.
179// If the input node is not a sequence node, put it inside a sequence node and return that.
180TIntermAggregate *TIntermediate::ensureSequence(TIntermNode *node)
181{
182 if (node == nullptr)
183 return nullptr;
184 TIntermAggregate *aggNode = node->getAsAggregate();
185 if (aggNode != nullptr && aggNode->getOp() == EOpSequence)
186 return aggNode;
187
188 aggNode = makeAggregate(node, node->getLine());
189 aggNode->setOp(EOpSequence);
190 return aggNode;
191}
192
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000193//
194// For "if" test nodes. There are three children; a condition,
195// a true path, and a false path. The two paths are in the
196// nodePair.
197//
198// Returns the selection node created.
199//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700200TIntermNode *TIntermediate::addSelection(
201 TIntermTyped *cond, TIntermNodePair nodePair, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000202{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000203 //
204 // For compile time constant selections, prune the code and
205 // test now.
206 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000207
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200208 if (cond->getAsConstantUnion())
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700209 {
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +0000210 if (cond->getAsConstantUnion()->getBConst(0) == true)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700211 {
212 return nodePair.node1 ? setAggregateOperator(
213 nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL;
214 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000215 else
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700216 {
217 return nodePair.node2 ? setAggregateOperator(
218 nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL;
219 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000220 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000221
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700222 TIntermSelection *node = new TIntermSelection(
Olli Etuaho7d7f8c42015-05-19 18:38:49 +0300223 cond, ensureSequence(nodePair.node1), ensureSequence(nodePair.node2));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000224 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000225
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000226 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000227}
228
Olli Etuaho15200042015-11-04 16:56:31 +0200229TIntermTyped *TIntermediate::addComma(TIntermTyped *left,
230 TIntermTyped *right,
231 const TSourceLoc &line,
232 int shaderVersion)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000233{
Olli Etuaho15200042015-11-04 16:56:31 +0200234 TQualifier resultQualifier = EvqConst;
235 // ESSL3.00 section 12.43: The result of a sequence operator is not a constant-expression.
236 if (shaderVersion >= 300 || left->getQualifier() != EvqConst ||
237 right->getQualifier() != EvqConst)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700238 {
Olli Etuaho15200042015-11-04 16:56:31 +0200239 resultQualifier = EvqTemporary;
240 }
241
242 TIntermTyped *commaNode = nullptr;
243 if (!left->hasSideEffects())
244 {
245 commaNode = right;
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700246 }
247 else
248 {
Olli Etuaho15200042015-11-04 16:56:31 +0200249 commaNode = growAggregate(left, right, line);
250 commaNode->getAsAggregate()->setOp(EOpComma);
251 commaNode->setType(right->getType());
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000252 }
Olli Etuaho15200042015-11-04 16:56:31 +0200253 commaNode->getTypePointer()->setQualifier(resultQualifier);
254 return commaNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000255}
256
257//
258// For "?:" test nodes. There are three children; a condition,
259// a true path, and a false path. The two paths are specified
260// as separate parameters.
261//
Olli Etuaho52901742015-04-15 13:42:45 +0300262// 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 +0000263//
Olli Etuaho52901742015-04-15 13:42:45 +0300264TIntermTyped *TIntermediate::addSelection(TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock,
265 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000266{
Olli Etuahob1edc4f2015-11-02 17:20:03 +0200267 TQualifier resultQualifier = EvqTemporary;
268 if (cond->getQualifier() == EvqConst && trueBlock->getQualifier() == EvqConst &&
269 falseBlock->getQualifier() == EvqConst)
270 {
271 resultQualifier = EvqConst;
272 }
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200273 // Note that the node resulting from here can be a constant union without being qualified as
274 // constant.
275 if (cond->getAsConstantUnion())
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700276 {
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +0000277 if (cond->getAsConstantUnion()->getBConst(0))
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200278 {
279 trueBlock->getTypePointer()->setQualifier(resultQualifier);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000280 return trueBlock;
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200281 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000282 else
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200283 {
284 falseBlock->getTypePointer()->setQualifier(resultQualifier);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000285 return falseBlock;
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200286 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000287 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000288
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000289 //
290 // Make a selection node.
291 //
Olli Etuaho52901742015-04-15 13:42:45 +0300292 TIntermSelection *node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
Olli Etuahob1edc4f2015-11-02 17:20:03 +0200293 node->getTypePointer()->setQualifier(resultQualifier);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000294 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000295
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000296 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000297}
298
Olli Etuahoa3a36662015-02-17 13:46:51 +0200299TIntermSwitch *TIntermediate::addSwitch(
300 TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &line)
301{
Olli Etuaho3c1dfb52015-02-20 11:34:03 +0200302 TIntermSwitch *node = new TIntermSwitch(init, statementList);
303 node->setLine(line);
304
305 return node;
Olli Etuahoa3a36662015-02-17 13:46:51 +0200306}
307
308TIntermCase *TIntermediate::addCase(
309 TIntermTyped *condition, const TSourceLoc &line)
310{
Olli Etuaho3c1dfb52015-02-20 11:34:03 +0200311 TIntermCase *node = new TIntermCase(condition);
312 node->setLine(line);
313
314 return node;
Olli Etuahoa3a36662015-02-17 13:46:51 +0200315}
316
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000317//
318// Constant terminal nodes. Has a union that contains bool, float or int constants
319//
320// Returns the constant union node created.
321//
322
Olli Etuaho5c0e0232015-11-11 15:55:59 +0200323TIntermConstantUnion *TIntermediate::addConstantUnion(const TConstantUnion *constantUnion,
324 const TType &type,
325 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000326{
Jamie Madillb11e2482015-05-04 14:21:22 -0400327 TIntermConstantUnion *node = new TIntermConstantUnion(constantUnion, type);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000328 node->setLine(line);
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
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700333TIntermTyped *TIntermediate::addSwizzle(
334 TVectorFields &fields, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000335{
336
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700337 TIntermAggregate *node = new TIntermAggregate(EOpSequence);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000338
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000339 node->setLine(line);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700340 TIntermConstantUnion *constIntNode;
341 TIntermSequence *sequenceVector = node->getSequence();
Jamie Madill6ba6ead2015-05-04 14:21:21 -0400342 TConstantUnion *unionArray;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000343
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700344 for (int i = 0; i < fields.num; i++)
345 {
Jamie Madill6ba6ead2015-05-04 14:21:21 -0400346 unionArray = new TConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000347 unionArray->setIConst(fields.offsets[i]);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700348 constIntNode = addConstantUnion(
349 unionArray, TType(EbtInt, EbpUndefined, EvqConst), line);
350 sequenceVector->push_back(constIntNode);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000351 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000352
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000353 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000354}
355
356//
357// Create loop nodes.
358//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700359TIntermNode *TIntermediate::addLoop(
360 TLoopType type, TIntermNode *init, TIntermTyped *cond, TIntermTyped *expr,
361 TIntermNode *body, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000362{
Olli Etuaho7d7f8c42015-05-19 18:38:49 +0300363 TIntermNode *node = new TIntermLoop(type, init, cond, expr, ensureSequence(body));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000364 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000365
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000366 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000367}
368
369//
370// Add branches.
371//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700372TIntermBranch* TIntermediate::addBranch(
373 TOperator branchOp, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000374{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000375 return addBranch(branchOp, 0, line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000376}
377
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700378TIntermBranch* TIntermediate::addBranch(
379 TOperator branchOp, TIntermTyped *expression, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000380{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700381 TIntermBranch *node = new TIntermBranch(branchOp, expression);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000382 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000383
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000384 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000385}
386
387//
388// This is to be executed once the final root is put on top by the parsing
389// process.
390//
Olli Etuaho43613b02015-08-04 11:02:21 +0300391TIntermAggregate *TIntermediate::postProcess(TIntermNode *root)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000392{
Olli Etuaho43613b02015-08-04 11:02:21 +0300393 if (root == nullptr)
394 return nullptr;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000395
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000396 //
Olli Etuaho43613b02015-08-04 11:02:21 +0300397 // Finish off the top level sequence, if any
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000398 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700399 TIntermAggregate *aggRoot = root->getAsAggregate();
Olli Etuaho43613b02015-08-04 11:02:21 +0300400 if (aggRoot != nullptr && aggRoot->getOp() == EOpNull)
401 {
alokp@chromium.org58e54292010-08-24 21:40:03 +0000402 aggRoot->setOp(EOpSequence);
Olli Etuaho43613b02015-08-04 11:02:21 +0300403 }
404 else if (aggRoot == nullptr || aggRoot->getOp() != EOpSequence)
405 {
406 aggRoot = new TIntermAggregate(EOpSequence);
407 aggRoot->setLine(root->getLine());
408 aggRoot->getSequence()->push_back(root);
409 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000410
Olli Etuaho43613b02015-08-04 11:02:21 +0300411 return aggRoot;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000412}
Arun Patole274f0702015-05-05 13:33:30 +0530413
Olli Etuahob43846e2015-06-02 18:18:57 +0300414TIntermTyped *TIntermediate::foldAggregateBuiltIn(TIntermAggregate *aggregate)
Arun Patole274f0702015-05-05 13:33:30 +0530415{
Olli Etuahob43846e2015-06-02 18:18:57 +0300416 switch (aggregate->getOp())
Arun Patole274f0702015-05-05 13:33:30 +0530417 {
Olli Etuaho1d122782015-11-06 15:35:17 +0200418 case EOpAtan:
419 case EOpPow:
420 case EOpMod:
421 case EOpMin:
422 case EOpMax:
423 case EOpClamp:
424 case EOpMix:
425 case EOpStep:
426 case EOpSmoothStep:
427 case EOpMul:
428 case EOpOuterProduct:
429 case EOpLessThan:
430 case EOpLessThanEqual:
431 case EOpGreaterThan:
432 case EOpGreaterThanEqual:
433 case EOpVectorEqual:
434 case EOpVectorNotEqual:
435 case EOpDistance:
436 case EOpDot:
437 case EOpCross:
438 case EOpFaceForward:
439 case EOpReflect:
440 case EOpRefract:
441 return aggregate->fold(mInfoSink);
442 default:
443 // TODO: Add support for folding array constructors
444 if (aggregate->isConstructor() && !aggregate->isArray())
445 {
446 return aggregate->fold(mInfoSink);
447 }
448 // Constant folding not supported for the built-in.
449 return nullptr;
Arun Patole274f0702015-05-05 13:33:30 +0530450 }
Arun Patole274f0702015-05-05 13:33:30 +0530451}