blob: 5e0edfde55097ee3a2d177d08482b3a95ad68330 [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -04002// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7//
8// Build the intermediate representation.
9//
10
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000011#include <float.h>
alokp@chromium.org1bcc3fd2010-05-19 17:08:44 +000012#include <limits.h>
alokp@chromium.org32cfaf42010-08-23 21:01:13 +000013#include <algorithm>
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000014
Jamie Madillb1a85f42014-08-19 15:23:24 -040015#include "compiler/translator/Intermediate.h"
Geoff Lang17732822013-08-29 13:46:49 -040016#include "compiler/translator/SymbolTable.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000017
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000018////////////////////////////////////////////////////////////////////////////
19//
20// First set of functions are to help build the intermediate representation.
21// These functions are not member functions of the nodes.
22// They are called from parser productions.
23//
24/////////////////////////////////////////////////////////////////////////////
25
26//
27// Add a terminal node for an identifier in an expression.
28//
29// Returns the added node.
30//
Zhenyao Moe40d1e92014-07-16 17:40:36 -070031TIntermSymbol *TIntermediate::addSymbol(
32 int id, const TString &name, const TType &type, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000033{
Zhenyao Moe40d1e92014-07-16 17:40:36 -070034 TIntermSymbol *node = new TIntermSymbol(id, name, type);
alokp@chromium.org2cf17712010-03-30 20:33:18 +000035 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000036
alokp@chromium.org2cf17712010-03-30 20:33:18 +000037 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000038}
39
40//
41// Connect two nodes with a new parent that does a binary operation on the nodes.
42//
43// Returns the added node.
44//
Zhenyao Moe40d1e92014-07-16 17:40:36 -070045TIntermTyped *TIntermediate::addBinaryMath(
46 TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000047{
alokp@chromium.org2cf17712010-03-30 20:33:18 +000048 //
49 // Need a new node holding things together then. Make
50 // one and promote it to the right type.
51 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -070052 TIntermBinary *node = new TIntermBinary(op);
alokp@chromium.org2cf17712010-03-30 20:33:18 +000053 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000054
alokp@chromium.org2cf17712010-03-30 20:33:18 +000055 node->setLeft(left);
56 node->setRight(right);
Zhenyao Moe40d1e92014-07-16 17:40:36 -070057 if (!node->promote(mInfoSink))
58 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000059
alokp@chromium.org2cf17712010-03-30 20:33:18 +000060 //
61 // See if we can fold constants.
62 //
alokp@chromium.org8f0f24a2010-09-01 21:06:24 +000063 TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
64 TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
Zhenyao Moe40d1e92014-07-16 17:40:36 -070065 if (leftTempConstant && rightTempConstant)
66 {
67 TIntermTyped *typedReturnNode =
68 leftTempConstant->fold(node->getOp(), rightTempConstant, mInfoSink);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000069
alokp@chromium.org2cf17712010-03-30 20:33:18 +000070 if (typedReturnNode)
71 return typedReturnNode;
72 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000073
alokp@chromium.org2cf17712010-03-30 20:33:18 +000074 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000075}
76
77//
78// Connect two nodes through an assignment.
79//
80// Returns the added node.
81//
Zhenyao Moe40d1e92014-07-16 17:40:36 -070082TIntermTyped *TIntermediate::addAssign(
83 TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000084{
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -040085 if (left->getType().getStruct() || right->getType().getStruct())
86 {
87 if (left->getType() != right->getType())
88 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -070089 return NULL;
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -040090 }
91 }
92
Zhenyao Moe40d1e92014-07-16 17:40:36 -070093 TIntermBinary *node = new TIntermBinary(op);
alokp@chromium.org2cf17712010-03-30 20:33:18 +000094 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000095
alokp@chromium.org2cf17712010-03-30 20:33:18 +000096 node->setLeft(left);
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -040097 node->setRight(right);
Zhenyao Moe40d1e92014-07-16 17:40:36 -070098 if (!node->promote(mInfoSink))
99 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000100
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000101 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000102}
103
104//
105// Connect two nodes through an index operator, where the left node is the base
106// of an array or struct, and the right node is a direct or indirect offset.
107//
108// Returns the added node.
109// The caller should set the type of the returned node.
110//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700111TIntermTyped *TIntermediate::addIndex(
112 TOperator op, TIntermTyped *base, TIntermTyped *index, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000113{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700114 TIntermBinary *node = new TIntermBinary(op);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000115 node->setLine(line);
116 node->setLeft(base);
117 node->setRight(index);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000118
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000119 // caller should set the type
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000120
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000121 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000122}
123
124//
125// Add one node as the parent of another that it operates on.
126//
127// Returns the added node.
128//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700129TIntermTyped *TIntermediate::addUnaryMath(
130 TOperator op, TIntermNode *childNode, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000131{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700132 TIntermUnary *node;
133 TIntermTyped *child = childNode->getAsTyped();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000134
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700135 if (child == NULL)
136 {
137 mInfoSink.info.message(EPrefixInternalError, line,
138 "Bad type in AddUnaryMath");
139 return NULL;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000140 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000141
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700142 switch (op)
143 {
144 case EOpLogicalNot:
Olli Etuaho31b5fc62015-01-16 12:13:36 +0200145 if (child->getBasicType() != EbtBool ||
146 child->isMatrix() ||
147 child->isArray() ||
148 child->isVector())
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700149 {
150 return NULL;
151 }
152 break;
Olli Etuaho31b5fc62015-01-16 12:13:36 +0200153 case EOpBitwiseNot:
154 if ((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) ||
155 child->isMatrix() ||
156 child->isArray())
157 {
158 return NULL;
159 }
160 break;
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700161 case EOpPostIncrement:
162 case EOpPreIncrement:
163 case EOpPostDecrement:
164 case EOpPreDecrement:
165 case EOpNegative:
Zhenyao Mode1e00e2014-10-09 16:55:32 -0700166 case EOpPositive:
Olli Etuaho31b5fc62015-01-16 12:13:36 +0200167 if (child->getBasicType() == EbtStruct ||
168 child->isArray())
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700169 {
170 return NULL;
171 }
172 default:
173 break;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000174 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000175
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000176 TIntermConstantUnion *childTempConstant = 0;
177 if (child->getAsConstantUnion())
178 childTempConstant = child->getAsConstantUnion();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000179
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000180 //
181 // Make a new node for the operator.
182 //
183 node = new TIntermUnary(op);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000184 node->setLine(line);
185 node->setOperand(child);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000186
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700187 if (!node->promote(mInfoSink))
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000188 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000189
Olli Etuaho7700ff62015-01-15 12:16:29 +0200190 switch (op)
191 {
192 case EOpPackSnorm2x16:
193 case EOpPackUnorm2x16:
194 case EOpPackHalf2x16:
195 case EOpUnpackSnorm2x16:
196 case EOpUnpackUnorm2x16:
197 node->getTypePointer()->setPrecision(EbpHigh);
198 break;
199 case EOpUnpackHalf2x16:
200 node->getTypePointer()->setPrecision(EbpMedium);
201 break;
202 default:
203 break;
204 }
205
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700206 if (childTempConstant)
207 {
208 TIntermTyped *newChild = childTempConstant->fold(op, 0, mInfoSink);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000209
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000210 if (newChild)
211 return newChild;
212 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000213
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000214 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000215}
216
217//
218// This is the safe way to change the operator on an aggregate, as it
219// does lots of error checking and fixing. Especially for establishing
220// a function call's operation on it's set of parameters. Sequences
221// of instructions are also aggregates, but they just direnctly set
222// their operator to EOpSequence.
223//
224// Returns an aggregate node, which could be the one passed in if
daniel@transgaming.com978702d2012-04-04 15:05:58 +0000225// it was already an aggregate but no operator was set.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000226//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700227TIntermAggregate *TIntermediate::setAggregateOperator(
228 TIntermNode *node, TOperator op, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000229{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700230 TIntermAggregate *aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000231
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000232 //
233 // Make sure we have an aggregate. If not turn it into one.
234 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700235 if (node)
236 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000237 aggNode = node->getAsAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700238 if (aggNode == NULL || aggNode->getOp() != EOpNull)
239 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000240 //
241 // Make an aggregate containing this node.
242 //
243 aggNode = new TIntermAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700244 aggNode->getSequence()->push_back(node);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000245 }
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700246 }
247 else
248 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000249 aggNode = new TIntermAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700250 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000251
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000252 //
253 // Set the operator.
254 //
alokp@chromium.org58e54292010-08-24 21:40:03 +0000255 aggNode->setOp(op);
Jamie Madill075edd82013-07-08 13:30:19 -0400256 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000257
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000258 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000259}
260
261//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000262// Safe way to combine two nodes into an aggregate. Works with null pointers,
263// a node that's not a aggregate yet, etc.
264//
265// Returns the resulting aggregate, unless 0 was passed in for
266// both existing nodes.
267//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700268TIntermAggregate *TIntermediate::growAggregate(
269 TIntermNode *left, TIntermNode *right, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000270{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700271 if (left == NULL && right == NULL)
272 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000273
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700274 TIntermAggregate *aggNode = NULL;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000275 if (left)
276 aggNode = left->getAsAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700277 if (!aggNode || aggNode->getOp() != EOpNull)
278 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000279 aggNode = new TIntermAggregate;
280 if (left)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700281 aggNode->getSequence()->push_back(left);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000282 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000283
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000284 if (right)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700285 aggNode->getSequence()->push_back(right);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000286
Jamie Madill075edd82013-07-08 13:30:19 -0400287 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000288
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000289 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000290}
291
292//
293// Turn an existing node into an aggregate.
294//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700295// Returns an aggregate, unless NULL was passed in for the existing node.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000296//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700297TIntermAggregate *TIntermediate::makeAggregate(
298 TIntermNode *node, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000299{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700300 if (node == NULL)
301 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000302
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700303 TIntermAggregate *aggNode = new TIntermAggregate;
304 aggNode->getSequence()->push_back(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000305
Jamie Madill075edd82013-07-08 13:30:19 -0400306 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000307
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000308 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000309}
310
311//
312// For "if" test nodes. There are three children; a condition,
313// a true path, and a false path. The two paths are in the
314// nodePair.
315//
316// Returns the selection node created.
317//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700318TIntermNode *TIntermediate::addSelection(
319 TIntermTyped *cond, TIntermNodePair nodePair, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000320{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000321 //
322 // For compile time constant selections, prune the code and
323 // test now.
324 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000325
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700326 if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion())
327 {
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +0000328 if (cond->getAsConstantUnion()->getBConst(0) == true)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700329 {
330 return nodePair.node1 ? setAggregateOperator(
331 nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL;
332 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000333 else
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700334 {
335 return nodePair.node2 ? setAggregateOperator(
336 nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL;
337 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000338 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000339
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700340 TIntermSelection *node = new TIntermSelection(
341 cond, nodePair.node1, nodePair.node2);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000342 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000343
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000344 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000345}
346
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700347TIntermTyped *TIntermediate::addComma(
348 TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000349{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700350 if (left->getType().getQualifier() == EvqConst &&
351 right->getType().getQualifier() == EvqConst)
352 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000353 return right;
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700354 }
355 else
356 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000357 TIntermTyped *commaAggregate = growAggregate(left, right, line);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000358 commaAggregate->getAsAggregate()->setOp(EOpComma);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000359 commaAggregate->setType(right->getType());
alokp@chromium.org58e54292010-08-24 21:40:03 +0000360 commaAggregate->getTypePointer()->setQualifier(EvqTemporary);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000361 return commaAggregate;
362 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000363}
364
365//
366// For "?:" test nodes. There are three children; a condition,
367// a true path, and a false path. The two paths are specified
368// as separate parameters.
369//
370// Returns the selection node created, or 0 if one could not be.
371//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700372TIntermTyped *TIntermediate::addSelection(
373 TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock,
374 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000375{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700376 if (!cond || !trueBlock || !falseBlock ||
377 trueBlock->getType() != falseBlock->getType())
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -0400378 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700379 return NULL;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000380 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000381
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000382 //
383 // See if all the operands are constant, then fold it otherwise not.
384 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000385
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700386 if (cond->getAsConstantUnion() &&
387 trueBlock->getAsConstantUnion() &&
388 falseBlock->getAsConstantUnion())
389 {
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +0000390 if (cond->getAsConstantUnion()->getBConst(0))
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000391 return trueBlock;
392 else
393 return falseBlock;
394 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000395
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000396 //
397 // Make a selection node.
398 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700399 TIntermSelection *node = new TIntermSelection(
400 cond, trueBlock, falseBlock, trueBlock->getType());
daniel@transgaming.com43affc52012-03-28 14:55:39 +0000401 node->getTypePointer()->setQualifier(EvqTemporary);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000402 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000403
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000404 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000405}
406
Olli Etuahoa3a36662015-02-17 13:46:51 +0200407TIntermSwitch *TIntermediate::addSwitch(
408 TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &line)
409{
Olli Etuaho3c1dfb52015-02-20 11:34:03 +0200410 TIntermSwitch *node = new TIntermSwitch(init, statementList);
411 node->setLine(line);
412
413 return node;
Olli Etuahoa3a36662015-02-17 13:46:51 +0200414}
415
416TIntermCase *TIntermediate::addCase(
417 TIntermTyped *condition, const TSourceLoc &line)
418{
Olli Etuaho3c1dfb52015-02-20 11:34:03 +0200419 TIntermCase *node = new TIntermCase(condition);
420 node->setLine(line);
421
422 return node;
Olli Etuahoa3a36662015-02-17 13:46:51 +0200423}
424
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000425//
426// Constant terminal nodes. Has a union that contains bool, float or int constants
427//
428// Returns the constant union node created.
429//
430
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700431TIntermConstantUnion *TIntermediate::addConstantUnion(
432 ConstantUnion *unionArrayPointer, const TType &t, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000433{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700434 TIntermConstantUnion *node = new TIntermConstantUnion(unionArrayPointer, t);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000435 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000436
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000437 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000438}
439
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700440TIntermTyped *TIntermediate::addSwizzle(
441 TVectorFields &fields, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000442{
443
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700444 TIntermAggregate *node = new TIntermAggregate(EOpSequence);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000445
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000446 node->setLine(line);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700447 TIntermConstantUnion *constIntNode;
448 TIntermSequence *sequenceVector = node->getSequence();
449 ConstantUnion *unionArray;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000450
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700451 for (int i = 0; i < fields.num; i++)
452 {
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000453 unionArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000454 unionArray->setIConst(fields.offsets[i]);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700455 constIntNode = addConstantUnion(
456 unionArray, TType(EbtInt, EbpUndefined, EvqConst), line);
457 sequenceVector->push_back(constIntNode);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000458 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000459
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000460 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000461}
462
463//
464// Create loop nodes.
465//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700466TIntermNode *TIntermediate::addLoop(
467 TLoopType type, TIntermNode *init, TIntermTyped *cond, TIntermTyped *expr,
468 TIntermNode *body, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000469{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700470 TIntermNode *node = new TIntermLoop(type, init, cond, expr, body);
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
476//
477// Add branches.
478//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700479TIntermBranch* TIntermediate::addBranch(
480 TOperator branchOp, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000481{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000482 return addBranch(branchOp, 0, line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000483}
484
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700485TIntermBranch* TIntermediate::addBranch(
486 TOperator branchOp, TIntermTyped *expression, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000487{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700488 TIntermBranch *node = new TIntermBranch(branchOp, expression);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000489 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000490
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000491 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000492}
493
494//
495// This is to be executed once the final root is put on top by the parsing
496// process.
497//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700498bool TIntermediate::postProcess(TIntermNode *root)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000499{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700500 if (root == NULL)
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000501 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000502
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000503 //
504 // First, finish off the top level sequence, if any
505 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700506 TIntermAggregate *aggRoot = root->getAsAggregate();
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000507 if (aggRoot && aggRoot->getOp() == EOpNull)
alokp@chromium.org58e54292010-08-24 21:40:03 +0000508 aggRoot->setOp(EOpSequence);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000509
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000510 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000511}