blob: 914b45053ae72c95d649a0529d4d525552988f01 [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{
Zhenyao Moe40d1e92014-07-16 17:40:36 -070048 switch (op)
49 {
50 case EOpEqual:
51 case EOpNotEqual:
52 if (left->isArray())
53 return NULL;
54 break;
55 case EOpLessThan:
56 case EOpGreaterThan:
57 case EOpLessThanEqual:
58 case EOpGreaterThanEqual:
59 if (left->isMatrix() || left->isArray() || left->isVector() ||
60 left->getBasicType() == EbtStruct)
61 {
62 return NULL;
63 }
64 break;
65 case EOpLogicalOr:
66 case EOpLogicalXor:
67 case EOpLogicalAnd:
68 if (left->getBasicType() != EbtBool ||
69 left->isMatrix() || left->isArray() || left->isVector())
70 {
71 return NULL;
72 }
73 break;
74 case EOpAdd:
75 case EOpSub:
76 case EOpDiv:
77 case EOpMul:
78 if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool)
Gregoire Payen de La Garanderiebe954a22014-12-23 00:05:28 +000079 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -070080 return NULL;
Gregoire Payen de La Garanderiebe954a22014-12-23 00:05:28 +000081 }
82 break;
83 case EOpMod:
Olli Etuahod68157f2015-01-16 12:24:17 +020084 // Note that this is only for the % operator, not for mod()
Gregoire Payen de La Garanderiebe954a22014-12-23 00:05:28 +000085 if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat)
86 {
87 return NULL;
88 }
89 break;
Zhenyao Moe40d1e92014-07-16 17:40:36 -070090 default:
91 break;
alokp@chromium.org2cf17712010-03-30 20:33:18 +000092 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000093
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -040094 if (left->getBasicType() != right->getBasicType())
95 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -070096 return NULL;
alokp@chromium.org2cf17712010-03-30 20:33:18 +000097 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000098
alokp@chromium.org2cf17712010-03-30 20:33:18 +000099 //
100 // Need a new node holding things together then. Make
101 // one and promote it to the right type.
102 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700103 TIntermBinary *node = new TIntermBinary(op);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000104 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000105
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000106 node->setLeft(left);
107 node->setRight(right);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700108 if (!node->promote(mInfoSink))
109 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000110
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000111 //
112 // See if we can fold constants.
113 //
alokp@chromium.org8f0f24a2010-09-01 21:06:24 +0000114 TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
115 TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700116 if (leftTempConstant && rightTempConstant)
117 {
118 TIntermTyped *typedReturnNode =
119 leftTempConstant->fold(node->getOp(), rightTempConstant, mInfoSink);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000120
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000121 if (typedReturnNode)
122 return typedReturnNode;
123 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000124
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000125 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000126}
127
128//
129// Connect two nodes through an assignment.
130//
131// Returns the added node.
132//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700133TIntermTyped *TIntermediate::addAssign(
134 TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000135{
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -0400136 if (left->getType().getStruct() || right->getType().getStruct())
137 {
138 if (left->getType() != right->getType())
139 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700140 return NULL;
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -0400141 }
142 }
143
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700144 TIntermBinary *node = new TIntermBinary(op);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000145 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000146
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000147 node->setLeft(left);
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -0400148 node->setRight(right);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700149 if (!node->promote(mInfoSink))
150 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000151
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000152 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000153}
154
155//
156// Connect two nodes through an index operator, where the left node is the base
157// of an array or struct, and the right node is a direct or indirect offset.
158//
159// Returns the added node.
160// The caller should set the type of the returned node.
161//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700162TIntermTyped *TIntermediate::addIndex(
163 TOperator op, TIntermTyped *base, TIntermTyped *index, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000164{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700165 TIntermBinary *node = new TIntermBinary(op);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000166 node->setLine(line);
167 node->setLeft(base);
168 node->setRight(index);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000169
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000170 // caller should set the type
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000171
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000172 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000173}
174
175//
176// Add one node as the parent of another that it operates on.
177//
178// Returns the added node.
179//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700180TIntermTyped *TIntermediate::addUnaryMath(
181 TOperator op, TIntermNode *childNode, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000182{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700183 TIntermUnary *node;
184 TIntermTyped *child = childNode->getAsTyped();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000185
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700186 if (child == NULL)
187 {
188 mInfoSink.info.message(EPrefixInternalError, line,
189 "Bad type in AddUnaryMath");
190 return NULL;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000191 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000192
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700193 switch (op)
194 {
195 case EOpLogicalNot:
196 if (child->getType().getBasicType() != EbtBool ||
197 child->getType().isMatrix() ||
198 child->getType().isArray() ||
199 child->getType().isVector())
200 {
201 return NULL;
202 }
203 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000204
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700205 case EOpPostIncrement:
206 case EOpPreIncrement:
207 case EOpPostDecrement:
208 case EOpPreDecrement:
209 case EOpNegative:
Zhenyao Mode1e00e2014-10-09 16:55:32 -0700210 case EOpPositive:
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700211 if (child->getType().getBasicType() == EbtStruct ||
212 child->getType().isArray())
213 {
214 return NULL;
215 }
216 default:
217 break;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000218 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000219
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000220 TIntermConstantUnion *childTempConstant = 0;
221 if (child->getAsConstantUnion())
222 childTempConstant = child->getAsConstantUnion();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000223
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000224 //
225 // Make a new node for the operator.
226 //
227 node = new TIntermUnary(op);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000228 node->setLine(line);
229 node->setOperand(child);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000230
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700231 if (!node->promote(mInfoSink))
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000232 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000233
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700234 if (childTempConstant)
235 {
236 TIntermTyped *newChild = childTempConstant->fold(op, 0, mInfoSink);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000237
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000238 if (newChild)
239 return newChild;
240 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000241
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000242 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000243}
244
245//
246// This is the safe way to change the operator on an aggregate, as it
247// does lots of error checking and fixing. Especially for establishing
248// a function call's operation on it's set of parameters. Sequences
249// of instructions are also aggregates, but they just direnctly set
250// their operator to EOpSequence.
251//
252// Returns an aggregate node, which could be the one passed in if
daniel@transgaming.com978702d2012-04-04 15:05:58 +0000253// it was already an aggregate but no operator was set.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000254//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700255TIntermAggregate *TIntermediate::setAggregateOperator(
256 TIntermNode *node, TOperator op, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000257{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700258 TIntermAggregate *aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000259
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000260 //
261 // Make sure we have an aggregate. If not turn it into one.
262 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700263 if (node)
264 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000265 aggNode = node->getAsAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700266 if (aggNode == NULL || aggNode->getOp() != EOpNull)
267 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000268 //
269 // Make an aggregate containing this node.
270 //
271 aggNode = new TIntermAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700272 aggNode->getSequence()->push_back(node);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000273 }
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700274 }
275 else
276 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000277 aggNode = new TIntermAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700278 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000279
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000280 //
281 // Set the operator.
282 //
alokp@chromium.org58e54292010-08-24 21:40:03 +0000283 aggNode->setOp(op);
Jamie Madill075edd82013-07-08 13:30:19 -0400284 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000285
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000286 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000287}
288
289//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000290// Safe way to combine two nodes into an aggregate. Works with null pointers,
291// a node that's not a aggregate yet, etc.
292//
293// Returns the resulting aggregate, unless 0 was passed in for
294// both existing nodes.
295//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700296TIntermAggregate *TIntermediate::growAggregate(
297 TIntermNode *left, TIntermNode *right, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000298{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700299 if (left == NULL && right == NULL)
300 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000301
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700302 TIntermAggregate *aggNode = NULL;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000303 if (left)
304 aggNode = left->getAsAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700305 if (!aggNode || aggNode->getOp() != EOpNull)
306 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000307 aggNode = new TIntermAggregate;
308 if (left)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700309 aggNode->getSequence()->push_back(left);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000310 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000311
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000312 if (right)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700313 aggNode->getSequence()->push_back(right);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000314
Jamie Madill075edd82013-07-08 13:30:19 -0400315 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000316
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000317 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000318}
319
320//
321// Turn an existing node into an aggregate.
322//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700323// Returns an aggregate, unless NULL was passed in for the existing node.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000324//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700325TIntermAggregate *TIntermediate::makeAggregate(
326 TIntermNode *node, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000327{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700328 if (node == NULL)
329 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000330
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700331 TIntermAggregate *aggNode = new TIntermAggregate;
332 aggNode->getSequence()->push_back(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000333
Jamie Madill075edd82013-07-08 13:30:19 -0400334 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000335
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000336 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000337}
338
339//
340// For "if" test nodes. There are three children; a condition,
341// a true path, and a false path. The two paths are in the
342// nodePair.
343//
344// Returns the selection node created.
345//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700346TIntermNode *TIntermediate::addSelection(
347 TIntermTyped *cond, TIntermNodePair nodePair, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000348{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000349 //
350 // For compile time constant selections, prune the code and
351 // test now.
352 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000353
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700354 if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion())
355 {
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +0000356 if (cond->getAsConstantUnion()->getBConst(0) == true)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700357 {
358 return nodePair.node1 ? setAggregateOperator(
359 nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL;
360 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000361 else
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700362 {
363 return nodePair.node2 ? setAggregateOperator(
364 nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL;
365 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000366 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000367
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700368 TIntermSelection *node = new TIntermSelection(
369 cond, nodePair.node1, nodePair.node2);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000370 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000371
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000372 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000373}
374
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700375TIntermTyped *TIntermediate::addComma(
376 TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000377{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700378 if (left->getType().getQualifier() == EvqConst &&
379 right->getType().getQualifier() == EvqConst)
380 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000381 return right;
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700382 }
383 else
384 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000385 TIntermTyped *commaAggregate = growAggregate(left, right, line);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000386 commaAggregate->getAsAggregate()->setOp(EOpComma);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000387 commaAggregate->setType(right->getType());
alokp@chromium.org58e54292010-08-24 21:40:03 +0000388 commaAggregate->getTypePointer()->setQualifier(EvqTemporary);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000389 return commaAggregate;
390 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000391}
392
393//
394// For "?:" test nodes. There are three children; a condition,
395// a true path, and a false path. The two paths are specified
396// as separate parameters.
397//
398// Returns the selection node created, or 0 if one could not be.
399//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700400TIntermTyped *TIntermediate::addSelection(
401 TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock,
402 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000403{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700404 if (!cond || !trueBlock || !falseBlock ||
405 trueBlock->getType() != falseBlock->getType())
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -0400406 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700407 return NULL;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000408 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000409
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000410 //
411 // See if all the operands are constant, then fold it otherwise not.
412 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000413
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700414 if (cond->getAsConstantUnion() &&
415 trueBlock->getAsConstantUnion() &&
416 falseBlock->getAsConstantUnion())
417 {
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +0000418 if (cond->getAsConstantUnion()->getBConst(0))
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000419 return trueBlock;
420 else
421 return falseBlock;
422 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000423
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000424 //
425 // Make a selection node.
426 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700427 TIntermSelection *node = new TIntermSelection(
428 cond, trueBlock, falseBlock, trueBlock->getType());
daniel@transgaming.com43affc52012-03-28 14:55:39 +0000429 node->getTypePointer()->setQualifier(EvqTemporary);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000430 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000431
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000432 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000433}
434
435//
436// Constant terminal nodes. Has a union that contains bool, float or int constants
437//
438// Returns the constant union node created.
439//
440
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700441TIntermConstantUnion *TIntermediate::addConstantUnion(
442 ConstantUnion *unionArrayPointer, const TType &t, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000443{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700444 TIntermConstantUnion *node = new TIntermConstantUnion(unionArrayPointer, t);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000445 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000446
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000447 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000448}
449
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700450TIntermTyped *TIntermediate::addSwizzle(
451 TVectorFields &fields, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000452{
453
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700454 TIntermAggregate *node = new TIntermAggregate(EOpSequence);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000455
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000456 node->setLine(line);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700457 TIntermConstantUnion *constIntNode;
458 TIntermSequence *sequenceVector = node->getSequence();
459 ConstantUnion *unionArray;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000460
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700461 for (int i = 0; i < fields.num; i++)
462 {
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000463 unionArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000464 unionArray->setIConst(fields.offsets[i]);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700465 constIntNode = addConstantUnion(
466 unionArray, TType(EbtInt, EbpUndefined, EvqConst), line);
467 sequenceVector->push_back(constIntNode);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000468 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000469
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000470 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000471}
472
473//
474// Create loop nodes.
475//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700476TIntermNode *TIntermediate::addLoop(
477 TLoopType type, TIntermNode *init, TIntermTyped *cond, TIntermTyped *expr,
478 TIntermNode *body, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000479{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700480 TIntermNode *node = new TIntermLoop(type, init, cond, expr, body);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000481 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000482
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000483 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000484}
485
486//
487// Add branches.
488//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700489TIntermBranch* TIntermediate::addBranch(
490 TOperator branchOp, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000491{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000492 return addBranch(branchOp, 0, line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000493}
494
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700495TIntermBranch* TIntermediate::addBranch(
496 TOperator branchOp, TIntermTyped *expression, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000497{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700498 TIntermBranch *node = new TIntermBranch(branchOp, expression);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000499 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000500
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000501 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000502}
503
504//
505// This is to be executed once the final root is put on top by the parsing
506// process.
507//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700508bool TIntermediate::postProcess(TIntermNode *root)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000509{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700510 if (root == NULL)
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000511 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000512
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000513 //
514 // First, finish off the top level sequence, if any
515 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700516 TIntermAggregate *aggRoot = root->getAsAggregate();
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000517 if (aggRoot && aggRoot->getOp() == EOpNull)
alokp@chromium.org58e54292010-08-24 21:40:03 +0000518 aggRoot->setOp(EOpSequence);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000519
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000520 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000521}