blob: 47b3b051733af98edc13404028a0cdec809f78f8 [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)
79 return NULL;
80 default:
81 break;
alokp@chromium.org2cf17712010-03-30 20:33:18 +000082 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000083
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -040084 if (left->getBasicType() != right->getBasicType())
85 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -070086 return NULL;
alokp@chromium.org2cf17712010-03-30 20:33:18 +000087 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000088
alokp@chromium.org2cf17712010-03-30 20:33:18 +000089 //
90 // Need a new node holding things together then. Make
91 // one and promote it to the right type.
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);
97 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 //
102 // See if we can fold constants.
103 //
alokp@chromium.org8f0f24a2010-09-01 21:06:24 +0000104 TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
105 TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700106 if (leftTempConstant && rightTempConstant)
107 {
108 TIntermTyped *typedReturnNode =
109 leftTempConstant->fold(node->getOp(), rightTempConstant, mInfoSink);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000110
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000111 if (typedReturnNode)
112 return typedReturnNode;
113 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000114
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000115 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000116}
117
118//
119// Connect two nodes through an assignment.
120//
121// Returns the added node.
122//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700123TIntermTyped *TIntermediate::addAssign(
124 TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000125{
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -0400126 if (left->getType().getStruct() || right->getType().getStruct())
127 {
128 if (left->getType() != right->getType())
129 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700130 return NULL;
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -0400131 }
132 }
133
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700134 TIntermBinary *node = new TIntermBinary(op);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000135 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000136
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000137 node->setLeft(left);
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -0400138 node->setRight(right);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700139 if (!node->promote(mInfoSink))
140 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000141
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000142 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000143}
144
145//
146// Connect two nodes through an index operator, where the left node is the base
147// of an array or struct, and the right node is a direct or indirect offset.
148//
149// Returns the added node.
150// The caller should set the type of the returned node.
151//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700152TIntermTyped *TIntermediate::addIndex(
153 TOperator op, TIntermTyped *base, TIntermTyped *index, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000154{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700155 TIntermBinary *node = new TIntermBinary(op);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000156 node->setLine(line);
157 node->setLeft(base);
158 node->setRight(index);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000159
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000160 // caller should set the type
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000161
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000162 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000163}
164
165//
166// Add one node as the parent of another that it operates on.
167//
168// Returns the added node.
169//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700170TIntermTyped *TIntermediate::addUnaryMath(
171 TOperator op, TIntermNode *childNode, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000172{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700173 TIntermUnary *node;
174 TIntermTyped *child = childNode->getAsTyped();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000175
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700176 if (child == NULL)
177 {
178 mInfoSink.info.message(EPrefixInternalError, line,
179 "Bad type in AddUnaryMath");
180 return NULL;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000181 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000182
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700183 switch (op)
184 {
185 case EOpLogicalNot:
186 if (child->getType().getBasicType() != EbtBool ||
187 child->getType().isMatrix() ||
188 child->getType().isArray() ||
189 child->getType().isVector())
190 {
191 return NULL;
192 }
193 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000194
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700195 case EOpPostIncrement:
196 case EOpPreIncrement:
197 case EOpPostDecrement:
198 case EOpPreDecrement:
199 case EOpNegative:
Zhenyao Mode1e00e2014-10-09 16:55:32 -0700200 case EOpPositive:
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700201 if (child->getType().getBasicType() == EbtStruct ||
202 child->getType().isArray())
203 {
204 return NULL;
205 }
206 default:
207 break;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000208 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000209
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000210 TIntermConstantUnion *childTempConstant = 0;
211 if (child->getAsConstantUnion())
212 childTempConstant = child->getAsConstantUnion();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000213
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000214 //
215 // Make a new node for the operator.
216 //
217 node = new TIntermUnary(op);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000218 node->setLine(line);
219 node->setOperand(child);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000220
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700221 if (!node->promote(mInfoSink))
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000222 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000223
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700224 if (childTempConstant)
225 {
226 TIntermTyped *newChild = childTempConstant->fold(op, 0, mInfoSink);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000227
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000228 if (newChild)
229 return newChild;
230 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000231
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000232 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000233}
234
235//
236// This is the safe way to change the operator on an aggregate, as it
237// does lots of error checking and fixing. Especially for establishing
238// a function call's operation on it's set of parameters. Sequences
239// of instructions are also aggregates, but they just direnctly set
240// their operator to EOpSequence.
241//
242// Returns an aggregate node, which could be the one passed in if
daniel@transgaming.com978702d2012-04-04 15:05:58 +0000243// it was already an aggregate but no operator was set.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000244//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700245TIntermAggregate *TIntermediate::setAggregateOperator(
246 TIntermNode *node, TOperator op, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000247{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700248 TIntermAggregate *aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000249
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000250 //
251 // Make sure we have an aggregate. If not turn it into one.
252 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700253 if (node)
254 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000255 aggNode = node->getAsAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700256 if (aggNode == NULL || aggNode->getOp() != EOpNull)
257 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000258 //
259 // Make an aggregate containing this node.
260 //
261 aggNode = new TIntermAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700262 aggNode->getSequence()->push_back(node);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000263 }
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700264 }
265 else
266 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000267 aggNode = new TIntermAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700268 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000269
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000270 //
271 // Set the operator.
272 //
alokp@chromium.org58e54292010-08-24 21:40:03 +0000273 aggNode->setOp(op);
Jamie Madill075edd82013-07-08 13:30:19 -0400274 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000275
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000276 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000277}
278
279//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000280// Safe way to combine two nodes into an aggregate. Works with null pointers,
281// a node that's not a aggregate yet, etc.
282//
283// Returns the resulting aggregate, unless 0 was passed in for
284// both existing nodes.
285//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700286TIntermAggregate *TIntermediate::growAggregate(
287 TIntermNode *left, TIntermNode *right, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000288{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700289 if (left == NULL && right == NULL)
290 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000291
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700292 TIntermAggregate *aggNode = NULL;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000293 if (left)
294 aggNode = left->getAsAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700295 if (!aggNode || aggNode->getOp() != EOpNull)
296 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000297 aggNode = new TIntermAggregate;
298 if (left)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700299 aggNode->getSequence()->push_back(left);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000300 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000301
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000302 if (right)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700303 aggNode->getSequence()->push_back(right);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000304
Jamie Madill075edd82013-07-08 13:30:19 -0400305 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000306
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000307 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000308}
309
310//
311// Turn an existing node into an aggregate.
312//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700313// Returns an aggregate, unless NULL was passed in for the existing node.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000314//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700315TIntermAggregate *TIntermediate::makeAggregate(
316 TIntermNode *node, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000317{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700318 if (node == NULL)
319 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000320
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700321 TIntermAggregate *aggNode = new TIntermAggregate;
322 aggNode->getSequence()->push_back(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000323
Jamie Madill075edd82013-07-08 13:30:19 -0400324 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000325
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000326 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000327}
328
329//
330// For "if" test nodes. There are three children; a condition,
331// a true path, and a false path. The two paths are in the
332// nodePair.
333//
334// Returns the selection node created.
335//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700336TIntermNode *TIntermediate::addSelection(
337 TIntermTyped *cond, TIntermNodePair nodePair, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000338{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000339 //
340 // For compile time constant selections, prune the code and
341 // test now.
342 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000343
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700344 if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion())
345 {
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +0000346 if (cond->getAsConstantUnion()->getBConst(0) == true)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700347 {
348 return nodePair.node1 ? setAggregateOperator(
349 nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL;
350 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000351 else
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700352 {
353 return nodePair.node2 ? setAggregateOperator(
354 nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL;
355 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000356 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000357
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700358 TIntermSelection *node = new TIntermSelection(
359 cond, nodePair.node1, nodePair.node2);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000360 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000361
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000362 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000363}
364
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700365TIntermTyped *TIntermediate::addComma(
366 TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000367{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700368 if (left->getType().getQualifier() == EvqConst &&
369 right->getType().getQualifier() == EvqConst)
370 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000371 return right;
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700372 }
373 else
374 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000375 TIntermTyped *commaAggregate = growAggregate(left, right, line);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000376 commaAggregate->getAsAggregate()->setOp(EOpComma);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000377 commaAggregate->setType(right->getType());
alokp@chromium.org58e54292010-08-24 21:40:03 +0000378 commaAggregate->getTypePointer()->setQualifier(EvqTemporary);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000379 return commaAggregate;
380 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000381}
382
383//
384// For "?:" test nodes. There are three children; a condition,
385// a true path, and a false path. The two paths are specified
386// as separate parameters.
387//
388// Returns the selection node created, or 0 if one could not be.
389//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700390TIntermTyped *TIntermediate::addSelection(
391 TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock,
392 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000393{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700394 if (!cond || !trueBlock || !falseBlock ||
395 trueBlock->getType() != falseBlock->getType())
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -0400396 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700397 return NULL;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000398 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000399
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000400 //
401 // See if all the operands are constant, then fold it otherwise not.
402 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000403
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700404 if (cond->getAsConstantUnion() &&
405 trueBlock->getAsConstantUnion() &&
406 falseBlock->getAsConstantUnion())
407 {
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +0000408 if (cond->getAsConstantUnion()->getBConst(0))
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000409 return trueBlock;
410 else
411 return falseBlock;
412 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000413
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000414 //
415 // Make a selection node.
416 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700417 TIntermSelection *node = new TIntermSelection(
418 cond, trueBlock, falseBlock, trueBlock->getType());
daniel@transgaming.com43affc52012-03-28 14:55:39 +0000419 node->getTypePointer()->setQualifier(EvqTemporary);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000420 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000421
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000422 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000423}
424
425//
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}