blob: 243a9ca6e6552062cb03dcf3dcdc94807aa8d006 [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:
84 if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat)
85 {
86 return NULL;
87 }
88 break;
Zhenyao Moe40d1e92014-07-16 17:40:36 -070089 default:
90 break;
alokp@chromium.org2cf17712010-03-30 20:33:18 +000091 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000092
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -040093 if (left->getBasicType() != right->getBasicType())
94 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -070095 return NULL;
alokp@chromium.org2cf17712010-03-30 20:33:18 +000096 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000097
alokp@chromium.org2cf17712010-03-30 20:33:18 +000098 //
99 // Need a new node holding things together then. Make
100 // one and promote it to the right type.
101 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700102 TIntermBinary *node = new TIntermBinary(op);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000103 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000104
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000105 node->setLeft(left);
106 node->setRight(right);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700107 if (!node->promote(mInfoSink))
108 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000109
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000110 //
111 // See if we can fold constants.
112 //
alokp@chromium.org8f0f24a2010-09-01 21:06:24 +0000113 TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
114 TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700115 if (leftTempConstant && rightTempConstant)
116 {
117 TIntermTyped *typedReturnNode =
118 leftTempConstant->fold(node->getOp(), rightTempConstant, mInfoSink);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000119
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000120 if (typedReturnNode)
121 return typedReturnNode;
122 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000123
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000124 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000125}
126
127//
128// Connect two nodes through an assignment.
129//
130// Returns the added node.
131//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700132TIntermTyped *TIntermediate::addAssign(
133 TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000134{
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -0400135 if (left->getType().getStruct() || right->getType().getStruct())
136 {
137 if (left->getType() != right->getType())
138 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700139 return NULL;
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -0400140 }
141 }
142
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700143 TIntermBinary *node = new TIntermBinary(op);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000144 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000145
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000146 node->setLeft(left);
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -0400147 node->setRight(right);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700148 if (!node->promote(mInfoSink))
149 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000150
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000151 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000152}
153
154//
155// Connect two nodes through an index operator, where the left node is the base
156// of an array or struct, and the right node is a direct or indirect offset.
157//
158// Returns the added node.
159// The caller should set the type of the returned node.
160//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700161TIntermTyped *TIntermediate::addIndex(
162 TOperator op, TIntermTyped *base, TIntermTyped *index, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000163{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700164 TIntermBinary *node = new TIntermBinary(op);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000165 node->setLine(line);
166 node->setLeft(base);
167 node->setRight(index);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000168
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000169 // caller should set the type
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000170
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000171 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000172}
173
174//
175// Add one node as the parent of another that it operates on.
176//
177// Returns the added node.
178//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700179TIntermTyped *TIntermediate::addUnaryMath(
180 TOperator op, TIntermNode *childNode, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000181{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700182 TIntermUnary *node;
183 TIntermTyped *child = childNode->getAsTyped();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000184
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700185 if (child == NULL)
186 {
187 mInfoSink.info.message(EPrefixInternalError, line,
188 "Bad type in AddUnaryMath");
189 return NULL;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000190 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000191
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700192 switch (op)
193 {
194 case EOpLogicalNot:
195 if (child->getType().getBasicType() != EbtBool ||
196 child->getType().isMatrix() ||
197 child->getType().isArray() ||
198 child->getType().isVector())
199 {
200 return NULL;
201 }
202 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000203
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700204 case EOpPostIncrement:
205 case EOpPreIncrement:
206 case EOpPostDecrement:
207 case EOpPreDecrement:
208 case EOpNegative:
Zhenyao Mode1e00e2014-10-09 16:55:32 -0700209 case EOpPositive:
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700210 if (child->getType().getBasicType() == EbtStruct ||
211 child->getType().isArray())
212 {
213 return NULL;
214 }
215 default:
216 break;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000217 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000218
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000219 TIntermConstantUnion *childTempConstant = 0;
220 if (child->getAsConstantUnion())
221 childTempConstant = child->getAsConstantUnion();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000222
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000223 //
224 // Make a new node for the operator.
225 //
226 node = new TIntermUnary(op);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000227 node->setLine(line);
228 node->setOperand(child);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000229
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700230 if (!node->promote(mInfoSink))
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000231 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000232
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700233 if (childTempConstant)
234 {
235 TIntermTyped *newChild = childTempConstant->fold(op, 0, mInfoSink);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000236
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000237 if (newChild)
238 return newChild;
239 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000240
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000241 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000242}
243
244//
245// This is the safe way to change the operator on an aggregate, as it
246// does lots of error checking and fixing. Especially for establishing
247// a function call's operation on it's set of parameters. Sequences
248// of instructions are also aggregates, but they just direnctly set
249// their operator to EOpSequence.
250//
251// Returns an aggregate node, which could be the one passed in if
daniel@transgaming.com978702d2012-04-04 15:05:58 +0000252// it was already an aggregate but no operator was set.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000253//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700254TIntermAggregate *TIntermediate::setAggregateOperator(
255 TIntermNode *node, TOperator op, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000256{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700257 TIntermAggregate *aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000258
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000259 //
260 // Make sure we have an aggregate. If not turn it into one.
261 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700262 if (node)
263 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000264 aggNode = node->getAsAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700265 if (aggNode == NULL || aggNode->getOp() != EOpNull)
266 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000267 //
268 // Make an aggregate containing this node.
269 //
270 aggNode = new TIntermAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700271 aggNode->getSequence()->push_back(node);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000272 }
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700273 }
274 else
275 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000276 aggNode = new TIntermAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700277 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000278
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000279 //
280 // Set the operator.
281 //
alokp@chromium.org58e54292010-08-24 21:40:03 +0000282 aggNode->setOp(op);
Jamie Madill075edd82013-07-08 13:30:19 -0400283 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000284
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000285 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000286}
287
288//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000289// Safe way to combine two nodes into an aggregate. Works with null pointers,
290// a node that's not a aggregate yet, etc.
291//
292// Returns the resulting aggregate, unless 0 was passed in for
293// both existing nodes.
294//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700295TIntermAggregate *TIntermediate::growAggregate(
296 TIntermNode *left, TIntermNode *right, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000297{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700298 if (left == NULL && right == NULL)
299 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000300
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700301 TIntermAggregate *aggNode = NULL;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000302 if (left)
303 aggNode = left->getAsAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700304 if (!aggNode || aggNode->getOp() != EOpNull)
305 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000306 aggNode = new TIntermAggregate;
307 if (left)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700308 aggNode->getSequence()->push_back(left);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000309 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000310
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000311 if (right)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700312 aggNode->getSequence()->push_back(right);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000313
Jamie Madill075edd82013-07-08 13:30:19 -0400314 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000315
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000316 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000317}
318
319//
320// Turn an existing node into an aggregate.
321//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700322// Returns an aggregate, unless NULL was passed in for the existing node.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000323//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700324TIntermAggregate *TIntermediate::makeAggregate(
325 TIntermNode *node, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000326{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700327 if (node == NULL)
328 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000329
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700330 TIntermAggregate *aggNode = new TIntermAggregate;
331 aggNode->getSequence()->push_back(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000332
Jamie Madill075edd82013-07-08 13:30:19 -0400333 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000334
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000335 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000336}
337
338//
339// For "if" test nodes. There are three children; a condition,
340// a true path, and a false path. The two paths are in the
341// nodePair.
342//
343// Returns the selection node created.
344//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700345TIntermNode *TIntermediate::addSelection(
346 TIntermTyped *cond, TIntermNodePair nodePair, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000347{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000348 //
349 // For compile time constant selections, prune the code and
350 // test now.
351 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000352
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700353 if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion())
354 {
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +0000355 if (cond->getAsConstantUnion()->getBConst(0) == true)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700356 {
357 return nodePair.node1 ? setAggregateOperator(
358 nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL;
359 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000360 else
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700361 {
362 return nodePair.node2 ? setAggregateOperator(
363 nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL;
364 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000365 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000366
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700367 TIntermSelection *node = new TIntermSelection(
368 cond, nodePair.node1, nodePair.node2);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000369 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000370
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000371 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000372}
373
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700374TIntermTyped *TIntermediate::addComma(
375 TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000376{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700377 if (left->getType().getQualifier() == EvqConst &&
378 right->getType().getQualifier() == EvqConst)
379 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000380 return right;
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700381 }
382 else
383 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000384 TIntermTyped *commaAggregate = growAggregate(left, right, line);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000385 commaAggregate->getAsAggregate()->setOp(EOpComma);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000386 commaAggregate->setType(right->getType());
alokp@chromium.org58e54292010-08-24 21:40:03 +0000387 commaAggregate->getTypePointer()->setQualifier(EvqTemporary);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000388 return commaAggregate;
389 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000390}
391
392//
393// For "?:" test nodes. There are three children; a condition,
394// a true path, and a false path. The two paths are specified
395// as separate parameters.
396//
397// Returns the selection node created, or 0 if one could not be.
398//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700399TIntermTyped *TIntermediate::addSelection(
400 TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock,
401 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000402{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700403 if (!cond || !trueBlock || !falseBlock ||
404 trueBlock->getType() != falseBlock->getType())
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -0400405 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700406 return NULL;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000407 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000408
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000409 //
410 // See if all the operands are constant, then fold it otherwise not.
411 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000412
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700413 if (cond->getAsConstantUnion() &&
414 trueBlock->getAsConstantUnion() &&
415 falseBlock->getAsConstantUnion())
416 {
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +0000417 if (cond->getAsConstantUnion()->getBConst(0))
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000418 return trueBlock;
419 else
420 return falseBlock;
421 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000422
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000423 //
424 // Make a selection node.
425 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700426 TIntermSelection *node = new TIntermSelection(
427 cond, trueBlock, falseBlock, trueBlock->getType());
daniel@transgaming.com43affc52012-03-28 14:55:39 +0000428 node->getTypePointer()->setQualifier(EvqTemporary);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000429 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000430
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000431 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000432}
433
434//
435// Constant terminal nodes. Has a union that contains bool, float or int constants
436//
437// Returns the constant union node created.
438//
439
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700440TIntermConstantUnion *TIntermediate::addConstantUnion(
441 ConstantUnion *unionArrayPointer, const TType &t, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000442{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700443 TIntermConstantUnion *node = new TIntermConstantUnion(unionArrayPointer, t);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000444 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000445
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000446 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000447}
448
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700449TIntermTyped *TIntermediate::addSwizzle(
450 TVectorFields &fields, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000451{
452
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700453 TIntermAggregate *node = new TIntermAggregate(EOpSequence);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000454
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000455 node->setLine(line);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700456 TIntermConstantUnion *constIntNode;
457 TIntermSequence *sequenceVector = node->getSequence();
458 ConstantUnion *unionArray;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000459
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700460 for (int i = 0; i < fields.num; i++)
461 {
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000462 unionArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000463 unionArray->setIConst(fields.offsets[i]);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700464 constIntNode = addConstantUnion(
465 unionArray, TType(EbtInt, EbpUndefined, EvqConst), line);
466 sequenceVector->push_back(constIntNode);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000467 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000468
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000469 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000470}
471
472//
473// Create loop nodes.
474//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700475TIntermNode *TIntermediate::addLoop(
476 TLoopType type, TIntermNode *init, TIntermTyped *cond, TIntermTyped *expr,
477 TIntermNode *body, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000478{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700479 TIntermNode *node = new TIntermLoop(type, init, cond, expr, body);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000480 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000481
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000482 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000483}
484
485//
486// Add branches.
487//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700488TIntermBranch* TIntermediate::addBranch(
489 TOperator branchOp, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000490{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000491 return addBranch(branchOp, 0, line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000492}
493
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700494TIntermBranch* TIntermediate::addBranch(
495 TOperator branchOp, TIntermTyped *expression, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000496{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700497 TIntermBranch *node = new TIntermBranch(branchOp, expression);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000498 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000499
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000500 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000501}
502
503//
504// This is to be executed once the final root is put on top by the parsing
505// process.
506//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700507bool TIntermediate::postProcess(TIntermNode *root)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000508{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700509 if (root == NULL)
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000510 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000511
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000512 //
513 // First, finish off the top level sequence, if any
514 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700515 TIntermAggregate *aggRoot = root->getAsAggregate();
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000516 if (aggRoot && aggRoot->getOp() == EOpNull)
alokp@chromium.org58e54292010-08-24 21:40:03 +0000517 aggRoot->setOp(EOpSequence);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000518
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000519 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000520}