blob: 5e29cd2876f220c8c6af3d3fdd1ee1667a40fd81 [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;
Olli Etuahoff805cc2015-02-13 10:59:34 +020083 case EOpIMod:
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;
Olli Etuaho31b5fc62015-01-16 12:13:36 +020090 // Note that for bitwise ops, type checking is done in promote() to
91 // share code between ops and compound assignment
Zhenyao Moe40d1e92014-07-16 17:40:36 -070092 default:
93 break;
alokp@chromium.org2cf17712010-03-30 20:33:18 +000094 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000095
Olli Etuaho31b5fc62015-01-16 12:13:36 +020096 // This check is duplicated between here and node->promote() as an optimization.
97 if (left->getBasicType() != right->getBasicType() && op != EOpBitShiftLeft && op != EOpBitShiftRight)
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -040098 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -070099 return NULL;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000100 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000101
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000102 //
103 // Need a new node holding things together then. Make
104 // one and promote it to the right type.
105 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700106 TIntermBinary *node = new TIntermBinary(op);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000107 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000108
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000109 node->setLeft(left);
110 node->setRight(right);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700111 if (!node->promote(mInfoSink))
112 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000113
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000114 //
115 // See if we can fold constants.
116 //
alokp@chromium.org8f0f24a2010-09-01 21:06:24 +0000117 TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
118 TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700119 if (leftTempConstant && rightTempConstant)
120 {
121 TIntermTyped *typedReturnNode =
122 leftTempConstant->fold(node->getOp(), rightTempConstant, mInfoSink);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000123
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000124 if (typedReturnNode)
125 return typedReturnNode;
126 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000127
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000128 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000129}
130
131//
132// Connect two nodes through an assignment.
133//
134// Returns the added node.
135//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700136TIntermTyped *TIntermediate::addAssign(
137 TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000138{
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -0400139 if (left->getType().getStruct() || right->getType().getStruct())
140 {
141 if (left->getType() != right->getType())
142 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700143 return NULL;
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -0400144 }
145 }
146
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700147 TIntermBinary *node = new TIntermBinary(op);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000148 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000149
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000150 node->setLeft(left);
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -0400151 node->setRight(right);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700152 if (!node->promote(mInfoSink))
153 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000154
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000155 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000156}
157
158//
159// Connect two nodes through an index operator, where the left node is the base
160// of an array or struct, and the right node is a direct or indirect offset.
161//
162// Returns the added node.
163// The caller should set the type of the returned node.
164//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700165TIntermTyped *TIntermediate::addIndex(
166 TOperator op, TIntermTyped *base, TIntermTyped *index, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000167{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700168 TIntermBinary *node = new TIntermBinary(op);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000169 node->setLine(line);
170 node->setLeft(base);
171 node->setRight(index);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000172
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000173 // caller should set the type
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000174
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000175 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000176}
177
178//
179// Add one node as the parent of another that it operates on.
180//
181// Returns the added node.
182//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700183TIntermTyped *TIntermediate::addUnaryMath(
184 TOperator op, TIntermNode *childNode, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000185{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700186 TIntermUnary *node;
187 TIntermTyped *child = childNode->getAsTyped();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000188
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700189 if (child == NULL)
190 {
191 mInfoSink.info.message(EPrefixInternalError, line,
192 "Bad type in AddUnaryMath");
193 return NULL;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000194 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000195
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700196 switch (op)
197 {
198 case EOpLogicalNot:
Olli Etuaho31b5fc62015-01-16 12:13:36 +0200199 if (child->getBasicType() != EbtBool ||
200 child->isMatrix() ||
201 child->isArray() ||
202 child->isVector())
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700203 {
204 return NULL;
205 }
206 break;
Olli Etuaho31b5fc62015-01-16 12:13:36 +0200207 case EOpBitwiseNot:
208 if ((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) ||
209 child->isMatrix() ||
210 child->isArray())
211 {
212 return NULL;
213 }
214 break;
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700215 case EOpPostIncrement:
216 case EOpPreIncrement:
217 case EOpPostDecrement:
218 case EOpPreDecrement:
219 case EOpNegative:
Zhenyao Mode1e00e2014-10-09 16:55:32 -0700220 case EOpPositive:
Olli Etuaho31b5fc62015-01-16 12:13:36 +0200221 if (child->getBasicType() == EbtStruct ||
222 child->isArray())
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700223 {
224 return NULL;
225 }
226 default:
227 break;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000228 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000229
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000230 TIntermConstantUnion *childTempConstant = 0;
231 if (child->getAsConstantUnion())
232 childTempConstant = child->getAsConstantUnion();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000233
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000234 //
235 // Make a new node for the operator.
236 //
237 node = new TIntermUnary(op);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000238 node->setLine(line);
239 node->setOperand(child);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000240
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700241 if (!node->promote(mInfoSink))
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000242 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000243
Olli Etuaho7700ff62015-01-15 12:16:29 +0200244 switch (op)
245 {
246 case EOpPackSnorm2x16:
247 case EOpPackUnorm2x16:
248 case EOpPackHalf2x16:
249 case EOpUnpackSnorm2x16:
250 case EOpUnpackUnorm2x16:
251 node->getTypePointer()->setPrecision(EbpHigh);
252 break;
253 case EOpUnpackHalf2x16:
254 node->getTypePointer()->setPrecision(EbpMedium);
255 break;
256 default:
257 break;
258 }
259
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700260 if (childTempConstant)
261 {
262 TIntermTyped *newChild = childTempConstant->fold(op, 0, mInfoSink);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000263
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000264 if (newChild)
265 return newChild;
266 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000267
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000268 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000269}
270
271//
272// This is the safe way to change the operator on an aggregate, as it
273// does lots of error checking and fixing. Especially for establishing
274// a function call's operation on it's set of parameters. Sequences
275// of instructions are also aggregates, but they just direnctly set
276// their operator to EOpSequence.
277//
278// Returns an aggregate node, which could be the one passed in if
daniel@transgaming.com978702d2012-04-04 15:05:58 +0000279// it was already an aggregate but no operator was set.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000280//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700281TIntermAggregate *TIntermediate::setAggregateOperator(
282 TIntermNode *node, TOperator op, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000283{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700284 TIntermAggregate *aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000285
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000286 //
287 // Make sure we have an aggregate. If not turn it into one.
288 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700289 if (node)
290 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000291 aggNode = node->getAsAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700292 if (aggNode == NULL || aggNode->getOp() != EOpNull)
293 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000294 //
295 // Make an aggregate containing this node.
296 //
297 aggNode = new TIntermAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700298 aggNode->getSequence()->push_back(node);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000299 }
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700300 }
301 else
302 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000303 aggNode = new TIntermAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700304 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000305
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000306 //
307 // Set the operator.
308 //
alokp@chromium.org58e54292010-08-24 21:40:03 +0000309 aggNode->setOp(op);
Jamie Madill075edd82013-07-08 13:30:19 -0400310 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000311
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000312 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000313}
314
315//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000316// Safe way to combine two nodes into an aggregate. Works with null pointers,
317// a node that's not a aggregate yet, etc.
318//
319// Returns the resulting aggregate, unless 0 was passed in for
320// both existing nodes.
321//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700322TIntermAggregate *TIntermediate::growAggregate(
323 TIntermNode *left, TIntermNode *right, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000324{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700325 if (left == NULL && right == NULL)
326 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000327
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700328 TIntermAggregate *aggNode = NULL;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000329 if (left)
330 aggNode = left->getAsAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700331 if (!aggNode || aggNode->getOp() != EOpNull)
332 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000333 aggNode = new TIntermAggregate;
334 if (left)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700335 aggNode->getSequence()->push_back(left);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000336 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000337
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000338 if (right)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700339 aggNode->getSequence()->push_back(right);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000340
Jamie Madill075edd82013-07-08 13:30:19 -0400341 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000342
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000343 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000344}
345
346//
347// Turn an existing node into an aggregate.
348//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700349// Returns an aggregate, unless NULL was passed in for the existing node.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000350//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700351TIntermAggregate *TIntermediate::makeAggregate(
352 TIntermNode *node, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000353{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700354 if (node == NULL)
355 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000356
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700357 TIntermAggregate *aggNode = new TIntermAggregate;
358 aggNode->getSequence()->push_back(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000359
Jamie Madill075edd82013-07-08 13:30:19 -0400360 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000361
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000362 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000363}
364
365//
366// For "if" test nodes. There are three children; a condition,
367// a true path, and a false path. The two paths are in the
368// nodePair.
369//
370// Returns the selection node created.
371//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700372TIntermNode *TIntermediate::addSelection(
373 TIntermTyped *cond, TIntermNodePair nodePair, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000374{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000375 //
376 // For compile time constant selections, prune the code and
377 // test now.
378 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000379
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700380 if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion())
381 {
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +0000382 if (cond->getAsConstantUnion()->getBConst(0) == true)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700383 {
384 return nodePair.node1 ? setAggregateOperator(
385 nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL;
386 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000387 else
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700388 {
389 return nodePair.node2 ? setAggregateOperator(
390 nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL;
391 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000392 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000393
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700394 TIntermSelection *node = new TIntermSelection(
395 cond, nodePair.node1, nodePair.node2);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000396 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000397
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000398 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000399}
400
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700401TIntermTyped *TIntermediate::addComma(
402 TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000403{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700404 if (left->getType().getQualifier() == EvqConst &&
405 right->getType().getQualifier() == EvqConst)
406 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000407 return right;
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700408 }
409 else
410 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000411 TIntermTyped *commaAggregate = growAggregate(left, right, line);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000412 commaAggregate->getAsAggregate()->setOp(EOpComma);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000413 commaAggregate->setType(right->getType());
alokp@chromium.org58e54292010-08-24 21:40:03 +0000414 commaAggregate->getTypePointer()->setQualifier(EvqTemporary);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000415 return commaAggregate;
416 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000417}
418
419//
420// For "?:" test nodes. There are three children; a condition,
421// a true path, and a false path. The two paths are specified
422// as separate parameters.
423//
424// Returns the selection node created, or 0 if one could not be.
425//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700426TIntermTyped *TIntermediate::addSelection(
427 TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock,
428 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000429{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700430 if (!cond || !trueBlock || !falseBlock ||
431 trueBlock->getType() != falseBlock->getType())
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -0400432 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700433 return NULL;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000434 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000435
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000436 //
437 // See if all the operands are constant, then fold it otherwise not.
438 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000439
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700440 if (cond->getAsConstantUnion() &&
441 trueBlock->getAsConstantUnion() &&
442 falseBlock->getAsConstantUnion())
443 {
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +0000444 if (cond->getAsConstantUnion()->getBConst(0))
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000445 return trueBlock;
446 else
447 return falseBlock;
448 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000449
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000450 //
451 // Make a selection node.
452 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700453 TIntermSelection *node = new TIntermSelection(
454 cond, trueBlock, falseBlock, trueBlock->getType());
daniel@transgaming.com43affc52012-03-28 14:55:39 +0000455 node->getTypePointer()->setQualifier(EvqTemporary);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000456 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000457
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000458 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000459}
460
461//
462// Constant terminal nodes. Has a union that contains bool, float or int constants
463//
464// Returns the constant union node created.
465//
466
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700467TIntermConstantUnion *TIntermediate::addConstantUnion(
468 ConstantUnion *unionArrayPointer, const TType &t, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000469{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700470 TIntermConstantUnion *node = new TIntermConstantUnion(unionArrayPointer, t);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000471 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000472
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000473 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000474}
475
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700476TIntermTyped *TIntermediate::addSwizzle(
477 TVectorFields &fields, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000478{
479
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700480 TIntermAggregate *node = new TIntermAggregate(EOpSequence);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000481
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000482 node->setLine(line);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700483 TIntermConstantUnion *constIntNode;
484 TIntermSequence *sequenceVector = node->getSequence();
485 ConstantUnion *unionArray;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000486
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700487 for (int i = 0; i < fields.num; i++)
488 {
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000489 unionArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000490 unionArray->setIConst(fields.offsets[i]);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700491 constIntNode = addConstantUnion(
492 unionArray, TType(EbtInt, EbpUndefined, EvqConst), line);
493 sequenceVector->push_back(constIntNode);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000494 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000495
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000496 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000497}
498
499//
500// Create loop nodes.
501//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700502TIntermNode *TIntermediate::addLoop(
503 TLoopType type, TIntermNode *init, TIntermTyped *cond, TIntermTyped *expr,
504 TIntermNode *body, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000505{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700506 TIntermNode *node = new TIntermLoop(type, init, cond, expr, body);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000507 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000508
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000509 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000510}
511
512//
513// Add branches.
514//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700515TIntermBranch* TIntermediate::addBranch(
516 TOperator branchOp, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000517{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000518 return addBranch(branchOp, 0, line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000519}
520
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700521TIntermBranch* TIntermediate::addBranch(
522 TOperator branchOp, TIntermTyped *expression, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000523{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700524 TIntermBranch *node = new TIntermBranch(branchOp, expression);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000525 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000526
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000527 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000528}
529
530//
531// This is to be executed once the final root is put on top by the parsing
532// process.
533//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700534bool TIntermediate::postProcess(TIntermNode *root)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000535{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700536 if (root == NULL)
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000537 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000538
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000539 //
540 // First, finish off the top level sequence, if any
541 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700542 TIntermAggregate *aggRoot = root->getAsAggregate();
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000543 if (aggRoot && aggRoot->getOp() == EOpNull)
alokp@chromium.org58e54292010-08-24 21:40:03 +0000544 aggRoot->setOp(EOpSequence);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000545
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000546 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000547}