blob: 5762b1e9f475cd2c0fdca63682ca3b2b7ce25e0d [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 TIntermConstantUnion *childTempConstant = 0;
124 if (child->getAsConstantUnion())
125 childTempConstant = child->getAsConstantUnion();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000126
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000127 //
128 // Make a new node for the operator.
129 //
Olli Etuaho69c11b52015-03-26 12:59:00 +0200130 TIntermUnary *node = new TIntermUnary(op);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000131 node->setLine(line);
132 node->setOperand(child);
Olli Etuahof6c694b2015-03-26 14:50:53 +0200133 node->promote(funcReturnType);
Olli Etuaho7700ff62015-01-15 12:16:29 +0200134
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700135 if (childTempConstant)
136 {
Olli Etuaho2c4b7462015-06-08 11:30:31 +0300137 TIntermTyped *newChild = childTempConstant->foldUnary(op, mInfoSink);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000138
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000139 if (newChild)
140 return newChild;
141 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000142
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000143 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000144}
145
146//
147// This is the safe way to change the operator on an aggregate, as it
148// does lots of error checking and fixing. Especially for establishing
149// a function call's operation on it's set of parameters. Sequences
150// of instructions are also aggregates, but they just direnctly set
151// their operator to EOpSequence.
152//
153// Returns an aggregate node, which could be the one passed in if
daniel@transgaming.com978702d2012-04-04 15:05:58 +0000154// it was already an aggregate but no operator was set.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000155//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700156TIntermAggregate *TIntermediate::setAggregateOperator(
157 TIntermNode *node, TOperator op, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000158{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700159 TIntermAggregate *aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000160
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000161 //
162 // Make sure we have an aggregate. If not turn it into one.
163 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700164 if (node)
165 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000166 aggNode = node->getAsAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700167 if (aggNode == NULL || aggNode->getOp() != EOpNull)
168 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000169 //
170 // Make an aggregate containing this node.
171 //
172 aggNode = new TIntermAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700173 aggNode->getSequence()->push_back(node);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000174 }
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700175 }
176 else
177 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000178 aggNode = new TIntermAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700179 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000180
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000181 //
182 // Set the operator.
183 //
alokp@chromium.org58e54292010-08-24 21:40:03 +0000184 aggNode->setOp(op);
Jamie Madill075edd82013-07-08 13:30:19 -0400185 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000186
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000187 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000188}
189
190//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000191// Safe way to combine two nodes into an aggregate. Works with null pointers,
192// a node that's not a aggregate yet, etc.
193//
194// Returns the resulting aggregate, unless 0 was passed in for
195// both existing nodes.
196//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700197TIntermAggregate *TIntermediate::growAggregate(
198 TIntermNode *left, TIntermNode *right, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000199{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700200 if (left == NULL && right == NULL)
201 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000202
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700203 TIntermAggregate *aggNode = NULL;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000204 if (left)
205 aggNode = left->getAsAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700206 if (!aggNode || aggNode->getOp() != EOpNull)
207 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000208 aggNode = new TIntermAggregate;
209 if (left)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700210 aggNode->getSequence()->push_back(left);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000211 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000212
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000213 if (right)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700214 aggNode->getSequence()->push_back(right);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000215
Jamie Madill075edd82013-07-08 13:30:19 -0400216 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000217
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000218 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000219}
220
221//
222// Turn an existing node into an aggregate.
223//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700224// Returns an aggregate, unless NULL was passed in for the existing node.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000225//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700226TIntermAggregate *TIntermediate::makeAggregate(
227 TIntermNode *node, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000228{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700229 if (node == NULL)
230 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000231
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700232 TIntermAggregate *aggNode = new TIntermAggregate;
233 aggNode->getSequence()->push_back(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000234
Jamie Madill075edd82013-07-08 13:30:19 -0400235 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000236
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000237 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000238}
239
Olli Etuaho7d7f8c42015-05-19 18:38:49 +0300240// If the input node is nullptr, return nullptr.
241// If the input node is a sequence (block) node, return it.
242// If the input node is not a sequence node, put it inside a sequence node and return that.
243TIntermAggregate *TIntermediate::ensureSequence(TIntermNode *node)
244{
245 if (node == nullptr)
246 return nullptr;
247 TIntermAggregate *aggNode = node->getAsAggregate();
248 if (aggNode != nullptr && aggNode->getOp() == EOpSequence)
249 return aggNode;
250
251 aggNode = makeAggregate(node, node->getLine());
252 aggNode->setOp(EOpSequence);
253 return aggNode;
254}
255
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000256//
257// For "if" test nodes. There are three children; a condition,
258// a true path, and a false path. The two paths are in the
259// nodePair.
260//
261// Returns the selection node created.
262//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700263TIntermNode *TIntermediate::addSelection(
264 TIntermTyped *cond, TIntermNodePair nodePair, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000265{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000266 //
267 // For compile time constant selections, prune the code and
268 // test now.
269 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000270
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700271 if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion())
272 {
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +0000273 if (cond->getAsConstantUnion()->getBConst(0) == true)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700274 {
275 return nodePair.node1 ? setAggregateOperator(
276 nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL;
277 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000278 else
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700279 {
280 return nodePair.node2 ? setAggregateOperator(
281 nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL;
282 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000283 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000284
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700285 TIntermSelection *node = new TIntermSelection(
Olli Etuaho7d7f8c42015-05-19 18:38:49 +0300286 cond, ensureSequence(nodePair.node1), ensureSequence(nodePair.node2));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000287 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000288
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000289 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000290}
291
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700292TIntermTyped *TIntermediate::addComma(
293 TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000294{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700295 if (left->getType().getQualifier() == EvqConst &&
296 right->getType().getQualifier() == EvqConst)
297 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000298 return right;
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700299 }
300 else
301 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000302 TIntermTyped *commaAggregate = growAggregate(left, right, line);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000303 commaAggregate->getAsAggregate()->setOp(EOpComma);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000304 commaAggregate->setType(right->getType());
alokp@chromium.org58e54292010-08-24 21:40:03 +0000305 commaAggregate->getTypePointer()->setQualifier(EvqTemporary);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000306 return commaAggregate;
307 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000308}
309
310//
311// For "?:" test nodes. There are three children; a condition,
312// a true path, and a false path. The two paths are specified
313// as separate parameters.
314//
Olli Etuaho52901742015-04-15 13:42:45 +0300315// 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 +0000316//
Olli Etuaho52901742015-04-15 13:42:45 +0300317TIntermTyped *TIntermediate::addSelection(TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock,
318 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000319{
Olli Etuaho52901742015-04-15 13:42:45 +0300320 // Right now it's safe to fold ternary operators only when all operands
321 // are constant. If only the condition is constant, it's theoretically
322 // possible to fold the ternary operator, but that requires making sure
323 // that the node returned from here won't be treated as a constant
324 // expression in case the node that gets eliminated was not a constant
325 // expression.
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700326 if (cond->getAsConstantUnion() &&
327 trueBlock->getAsConstantUnion() &&
328 falseBlock->getAsConstantUnion())
329 {
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +0000330 if (cond->getAsConstantUnion()->getBConst(0))
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000331 return trueBlock;
332 else
333 return falseBlock;
334 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000335
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000336 //
337 // Make a selection node.
338 //
Olli Etuaho52901742015-04-15 13:42:45 +0300339 TIntermSelection *node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
daniel@transgaming.com43affc52012-03-28 14:55:39 +0000340 node->getTypePointer()->setQualifier(EvqTemporary);
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
Olli Etuahoa3a36662015-02-17 13:46:51 +0200346TIntermSwitch *TIntermediate::addSwitch(
347 TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &line)
348{
Olli Etuaho3c1dfb52015-02-20 11:34:03 +0200349 TIntermSwitch *node = new TIntermSwitch(init, statementList);
350 node->setLine(line);
351
352 return node;
Olli Etuahoa3a36662015-02-17 13:46:51 +0200353}
354
355TIntermCase *TIntermediate::addCase(
356 TIntermTyped *condition, const TSourceLoc &line)
357{
Olli Etuaho3c1dfb52015-02-20 11:34:03 +0200358 TIntermCase *node = new TIntermCase(condition);
359 node->setLine(line);
360
361 return node;
Olli Etuahoa3a36662015-02-17 13:46:51 +0200362}
363
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000364//
365// Constant terminal nodes. Has a union that contains bool, float or int constants
366//
367// Returns the constant union node created.
368//
369
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700370TIntermConstantUnion *TIntermediate::addConstantUnion(
Jamie Madillb11e2482015-05-04 14:21:22 -0400371 TConstantUnion *constantUnion, const TType &type, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000372{
Jamie Madillb11e2482015-05-04 14:21:22 -0400373 TIntermConstantUnion *node = new TIntermConstantUnion(constantUnion, type);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000374 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000375
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000376 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000377}
378
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700379TIntermTyped *TIntermediate::addSwizzle(
380 TVectorFields &fields, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000381{
382
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700383 TIntermAggregate *node = new TIntermAggregate(EOpSequence);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000384
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000385 node->setLine(line);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700386 TIntermConstantUnion *constIntNode;
387 TIntermSequence *sequenceVector = node->getSequence();
Jamie Madill6ba6ead2015-05-04 14:21:21 -0400388 TConstantUnion *unionArray;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000389
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700390 for (int i = 0; i < fields.num; i++)
391 {
Jamie Madill6ba6ead2015-05-04 14:21:21 -0400392 unionArray = new TConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000393 unionArray->setIConst(fields.offsets[i]);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700394 constIntNode = addConstantUnion(
395 unionArray, TType(EbtInt, EbpUndefined, EvqConst), line);
396 sequenceVector->push_back(constIntNode);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000397 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000398
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000399 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000400}
401
402//
403// Create loop nodes.
404//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700405TIntermNode *TIntermediate::addLoop(
406 TLoopType type, TIntermNode *init, TIntermTyped *cond, TIntermTyped *expr,
407 TIntermNode *body, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000408{
Olli Etuaho7d7f8c42015-05-19 18:38:49 +0300409 TIntermNode *node = new TIntermLoop(type, init, cond, expr, ensureSequence(body));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000410 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000411
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000412 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000413}
414
415//
416// Add branches.
417//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700418TIntermBranch* TIntermediate::addBranch(
419 TOperator branchOp, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000420{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000421 return addBranch(branchOp, 0, line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000422}
423
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700424TIntermBranch* TIntermediate::addBranch(
425 TOperator branchOp, TIntermTyped *expression, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000426{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700427 TIntermBranch *node = new TIntermBranch(branchOp, expression);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000428 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000429
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000430 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000431}
432
433//
434// This is to be executed once the final root is put on top by the parsing
435// process.
436//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700437bool TIntermediate::postProcess(TIntermNode *root)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000438{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700439 if (root == NULL)
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000440 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000441
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000442 //
443 // First, finish off the top level sequence, if any
444 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700445 TIntermAggregate *aggRoot = root->getAsAggregate();
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000446 if (aggRoot && aggRoot->getOp() == EOpNull)
alokp@chromium.org58e54292010-08-24 21:40:03 +0000447 aggRoot->setOp(EOpSequence);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000448
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000449 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000450}
Arun Patole274f0702015-05-05 13:33:30 +0530451
452TIntermTyped *TIntermediate::foldAggregateBuiltIn(TOperator op, TIntermAggregate *aggregate)
453{
454 switch (op)
455 {
Arun Patolebf790422015-05-18 17:53:04 +0530456 case EOpAtan:
457 case EOpPow:
458 case EOpMod:
Arun Patole274f0702015-05-05 13:33:30 +0530459 case EOpMin:
460 case EOpMax:
461 case EOpClamp:
Arun Patolebf790422015-05-18 17:53:04 +0530462 case EOpMix:
463 case EOpStep:
464 case EOpSmoothStep:
Arun Patole9d0b1f92015-05-20 14:27:17 +0530465 case EOpLessThan:
466 case EOpLessThanEqual:
467 case EOpGreaterThan:
468 case EOpGreaterThanEqual:
469 case EOpVectorEqual:
470 case EOpVectorNotEqual:
Arun Patole1155ddd2015-06-05 18:04:36 +0530471 case EOpDistance:
472 case EOpDot:
473 case EOpCross:
474 case EOpFaceForward:
475 case EOpReflect:
476 case EOpRefract:
Arun Patolebf790422015-05-18 17:53:04 +0530477 return TIntermConstantUnion::FoldAggregateBuiltIn(op, aggregate, mInfoSink);
Arun Patole274f0702015-05-05 13:33:30 +0530478 default:
479 // Constant folding not supported for the built-in.
480 return nullptr;
481 }
482
483 return nullptr;
484}