blob: fd0038df94c473245dffc0117e59feb784f57b6c [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 {
Olli Etuaho5e5c8262015-03-26 14:04:54 +0200192 case EOpFloatBitsToInt:
193 case EOpFloatBitsToUint:
194 case EOpIntBitsToFloat:
195 case EOpUintBitsToFloat:
Olli Etuaho7700ff62015-01-15 12:16:29 +0200196 case EOpPackSnorm2x16:
197 case EOpPackUnorm2x16:
198 case EOpPackHalf2x16:
199 case EOpUnpackSnorm2x16:
200 case EOpUnpackUnorm2x16:
201 node->getTypePointer()->setPrecision(EbpHigh);
202 break;
203 case EOpUnpackHalf2x16:
204 node->getTypePointer()->setPrecision(EbpMedium);
205 break;
206 default:
207 break;
208 }
209
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700210 if (childTempConstant)
211 {
212 TIntermTyped *newChild = childTempConstant->fold(op, 0, mInfoSink);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000213
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000214 if (newChild)
215 return newChild;
216 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000217
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000218 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000219}
220
221//
222// This is the safe way to change the operator on an aggregate, as it
223// does lots of error checking and fixing. Especially for establishing
224// a function call's operation on it's set of parameters. Sequences
225// of instructions are also aggregates, but they just direnctly set
226// their operator to EOpSequence.
227//
228// Returns an aggregate node, which could be the one passed in if
daniel@transgaming.com978702d2012-04-04 15:05:58 +0000229// it was already an aggregate but no operator was set.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000230//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700231TIntermAggregate *TIntermediate::setAggregateOperator(
232 TIntermNode *node, TOperator op, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000233{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700234 TIntermAggregate *aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000235
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000236 //
237 // Make sure we have an aggregate. If not turn it into one.
238 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700239 if (node)
240 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000241 aggNode = node->getAsAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700242 if (aggNode == NULL || aggNode->getOp() != EOpNull)
243 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000244 //
245 // Make an aggregate containing this node.
246 //
247 aggNode = new TIntermAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700248 aggNode->getSequence()->push_back(node);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000249 }
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700250 }
251 else
252 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000253 aggNode = new TIntermAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700254 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000255
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000256 //
257 // Set the operator.
258 //
alokp@chromium.org58e54292010-08-24 21:40:03 +0000259 aggNode->setOp(op);
Jamie Madill075edd82013-07-08 13:30:19 -0400260 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000261
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000262 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000263}
264
265//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000266// Safe way to combine two nodes into an aggregate. Works with null pointers,
267// a node that's not a aggregate yet, etc.
268//
269// Returns the resulting aggregate, unless 0 was passed in for
270// both existing nodes.
271//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700272TIntermAggregate *TIntermediate::growAggregate(
273 TIntermNode *left, TIntermNode *right, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000274{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700275 if (left == NULL && right == NULL)
276 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000277
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700278 TIntermAggregate *aggNode = NULL;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000279 if (left)
280 aggNode = left->getAsAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700281 if (!aggNode || aggNode->getOp() != EOpNull)
282 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000283 aggNode = new TIntermAggregate;
284 if (left)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700285 aggNode->getSequence()->push_back(left);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000286 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000287
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000288 if (right)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700289 aggNode->getSequence()->push_back(right);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000290
Jamie Madill075edd82013-07-08 13:30:19 -0400291 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000292
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000293 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000294}
295
296//
297// Turn an existing node into an aggregate.
298//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700299// Returns an aggregate, unless NULL was passed in for the existing node.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000300//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700301TIntermAggregate *TIntermediate::makeAggregate(
302 TIntermNode *node, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000303{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700304 if (node == NULL)
305 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000306
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700307 TIntermAggregate *aggNode = new TIntermAggregate;
308 aggNode->getSequence()->push_back(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000309
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//
316// For "if" test nodes. There are three children; a condition,
317// a true path, and a false path. The two paths are in the
318// nodePair.
319//
320// Returns the selection node created.
321//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700322TIntermNode *TIntermediate::addSelection(
323 TIntermTyped *cond, TIntermNodePair nodePair, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000324{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000325 //
326 // For compile time constant selections, prune the code and
327 // test now.
328 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000329
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700330 if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion())
331 {
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +0000332 if (cond->getAsConstantUnion()->getBConst(0) == true)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700333 {
334 return nodePair.node1 ? setAggregateOperator(
335 nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL;
336 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000337 else
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700338 {
339 return nodePair.node2 ? setAggregateOperator(
340 nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL;
341 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000342 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000343
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700344 TIntermSelection *node = new TIntermSelection(
345 cond, nodePair.node1, nodePair.node2);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000346 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000347
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000348 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000349}
350
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700351TIntermTyped *TIntermediate::addComma(
352 TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000353{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700354 if (left->getType().getQualifier() == EvqConst &&
355 right->getType().getQualifier() == EvqConst)
356 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000357 return right;
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700358 }
359 else
360 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000361 TIntermTyped *commaAggregate = growAggregate(left, right, line);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000362 commaAggregate->getAsAggregate()->setOp(EOpComma);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000363 commaAggregate->setType(right->getType());
alokp@chromium.org58e54292010-08-24 21:40:03 +0000364 commaAggregate->getTypePointer()->setQualifier(EvqTemporary);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000365 return commaAggregate;
366 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000367}
368
369//
370// For "?:" test nodes. There are three children; a condition,
371// a true path, and a false path. The two paths are specified
372// as separate parameters.
373//
374// Returns the selection node created, or 0 if one could not be.
375//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700376TIntermTyped *TIntermediate::addSelection(
377 TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock,
378 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000379{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700380 if (!cond || !trueBlock || !falseBlock ||
381 trueBlock->getType() != falseBlock->getType())
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -0400382 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700383 return NULL;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000384 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000385
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000386 //
387 // See if all the operands are constant, then fold it otherwise not.
388 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000389
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700390 if (cond->getAsConstantUnion() &&
391 trueBlock->getAsConstantUnion() &&
392 falseBlock->getAsConstantUnion())
393 {
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +0000394 if (cond->getAsConstantUnion()->getBConst(0))
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000395 return trueBlock;
396 else
397 return falseBlock;
398 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000399
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000400 //
401 // Make a selection node.
402 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700403 TIntermSelection *node = new TIntermSelection(
404 cond, trueBlock, falseBlock, trueBlock->getType());
daniel@transgaming.com43affc52012-03-28 14:55:39 +0000405 node->getTypePointer()->setQualifier(EvqTemporary);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000406 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000407
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000408 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000409}
410
Olli Etuahoa3a36662015-02-17 13:46:51 +0200411TIntermSwitch *TIntermediate::addSwitch(
412 TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &line)
413{
Olli Etuaho3c1dfb52015-02-20 11:34:03 +0200414 TIntermSwitch *node = new TIntermSwitch(init, statementList);
415 node->setLine(line);
416
417 return node;
Olli Etuahoa3a36662015-02-17 13:46:51 +0200418}
419
420TIntermCase *TIntermediate::addCase(
421 TIntermTyped *condition, const TSourceLoc &line)
422{
Olli Etuaho3c1dfb52015-02-20 11:34:03 +0200423 TIntermCase *node = new TIntermCase(condition);
424 node->setLine(line);
425
426 return node;
Olli Etuahoa3a36662015-02-17 13:46:51 +0200427}
428
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000429//
430// Constant terminal nodes. Has a union that contains bool, float or int constants
431//
432// Returns the constant union node created.
433//
434
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700435TIntermConstantUnion *TIntermediate::addConstantUnion(
436 ConstantUnion *unionArrayPointer, const TType &t, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000437{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700438 TIntermConstantUnion *node = new TIntermConstantUnion(unionArrayPointer, t);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000439 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000440
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000441 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000442}
443
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700444TIntermTyped *TIntermediate::addSwizzle(
445 TVectorFields &fields, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000446{
447
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700448 TIntermAggregate *node = new TIntermAggregate(EOpSequence);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000449
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000450 node->setLine(line);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700451 TIntermConstantUnion *constIntNode;
452 TIntermSequence *sequenceVector = node->getSequence();
453 ConstantUnion *unionArray;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000454
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700455 for (int i = 0; i < fields.num; i++)
456 {
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000457 unionArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000458 unionArray->setIConst(fields.offsets[i]);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700459 constIntNode = addConstantUnion(
460 unionArray, TType(EbtInt, EbpUndefined, EvqConst), line);
461 sequenceVector->push_back(constIntNode);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000462 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000463
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000464 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000465}
466
467//
468// Create loop nodes.
469//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700470TIntermNode *TIntermediate::addLoop(
471 TLoopType type, TIntermNode *init, TIntermTyped *cond, TIntermTyped *expr,
472 TIntermNode *body, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000473{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700474 TIntermNode *node = new TIntermLoop(type, init, cond, expr, body);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000475 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000476
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000477 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000478}
479
480//
481// Add branches.
482//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700483TIntermBranch* TIntermediate::addBranch(
484 TOperator branchOp, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000485{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000486 return addBranch(branchOp, 0, line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000487}
488
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700489TIntermBranch* TIntermediate::addBranch(
490 TOperator branchOp, TIntermTyped *expression, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000491{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700492 TIntermBranch *node = new TIntermBranch(branchOp, expression);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000493 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000494
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000495 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000496}
497
498//
499// This is to be executed once the final root is put on top by the parsing
500// process.
501//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700502bool TIntermediate::postProcess(TIntermNode *root)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000503{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700504 if (root == NULL)
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000505 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000506
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000507 //
508 // First, finish off the top level sequence, if any
509 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700510 TIntermAggregate *aggRoot = root->getAsAggregate();
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000511 if (aggRoot && aggRoot->getOp() == EOpNull)
alokp@chromium.org58e54292010-08-24 21:40:03 +0000512 aggRoot->setOp(EOpSequence);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000513
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000514 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000515}