blob: de72cfe8760499522e163a379ec5ee82c32d1fed [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
Olli Etuaho7700ff62015-01-15 12:16:29 +0200234 switch (op)
235 {
236 case EOpPackSnorm2x16:
237 case EOpPackUnorm2x16:
238 case EOpPackHalf2x16:
239 case EOpUnpackSnorm2x16:
240 case EOpUnpackUnorm2x16:
241 node->getTypePointer()->setPrecision(EbpHigh);
242 break;
243 case EOpUnpackHalf2x16:
244 node->getTypePointer()->setPrecision(EbpMedium);
245 break;
246 default:
247 break;
248 }
249
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700250 if (childTempConstant)
251 {
252 TIntermTyped *newChild = childTempConstant->fold(op, 0, mInfoSink);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000253
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000254 if (newChild)
255 return newChild;
256 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000257
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000258 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000259}
260
261//
262// This is the safe way to change the operator on an aggregate, as it
263// does lots of error checking and fixing. Especially for establishing
264// a function call's operation on it's set of parameters. Sequences
265// of instructions are also aggregates, but they just direnctly set
266// their operator to EOpSequence.
267//
268// Returns an aggregate node, which could be the one passed in if
daniel@transgaming.com978702d2012-04-04 15:05:58 +0000269// it was already an aggregate but no operator was set.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000270//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700271TIntermAggregate *TIntermediate::setAggregateOperator(
272 TIntermNode *node, TOperator op, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000273{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700274 TIntermAggregate *aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000275
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000276 //
277 // Make sure we have an aggregate. If not turn it into one.
278 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700279 if (node)
280 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000281 aggNode = node->getAsAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700282 if (aggNode == NULL || aggNode->getOp() != EOpNull)
283 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000284 //
285 // Make an aggregate containing this node.
286 //
287 aggNode = new TIntermAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700288 aggNode->getSequence()->push_back(node);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000289 }
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700290 }
291 else
292 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000293 aggNode = new TIntermAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700294 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000295
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000296 //
297 // Set the operator.
298 //
alokp@chromium.org58e54292010-08-24 21:40:03 +0000299 aggNode->setOp(op);
Jamie Madill075edd82013-07-08 13:30:19 -0400300 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000301
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000302 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000303}
304
305//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000306// Safe way to combine two nodes into an aggregate. Works with null pointers,
307// a node that's not a aggregate yet, etc.
308//
309// Returns the resulting aggregate, unless 0 was passed in for
310// both existing nodes.
311//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700312TIntermAggregate *TIntermediate::growAggregate(
313 TIntermNode *left, TIntermNode *right, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000314{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700315 if (left == NULL && right == NULL)
316 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000317
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700318 TIntermAggregate *aggNode = NULL;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000319 if (left)
320 aggNode = left->getAsAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700321 if (!aggNode || aggNode->getOp() != EOpNull)
322 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000323 aggNode = new TIntermAggregate;
324 if (left)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700325 aggNode->getSequence()->push_back(left);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000326 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000327
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000328 if (right)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700329 aggNode->getSequence()->push_back(right);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000330
Jamie Madill075edd82013-07-08 13:30:19 -0400331 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000332
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000333 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000334}
335
336//
337// Turn an existing node into an aggregate.
338//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700339// Returns an aggregate, unless NULL was passed in for the existing node.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000340//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700341TIntermAggregate *TIntermediate::makeAggregate(
342 TIntermNode *node, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000343{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700344 if (node == NULL)
345 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000346
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700347 TIntermAggregate *aggNode = new TIntermAggregate;
348 aggNode->getSequence()->push_back(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000349
Jamie Madill075edd82013-07-08 13:30:19 -0400350 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000351
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000352 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000353}
354
355//
356// For "if" test nodes. There are three children; a condition,
357// a true path, and a false path. The two paths are in the
358// nodePair.
359//
360// Returns the selection node created.
361//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700362TIntermNode *TIntermediate::addSelection(
363 TIntermTyped *cond, TIntermNodePair nodePair, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000364{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000365 //
366 // For compile time constant selections, prune the code and
367 // test now.
368 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000369
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700370 if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion())
371 {
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +0000372 if (cond->getAsConstantUnion()->getBConst(0) == true)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700373 {
374 return nodePair.node1 ? setAggregateOperator(
375 nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL;
376 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000377 else
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700378 {
379 return nodePair.node2 ? setAggregateOperator(
380 nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL;
381 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000382 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000383
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700384 TIntermSelection *node = new TIntermSelection(
385 cond, nodePair.node1, nodePair.node2);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000386 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000387
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000388 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000389}
390
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700391TIntermTyped *TIntermediate::addComma(
392 TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000393{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700394 if (left->getType().getQualifier() == EvqConst &&
395 right->getType().getQualifier() == EvqConst)
396 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000397 return right;
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700398 }
399 else
400 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000401 TIntermTyped *commaAggregate = growAggregate(left, right, line);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000402 commaAggregate->getAsAggregate()->setOp(EOpComma);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000403 commaAggregate->setType(right->getType());
alokp@chromium.org58e54292010-08-24 21:40:03 +0000404 commaAggregate->getTypePointer()->setQualifier(EvqTemporary);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000405 return commaAggregate;
406 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000407}
408
409//
410// For "?:" test nodes. There are three children; a condition,
411// a true path, and a false path. The two paths are specified
412// as separate parameters.
413//
414// Returns the selection node created, or 0 if one could not be.
415//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700416TIntermTyped *TIntermediate::addSelection(
417 TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock,
418 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000419{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700420 if (!cond || !trueBlock || !falseBlock ||
421 trueBlock->getType() != falseBlock->getType())
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -0400422 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700423 return NULL;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000424 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000425
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000426 //
427 // See if all the operands are constant, then fold it otherwise not.
428 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000429
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700430 if (cond->getAsConstantUnion() &&
431 trueBlock->getAsConstantUnion() &&
432 falseBlock->getAsConstantUnion())
433 {
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +0000434 if (cond->getAsConstantUnion()->getBConst(0))
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000435 return trueBlock;
436 else
437 return falseBlock;
438 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000439
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000440 //
441 // Make a selection node.
442 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700443 TIntermSelection *node = new TIntermSelection(
444 cond, trueBlock, falseBlock, trueBlock->getType());
daniel@transgaming.com43affc52012-03-28 14:55:39 +0000445 node->getTypePointer()->setQualifier(EvqTemporary);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000446 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000447
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000448 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000449}
450
451//
452// Constant terminal nodes. Has a union that contains bool, float or int constants
453//
454// Returns the constant union node created.
455//
456
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700457TIntermConstantUnion *TIntermediate::addConstantUnion(
458 ConstantUnion *unionArrayPointer, const TType &t, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000459{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700460 TIntermConstantUnion *node = new TIntermConstantUnion(unionArrayPointer, t);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000461 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000462
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000463 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000464}
465
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700466TIntermTyped *TIntermediate::addSwizzle(
467 TVectorFields &fields, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000468{
469
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700470 TIntermAggregate *node = new TIntermAggregate(EOpSequence);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000471
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000472 node->setLine(line);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700473 TIntermConstantUnion *constIntNode;
474 TIntermSequence *sequenceVector = node->getSequence();
475 ConstantUnion *unionArray;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000476
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700477 for (int i = 0; i < fields.num; i++)
478 {
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000479 unionArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000480 unionArray->setIConst(fields.offsets[i]);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700481 constIntNode = addConstantUnion(
482 unionArray, TType(EbtInt, EbpUndefined, EvqConst), line);
483 sequenceVector->push_back(constIntNode);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000484 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000485
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000486 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000487}
488
489//
490// Create loop nodes.
491//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700492TIntermNode *TIntermediate::addLoop(
493 TLoopType type, TIntermNode *init, TIntermTyped *cond, TIntermTyped *expr,
494 TIntermNode *body, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000495{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700496 TIntermNode *node = new TIntermLoop(type, init, cond, expr, body);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000497 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000498
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000499 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000500}
501
502//
503// Add branches.
504//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700505TIntermBranch* TIntermediate::addBranch(
506 TOperator branchOp, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000507{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000508 return addBranch(branchOp, 0, line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000509}
510
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700511TIntermBranch* TIntermediate::addBranch(
512 TOperator branchOp, TIntermTyped *expression, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000513{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700514 TIntermBranch *node = new TIntermBranch(branchOp, expression);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000515 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000516
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000517 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000518}
519
520//
521// This is to be executed once the final root is put on top by the parsing
522// process.
523//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700524bool TIntermediate::postProcess(TIntermNode *root)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000525{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700526 if (root == NULL)
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000527 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000528
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000529 //
530 // First, finish off the top level sequence, if any
531 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700532 TIntermAggregate *aggRoot = root->getAsAggregate();
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000533 if (aggRoot && aggRoot->getOp() == EOpNull)
alokp@chromium.org58e54292010-08-24 21:40:03 +0000534 aggRoot->setOp(EOpSequence);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000535
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000536 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000537}