blob: dca11776ea66de69e06ce289c6fdd251c9493a57 [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//
41// Connect two nodes with a new parent that does a binary operation on the nodes.
42//
43// Returns the added node.
44//
Zhenyao Moe40d1e92014-07-16 17:40:36 -070045TIntermTyped *TIntermediate::addBinaryMath(
46 TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000047{
alokp@chromium.org2cf17712010-03-30 20:33:18 +000048 //
49 // Need a new node holding things together then. Make
50 // one and promote it to the right type.
51 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -070052 TIntermBinary *node = new TIntermBinary(op);
alokp@chromium.org2cf17712010-03-30 20:33:18 +000053 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000054
alokp@chromium.org2cf17712010-03-30 20:33:18 +000055 node->setLeft(left);
56 node->setRight(right);
Zhenyao Moe40d1e92014-07-16 17:40:36 -070057 if (!node->promote(mInfoSink))
58 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000059
alokp@chromium.org2cf17712010-03-30 20:33:18 +000060 // See if we can fold constants.
Olli Etuaho2c4b7462015-06-08 11:30:31 +030061 TIntermTyped *foldedNode = node->fold(mInfoSink);
62 if (foldedNode)
63 return foldedNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000064
alokp@chromium.org2cf17712010-03-30 20:33:18 +000065 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000066}
67
68//
69// Connect two nodes through an assignment.
70//
71// Returns the added node.
72//
Zhenyao Moe40d1e92014-07-16 17:40:36 -070073TIntermTyped *TIntermediate::addAssign(
74 TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000075{
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -040076 if (left->getType().getStruct() || right->getType().getStruct())
77 {
78 if (left->getType() != right->getType())
79 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -070080 return NULL;
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -040081 }
82 }
83
Zhenyao Moe40d1e92014-07-16 17:40:36 -070084 TIntermBinary *node = new TIntermBinary(op);
alokp@chromium.org2cf17712010-03-30 20:33:18 +000085 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000086
alokp@chromium.org2cf17712010-03-30 20:33:18 +000087 node->setLeft(left);
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -040088 node->setRight(right);
Zhenyao Moe40d1e92014-07-16 17:40:36 -070089 if (!node->promote(mInfoSink))
90 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000091
alokp@chromium.org2cf17712010-03-30 20:33:18 +000092 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000093}
94
95//
96// Connect two nodes through an index operator, where the left node is the base
97// of an array or struct, and the right node is a direct or indirect offset.
98//
99// Returns the added node.
100// The caller should set the type of the returned node.
101//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700102TIntermTyped *TIntermediate::addIndex(
103 TOperator op, TIntermTyped *base, TIntermTyped *index, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000104{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700105 TIntermBinary *node = new TIntermBinary(op);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000106 node->setLine(line);
107 node->setLeft(base);
108 node->setRight(index);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000109
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000110 // caller should set the type
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000111
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000112 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000113}
114
115//
116// Add one node as the parent of another that it operates on.
117//
118// Returns the added node.
119//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700120TIntermTyped *TIntermediate::addUnaryMath(
Olli Etuahof6c694b2015-03-26 14:50:53 +0200121 TOperator op, TIntermTyped *child, const TSourceLoc &line, const TType *funcReturnType)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000122{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000123 //
124 // Make a new node for the operator.
125 //
Olli Etuaho69c11b52015-03-26 12:59:00 +0200126 TIntermUnary *node = new TIntermUnary(op);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000127 node->setLine(line);
128 node->setOperand(child);
Olli Etuahof6c694b2015-03-26 14:50:53 +0200129 node->promote(funcReturnType);
Olli Etuaho7700ff62015-01-15 12:16:29 +0200130
Olli Etuaho95310b02015-06-02 17:43:38 +0300131 TIntermTyped *foldedNode = node->fold(mInfoSink);
132 if (foldedNode)
133 return foldedNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000134
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000135 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000136}
137
138//
139// This is the safe way to change the operator on an aggregate, as it
140// does lots of error checking and fixing. Especially for establishing
141// a function call's operation on it's set of parameters. Sequences
142// of instructions are also aggregates, but they just direnctly set
143// their operator to EOpSequence.
144//
145// Returns an aggregate node, which could be the one passed in if
daniel@transgaming.com978702d2012-04-04 15:05:58 +0000146// it was already an aggregate but no operator was set.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000147//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700148TIntermAggregate *TIntermediate::setAggregateOperator(
149 TIntermNode *node, TOperator op, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000150{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700151 TIntermAggregate *aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000152
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000153 //
154 // Make sure we have an aggregate. If not turn it into one.
155 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700156 if (node)
157 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000158 aggNode = node->getAsAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700159 if (aggNode == NULL || aggNode->getOp() != EOpNull)
160 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000161 //
162 // Make an aggregate containing this node.
163 //
164 aggNode = new TIntermAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700165 aggNode->getSequence()->push_back(node);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000166 }
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700167 }
168 else
169 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000170 aggNode = new TIntermAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700171 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000172
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000173 //
174 // Set the operator.
175 //
alokp@chromium.org58e54292010-08-24 21:40:03 +0000176 aggNode->setOp(op);
Jamie Madill075edd82013-07-08 13:30:19 -0400177 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000178
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000179 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000180}
181
182//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000183// Safe way to combine two nodes into an aggregate. Works with null pointers,
184// a node that's not a aggregate yet, etc.
185//
186// Returns the resulting aggregate, unless 0 was passed in for
187// both existing nodes.
188//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700189TIntermAggregate *TIntermediate::growAggregate(
190 TIntermNode *left, TIntermNode *right, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000191{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700192 if (left == NULL && right == NULL)
193 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000194
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700195 TIntermAggregate *aggNode = NULL;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000196 if (left)
197 aggNode = left->getAsAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700198 if (!aggNode || aggNode->getOp() != EOpNull)
199 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000200 aggNode = new TIntermAggregate;
201 if (left)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700202 aggNode->getSequence()->push_back(left);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000203 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000204
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000205 if (right)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700206 aggNode->getSequence()->push_back(right);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000207
Jamie Madill075edd82013-07-08 13:30:19 -0400208 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000209
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000210 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000211}
212
213//
214// Turn an existing node into an aggregate.
215//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700216// Returns an aggregate, unless NULL was passed in for the existing node.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000217//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700218TIntermAggregate *TIntermediate::makeAggregate(
219 TIntermNode *node, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000220{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700221 if (node == NULL)
222 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000223
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700224 TIntermAggregate *aggNode = new TIntermAggregate;
225 aggNode->getSequence()->push_back(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000226
Jamie Madill075edd82013-07-08 13:30:19 -0400227 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000228
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000229 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000230}
231
Olli Etuaho7d7f8c42015-05-19 18:38:49 +0300232// If the input node is nullptr, return nullptr.
233// If the input node is a sequence (block) node, return it.
234// If the input node is not a sequence node, put it inside a sequence node and return that.
235TIntermAggregate *TIntermediate::ensureSequence(TIntermNode *node)
236{
237 if (node == nullptr)
238 return nullptr;
239 TIntermAggregate *aggNode = node->getAsAggregate();
240 if (aggNode != nullptr && aggNode->getOp() == EOpSequence)
241 return aggNode;
242
243 aggNode = makeAggregate(node, node->getLine());
244 aggNode->setOp(EOpSequence);
245 return aggNode;
246}
247
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000248//
249// For "if" test nodes. There are three children; a condition,
250// a true path, and a false path. The two paths are in the
251// nodePair.
252//
253// Returns the selection node created.
254//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700255TIntermNode *TIntermediate::addSelection(
256 TIntermTyped *cond, TIntermNodePair nodePair, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000257{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000258 //
259 // For compile time constant selections, prune the code and
260 // test now.
261 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000262
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200263 if (cond->getAsConstantUnion())
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700264 {
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +0000265 if (cond->getAsConstantUnion()->getBConst(0) == true)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700266 {
267 return nodePair.node1 ? setAggregateOperator(
268 nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL;
269 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000270 else
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700271 {
272 return nodePair.node2 ? setAggregateOperator(
273 nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL;
274 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000275 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000276
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700277 TIntermSelection *node = new TIntermSelection(
Olli Etuaho7d7f8c42015-05-19 18:38:49 +0300278 cond, ensureSequence(nodePair.node1), ensureSequence(nodePair.node2));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000279 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000280
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000281 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000282}
283
Olli Etuaho15200042015-11-04 16:56:31 +0200284TIntermTyped *TIntermediate::addComma(TIntermTyped *left,
285 TIntermTyped *right,
286 const TSourceLoc &line,
287 int shaderVersion)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000288{
Olli Etuaho15200042015-11-04 16:56:31 +0200289 TQualifier resultQualifier = EvqConst;
290 // ESSL3.00 section 12.43: The result of a sequence operator is not a constant-expression.
291 if (shaderVersion >= 300 || left->getQualifier() != EvqConst ||
292 right->getQualifier() != EvqConst)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700293 {
Olli Etuaho15200042015-11-04 16:56:31 +0200294 resultQualifier = EvqTemporary;
295 }
296
297 TIntermTyped *commaNode = nullptr;
298 if (!left->hasSideEffects())
299 {
300 commaNode = right;
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700301 }
302 else
303 {
Olli Etuaho15200042015-11-04 16:56:31 +0200304 commaNode = growAggregate(left, right, line);
305 commaNode->getAsAggregate()->setOp(EOpComma);
306 commaNode->setType(right->getType());
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000307 }
Olli Etuaho15200042015-11-04 16:56:31 +0200308 commaNode->getTypePointer()->setQualifier(resultQualifier);
309 return commaNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000310}
311
312//
313// For "?:" test nodes. There are three children; a condition,
314// a true path, and a false path. The two paths are specified
315// as separate parameters.
316//
Olli Etuaho52901742015-04-15 13:42:45 +0300317// 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 +0000318//
Olli Etuaho52901742015-04-15 13:42:45 +0300319TIntermTyped *TIntermediate::addSelection(TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock,
320 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000321{
Olli Etuahob1edc4f2015-11-02 17:20:03 +0200322 TQualifier resultQualifier = EvqTemporary;
323 if (cond->getQualifier() == EvqConst && trueBlock->getQualifier() == EvqConst &&
324 falseBlock->getQualifier() == EvqConst)
325 {
326 resultQualifier = EvqConst;
327 }
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200328 // Note that the node resulting from here can be a constant union without being qualified as
329 // constant.
330 if (cond->getAsConstantUnion())
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700331 {
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +0000332 if (cond->getAsConstantUnion()->getBConst(0))
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200333 {
334 trueBlock->getTypePointer()->setQualifier(resultQualifier);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000335 return trueBlock;
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200336 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000337 else
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200338 {
339 falseBlock->getTypePointer()->setQualifier(resultQualifier);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000340 return falseBlock;
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200341 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000342 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000343
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000344 //
345 // Make a selection node.
346 //
Olli Etuaho52901742015-04-15 13:42:45 +0300347 TIntermSelection *node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
Olli Etuahob1edc4f2015-11-02 17:20:03 +0200348 node->getTypePointer()->setQualifier(resultQualifier);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000349 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000350
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000351 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000352}
353
Olli Etuahoa3a36662015-02-17 13:46:51 +0200354TIntermSwitch *TIntermediate::addSwitch(
355 TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &line)
356{
Olli Etuaho3c1dfb52015-02-20 11:34:03 +0200357 TIntermSwitch *node = new TIntermSwitch(init, statementList);
358 node->setLine(line);
359
360 return node;
Olli Etuahoa3a36662015-02-17 13:46:51 +0200361}
362
363TIntermCase *TIntermediate::addCase(
364 TIntermTyped *condition, const TSourceLoc &line)
365{
Olli Etuaho3c1dfb52015-02-20 11:34:03 +0200366 TIntermCase *node = new TIntermCase(condition);
367 node->setLine(line);
368
369 return node;
Olli Etuahoa3a36662015-02-17 13:46:51 +0200370}
371
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000372//
373// Constant terminal nodes. Has a union that contains bool, float or int constants
374//
375// Returns the constant union node created.
376//
377
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700378TIntermConstantUnion *TIntermediate::addConstantUnion(
Jamie Madillb11e2482015-05-04 14:21:22 -0400379 TConstantUnion *constantUnion, const TType &type, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000380{
Jamie Madillb11e2482015-05-04 14:21:22 -0400381 TIntermConstantUnion *node = new TIntermConstantUnion(constantUnion, type);
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
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700387TIntermTyped *TIntermediate::addSwizzle(
388 TVectorFields &fields, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000389{
390
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700391 TIntermAggregate *node = new TIntermAggregate(EOpSequence);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000392
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000393 node->setLine(line);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700394 TIntermConstantUnion *constIntNode;
395 TIntermSequence *sequenceVector = node->getSequence();
Jamie Madill6ba6ead2015-05-04 14:21:21 -0400396 TConstantUnion *unionArray;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000397
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700398 for (int i = 0; i < fields.num; i++)
399 {
Jamie Madill6ba6ead2015-05-04 14:21:21 -0400400 unionArray = new TConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000401 unionArray->setIConst(fields.offsets[i]);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700402 constIntNode = addConstantUnion(
403 unionArray, TType(EbtInt, EbpUndefined, EvqConst), line);
404 sequenceVector->push_back(constIntNode);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000405 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000406
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000407 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000408}
409
410//
411// Create loop nodes.
412//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700413TIntermNode *TIntermediate::addLoop(
414 TLoopType type, TIntermNode *init, TIntermTyped *cond, TIntermTyped *expr,
415 TIntermNode *body, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000416{
Olli Etuaho7d7f8c42015-05-19 18:38:49 +0300417 TIntermNode *node = new TIntermLoop(type, init, cond, expr, ensureSequence(body));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000418 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000419
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000420 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000421}
422
423//
424// Add branches.
425//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700426TIntermBranch* TIntermediate::addBranch(
427 TOperator branchOp, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000428{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000429 return addBranch(branchOp, 0, line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000430}
431
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700432TIntermBranch* TIntermediate::addBranch(
433 TOperator branchOp, TIntermTyped *expression, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000434{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700435 TIntermBranch *node = new TIntermBranch(branchOp, expression);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000436 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000437
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000438 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000439}
440
441//
442// This is to be executed once the final root is put on top by the parsing
443// process.
444//
Olli Etuaho43613b02015-08-04 11:02:21 +0300445TIntermAggregate *TIntermediate::postProcess(TIntermNode *root)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000446{
Olli Etuaho43613b02015-08-04 11:02:21 +0300447 if (root == nullptr)
448 return nullptr;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000449
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000450 //
Olli Etuaho43613b02015-08-04 11:02:21 +0300451 // Finish off the top level sequence, if any
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000452 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700453 TIntermAggregate *aggRoot = root->getAsAggregate();
Olli Etuaho43613b02015-08-04 11:02:21 +0300454 if (aggRoot != nullptr && aggRoot->getOp() == EOpNull)
455 {
alokp@chromium.org58e54292010-08-24 21:40:03 +0000456 aggRoot->setOp(EOpSequence);
Olli Etuaho43613b02015-08-04 11:02:21 +0300457 }
458 else if (aggRoot == nullptr || aggRoot->getOp() != EOpSequence)
459 {
460 aggRoot = new TIntermAggregate(EOpSequence);
461 aggRoot->setLine(root->getLine());
462 aggRoot->getSequence()->push_back(root);
463 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000464
Olli Etuaho43613b02015-08-04 11:02:21 +0300465 return aggRoot;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000466}
Arun Patole274f0702015-05-05 13:33:30 +0530467
Olli Etuahob43846e2015-06-02 18:18:57 +0300468TIntermTyped *TIntermediate::foldAggregateBuiltIn(TIntermAggregate *aggregate)
Arun Patole274f0702015-05-05 13:33:30 +0530469{
Olli Etuahob43846e2015-06-02 18:18:57 +0300470 switch (aggregate->getOp())
Arun Patole274f0702015-05-05 13:33:30 +0530471 {
Arun Patolebf790422015-05-18 17:53:04 +0530472 case EOpAtan:
473 case EOpPow:
474 case EOpMod:
Arun Patole274f0702015-05-05 13:33:30 +0530475 case EOpMin:
476 case EOpMax:
477 case EOpClamp:
Arun Patolebf790422015-05-18 17:53:04 +0530478 case EOpMix:
479 case EOpStep:
480 case EOpSmoothStep:
Arun Patole7fa33552015-06-10 15:15:18 +0530481 case EOpMul:
482 case EOpOuterProduct:
Arun Patole9d0b1f92015-05-20 14:27:17 +0530483 case EOpLessThan:
484 case EOpLessThanEqual:
485 case EOpGreaterThan:
486 case EOpGreaterThanEqual:
487 case EOpVectorEqual:
488 case EOpVectorNotEqual:
Arun Patole1155ddd2015-06-05 18:04:36 +0530489 case EOpDistance:
490 case EOpDot:
491 case EOpCross:
492 case EOpFaceForward:
493 case EOpReflect:
494 case EOpRefract:
Olli Etuahob43846e2015-06-02 18:18:57 +0300495 return aggregate->fold(mInfoSink);
Arun Patole274f0702015-05-05 13:33:30 +0530496 default:
497 // Constant folding not supported for the built-in.
498 return nullptr;
499 }
500
501 return nullptr;
502}