blob: e558683c559cc952de815a7e44da74bab663d426 [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/RemoveTree.h"
17#include "compiler/translator/SymbolTable.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000018
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000019////////////////////////////////////////////////////////////////////////////
20//
21// First set of functions are to help build the intermediate representation.
22// These functions are not member functions of the nodes.
23// They are called from parser productions.
24//
25/////////////////////////////////////////////////////////////////////////////
26
27//
28// Add a terminal node for an identifier in an expression.
29//
30// Returns the added node.
31//
Zhenyao Moe40d1e92014-07-16 17:40:36 -070032TIntermSymbol *TIntermediate::addSymbol(
33 int id, const TString &name, const TType &type, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000034{
Zhenyao Moe40d1e92014-07-16 17:40:36 -070035 TIntermSymbol *node = new TIntermSymbol(id, name, type);
alokp@chromium.org2cf17712010-03-30 20:33:18 +000036 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000037
alokp@chromium.org2cf17712010-03-30 20:33:18 +000038 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000039}
40
41//
42// Connect two nodes with a new parent that does a binary operation on the nodes.
43//
44// Returns the added node.
45//
Zhenyao Moe40d1e92014-07-16 17:40:36 -070046TIntermTyped *TIntermediate::addBinaryMath(
47 TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000048{
Zhenyao Moe40d1e92014-07-16 17:40:36 -070049 switch (op)
50 {
51 case EOpEqual:
52 case EOpNotEqual:
53 if (left->isArray())
54 return NULL;
55 break;
56 case EOpLessThan:
57 case EOpGreaterThan:
58 case EOpLessThanEqual:
59 case EOpGreaterThanEqual:
60 if (left->isMatrix() || left->isArray() || left->isVector() ||
61 left->getBasicType() == EbtStruct)
62 {
63 return NULL;
64 }
65 break;
66 case EOpLogicalOr:
67 case EOpLogicalXor:
68 case EOpLogicalAnd:
69 if (left->getBasicType() != EbtBool ||
70 left->isMatrix() || left->isArray() || left->isVector())
71 {
72 return NULL;
73 }
74 break;
75 case EOpAdd:
76 case EOpSub:
77 case EOpDiv:
78 case EOpMul:
79 if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool)
80 return NULL;
81 default:
82 break;
alokp@chromium.org2cf17712010-03-30 20:33:18 +000083 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000084
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -040085 if (left->getBasicType() != right->getBasicType())
86 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -070087 return NULL;
alokp@chromium.org2cf17712010-03-30 20:33:18 +000088 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000089
alokp@chromium.org2cf17712010-03-30 20:33:18 +000090 //
91 // Need a new node holding things together then. Make
92 // one and promote it to the right type.
93 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -070094 TIntermBinary *node = new TIntermBinary(op);
alokp@chromium.org2cf17712010-03-30 20:33:18 +000095 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000096
alokp@chromium.org2cf17712010-03-30 20:33:18 +000097 node->setLeft(left);
98 node->setRight(right);
Zhenyao Moe40d1e92014-07-16 17:40:36 -070099 if (!node->promote(mInfoSink))
100 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000101
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000102 //
103 // See if we can fold constants.
104 //
alokp@chromium.org8f0f24a2010-09-01 21:06:24 +0000105 TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
106 TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700107 if (leftTempConstant && rightTempConstant)
108 {
109 TIntermTyped *typedReturnNode =
110 leftTempConstant->fold(node->getOp(), rightTempConstant, mInfoSink);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000111
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000112 if (typedReturnNode)
113 return typedReturnNode;
114 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000115
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000116 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000117}
118
119//
120// Connect two nodes through an assignment.
121//
122// Returns the added node.
123//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700124TIntermTyped *TIntermediate::addAssign(
125 TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000126{
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -0400127 if (left->getType().getStruct() || right->getType().getStruct())
128 {
129 if (left->getType() != right->getType())
130 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700131 return NULL;
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -0400132 }
133 }
134
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700135 TIntermBinary *node = new TIntermBinary(op);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000136 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000137
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000138 node->setLeft(left);
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -0400139 node->setRight(right);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700140 if (!node->promote(mInfoSink))
141 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000142
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000143 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000144}
145
146//
147// Connect two nodes through an index operator, where the left node is the base
148// of an array or struct, and the right node is a direct or indirect offset.
149//
150// Returns the added node.
151// The caller should set the type of the returned node.
152//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700153TIntermTyped *TIntermediate::addIndex(
154 TOperator op, TIntermTyped *base, TIntermTyped *index, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000155{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700156 TIntermBinary *node = new TIntermBinary(op);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000157 node->setLine(line);
158 node->setLeft(base);
159 node->setRight(index);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000160
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000161 // caller should set the type
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000162
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000163 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000164}
165
166//
167// Add one node as the parent of another that it operates on.
168//
169// Returns the added node.
170//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700171TIntermTyped *TIntermediate::addUnaryMath(
172 TOperator op, TIntermNode *childNode, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000173{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700174 TIntermUnary *node;
175 TIntermTyped *child = childNode->getAsTyped();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000176
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700177 if (child == NULL)
178 {
179 mInfoSink.info.message(EPrefixInternalError, line,
180 "Bad type in AddUnaryMath");
181 return NULL;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000182 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000183
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700184 switch (op)
185 {
186 case EOpLogicalNot:
187 if (child->getType().getBasicType() != EbtBool ||
188 child->getType().isMatrix() ||
189 child->getType().isArray() ||
190 child->getType().isVector())
191 {
192 return NULL;
193 }
194 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000195
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700196 case EOpPostIncrement:
197 case EOpPreIncrement:
198 case EOpPostDecrement:
199 case EOpPreDecrement:
200 case EOpNegative:
Zhenyao Mode1e00e2014-10-09 16:55:32 -0700201 case EOpPositive:
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700202 if (child->getType().getBasicType() == EbtStruct ||
203 child->getType().isArray())
204 {
205 return NULL;
206 }
207 default:
208 break;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000209 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000210
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000211 TIntermConstantUnion *childTempConstant = 0;
212 if (child->getAsConstantUnion())
213 childTempConstant = child->getAsConstantUnion();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000214
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000215 //
216 // Make a new node for the operator.
217 //
218 node = new TIntermUnary(op);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000219 node->setLine(line);
220 node->setOperand(child);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000221
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700222 if (!node->promote(mInfoSink))
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000223 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000224
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700225 if (childTempConstant)
226 {
227 TIntermTyped *newChild = childTempConstant->fold(op, 0, mInfoSink);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000228
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000229 if (newChild)
230 return newChild;
231 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000232
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000233 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000234}
235
236//
237// This is the safe way to change the operator on an aggregate, as it
238// does lots of error checking and fixing. Especially for establishing
239// a function call's operation on it's set of parameters. Sequences
240// of instructions are also aggregates, but they just direnctly set
241// their operator to EOpSequence.
242//
243// Returns an aggregate node, which could be the one passed in if
daniel@transgaming.com978702d2012-04-04 15:05:58 +0000244// it was already an aggregate but no operator was set.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000245//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700246TIntermAggregate *TIntermediate::setAggregateOperator(
247 TIntermNode *node, TOperator op, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000248{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700249 TIntermAggregate *aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000250
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000251 //
252 // Make sure we have an aggregate. If not turn it into one.
253 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700254 if (node)
255 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000256 aggNode = node->getAsAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700257 if (aggNode == NULL || aggNode->getOp() != EOpNull)
258 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000259 //
260 // Make an aggregate containing this node.
261 //
262 aggNode = new TIntermAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700263 aggNode->getSequence()->push_back(node);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000264 }
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700265 }
266 else
267 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000268 aggNode = new TIntermAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700269 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000270
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000271 //
272 // Set the operator.
273 //
alokp@chromium.org58e54292010-08-24 21:40:03 +0000274 aggNode->setOp(op);
Jamie Madill075edd82013-07-08 13:30:19 -0400275 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000276
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000277 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000278}
279
280//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000281// Safe way to combine two nodes into an aggregate. Works with null pointers,
282// a node that's not a aggregate yet, etc.
283//
284// Returns the resulting aggregate, unless 0 was passed in for
285// both existing nodes.
286//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700287TIntermAggregate *TIntermediate::growAggregate(
288 TIntermNode *left, TIntermNode *right, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000289{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700290 if (left == NULL && right == NULL)
291 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000292
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700293 TIntermAggregate *aggNode = NULL;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000294 if (left)
295 aggNode = left->getAsAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700296 if (!aggNode || aggNode->getOp() != EOpNull)
297 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000298 aggNode = new TIntermAggregate;
299 if (left)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700300 aggNode->getSequence()->push_back(left);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000301 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000302
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000303 if (right)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700304 aggNode->getSequence()->push_back(right);
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// Turn an existing node into an aggregate.
313//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700314// Returns an aggregate, unless NULL was passed in for the existing node.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000315//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700316TIntermAggregate *TIntermediate::makeAggregate(
317 TIntermNode *node, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000318{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700319 if (node == NULL)
320 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000321
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700322 TIntermAggregate *aggNode = new TIntermAggregate;
323 aggNode->getSequence()->push_back(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000324
Jamie Madill075edd82013-07-08 13:30:19 -0400325 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000326
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000327 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000328}
329
330//
331// For "if" test nodes. There are three children; a condition,
332// a true path, and a false path. The two paths are in the
333// nodePair.
334//
335// Returns the selection node created.
336//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700337TIntermNode *TIntermediate::addSelection(
338 TIntermTyped *cond, TIntermNodePair nodePair, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000339{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000340 //
341 // For compile time constant selections, prune the code and
342 // test now.
343 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000344
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700345 if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion())
346 {
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +0000347 if (cond->getAsConstantUnion()->getBConst(0) == true)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700348 {
349 return nodePair.node1 ? setAggregateOperator(
350 nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL;
351 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000352 else
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700353 {
354 return nodePair.node2 ? setAggregateOperator(
355 nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL;
356 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000357 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000358
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700359 TIntermSelection *node = new TIntermSelection(
360 cond, nodePair.node1, nodePair.node2);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000361 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000362
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000363 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000364}
365
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700366TIntermTyped *TIntermediate::addComma(
367 TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000368{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700369 if (left->getType().getQualifier() == EvqConst &&
370 right->getType().getQualifier() == EvqConst)
371 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000372 return right;
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700373 }
374 else
375 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000376 TIntermTyped *commaAggregate = growAggregate(left, right, line);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000377 commaAggregate->getAsAggregate()->setOp(EOpComma);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000378 commaAggregate->setType(right->getType());
alokp@chromium.org58e54292010-08-24 21:40:03 +0000379 commaAggregate->getTypePointer()->setQualifier(EvqTemporary);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000380 return commaAggregate;
381 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000382}
383
384//
385// For "?:" test nodes. There are three children; a condition,
386// a true path, and a false path. The two paths are specified
387// as separate parameters.
388//
389// Returns the selection node created, or 0 if one could not be.
390//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700391TIntermTyped *TIntermediate::addSelection(
392 TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock,
393 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000394{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700395 if (!cond || !trueBlock || !falseBlock ||
396 trueBlock->getType() != falseBlock->getType())
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -0400397 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700398 return NULL;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000399 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000400
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000401 //
402 // See if all the operands are constant, then fold it otherwise not.
403 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000404
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700405 if (cond->getAsConstantUnion() &&
406 trueBlock->getAsConstantUnion() &&
407 falseBlock->getAsConstantUnion())
408 {
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +0000409 if (cond->getAsConstantUnion()->getBConst(0))
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000410 return trueBlock;
411 else
412 return falseBlock;
413 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000414
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000415 //
416 // Make a selection node.
417 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700418 TIntermSelection *node = new TIntermSelection(
419 cond, trueBlock, falseBlock, trueBlock->getType());
daniel@transgaming.com43affc52012-03-28 14:55:39 +0000420 node->getTypePointer()->setQualifier(EvqTemporary);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000421 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000422
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000423 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000424}
425
426//
427// Constant terminal nodes. Has a union that contains bool, float or int constants
428//
429// Returns the constant union node created.
430//
431
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700432TIntermConstantUnion *TIntermediate::addConstantUnion(
433 ConstantUnion *unionArrayPointer, const TType &t, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000434{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700435 TIntermConstantUnion *node = new TIntermConstantUnion(unionArrayPointer, t);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000436 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000437
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000438 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000439}
440
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700441TIntermTyped *TIntermediate::addSwizzle(
442 TVectorFields &fields, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000443{
444
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700445 TIntermAggregate *node = new TIntermAggregate(EOpSequence);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000446
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000447 node->setLine(line);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700448 TIntermConstantUnion *constIntNode;
449 TIntermSequence *sequenceVector = node->getSequence();
450 ConstantUnion *unionArray;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000451
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700452 for (int i = 0; i < fields.num; i++)
453 {
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000454 unionArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000455 unionArray->setIConst(fields.offsets[i]);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700456 constIntNode = addConstantUnion(
457 unionArray, TType(EbtInt, EbpUndefined, EvqConst), line);
458 sequenceVector->push_back(constIntNode);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000459 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000460
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000461 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000462}
463
464//
465// Create loop nodes.
466//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700467TIntermNode *TIntermediate::addLoop(
468 TLoopType type, TIntermNode *init, TIntermTyped *cond, TIntermTyped *expr,
469 TIntermNode *body, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000470{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700471 TIntermNode *node = new TIntermLoop(type, init, cond, expr, body);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000472 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000473
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000474 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000475}
476
477//
478// Add branches.
479//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700480TIntermBranch* TIntermediate::addBranch(
481 TOperator branchOp, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000482{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000483 return addBranch(branchOp, 0, line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000484}
485
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700486TIntermBranch* TIntermediate::addBranch(
487 TOperator branchOp, TIntermTyped *expression, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000488{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700489 TIntermBranch *node = new TIntermBranch(branchOp, expression);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000490 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000491
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000492 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000493}
494
495//
496// This is to be executed once the final root is put on top by the parsing
497// process.
498//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700499bool TIntermediate::postProcess(TIntermNode *root)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000500{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700501 if (root == NULL)
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000502 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000503
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000504 //
505 // First, finish off the top level sequence, if any
506 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700507 TIntermAggregate *aggRoot = root->getAsAggregate();
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000508 if (aggRoot && aggRoot->getOp() == EOpNull)
alokp@chromium.org58e54292010-08-24 21:40:03 +0000509 aggRoot->setOp(EOpSequence);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000510
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000511 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000512}
513
514//
515// This deletes the tree.
516//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700517void TIntermediate::remove(TIntermNode *root)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000518{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000519 if (root)
520 RemoveAllTreeNodes(root);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000521}