blob: 1d8b36bc3ee6ab93ff9018ebf6f09a70cc082bd0 [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
Jamie Madillaebd0022015-06-04 19:43:44 +000060 //
alokp@chromium.org2cf17712010-03-30 20:33:18 +000061 // See if we can fold constants.
Jamie Madillaebd0022015-06-04 19:43:44 +000062 //
63 TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
64 TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
65 if (leftTempConstant && rightTempConstant)
66 {
67 TIntermTyped *typedReturnNode =
68 leftTempConstant->fold(node->getOp(), rightTempConstant, mInfoSink);
69
70 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(
Olli Etuahof6c694b2015-03-26 14:50:53 +0200130 TOperator op, TIntermTyped *child, const TSourceLoc &line, const TType *funcReturnType)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000131{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000132 TIntermConstantUnion *childTempConstant = 0;
133 if (child->getAsConstantUnion())
134 childTempConstant = child->getAsConstantUnion();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000135
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000136 //
137 // Make a new node for the operator.
138 //
Olli Etuaho69c11b52015-03-26 12:59:00 +0200139 TIntermUnary *node = new TIntermUnary(op);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000140 node->setLine(line);
141 node->setOperand(child);
Olli Etuahof6c694b2015-03-26 14:50:53 +0200142 node->promote(funcReturnType);
Olli Etuaho7700ff62015-01-15 12:16:29 +0200143
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700144 if (childTempConstant)
145 {
Jamie Madillaebd0022015-06-04 19:43:44 +0000146 TIntermTyped *newChild = childTempConstant->fold(op, nullptr, mInfoSink);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000147
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000148 if (newChild)
149 return newChild;
150 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000151
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000152 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000153}
154
155//
156// This is the safe way to change the operator on an aggregate, as it
157// does lots of error checking and fixing. Especially for establishing
158// a function call's operation on it's set of parameters. Sequences
159// of instructions are also aggregates, but they just direnctly set
160// their operator to EOpSequence.
161//
162// Returns an aggregate node, which could be the one passed in if
daniel@transgaming.com978702d2012-04-04 15:05:58 +0000163// it was already an aggregate but no operator was set.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000164//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700165TIntermAggregate *TIntermediate::setAggregateOperator(
166 TIntermNode *node, TOperator op, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000167{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700168 TIntermAggregate *aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000169
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000170 //
171 // Make sure we have an aggregate. If not turn it into one.
172 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700173 if (node)
174 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000175 aggNode = node->getAsAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700176 if (aggNode == NULL || aggNode->getOp() != EOpNull)
177 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000178 //
179 // Make an aggregate containing this node.
180 //
181 aggNode = new TIntermAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700182 aggNode->getSequence()->push_back(node);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000183 }
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700184 }
185 else
186 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000187 aggNode = new TIntermAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700188 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000189
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000190 //
191 // Set the operator.
192 //
alokp@chromium.org58e54292010-08-24 21:40:03 +0000193 aggNode->setOp(op);
Jamie Madill075edd82013-07-08 13:30:19 -0400194 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000195
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000196 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000197}
198
199//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000200// Safe way to combine two nodes into an aggregate. Works with null pointers,
201// a node that's not a aggregate yet, etc.
202//
203// Returns the resulting aggregate, unless 0 was passed in for
204// both existing nodes.
205//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700206TIntermAggregate *TIntermediate::growAggregate(
207 TIntermNode *left, TIntermNode *right, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000208{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700209 if (left == NULL && right == NULL)
210 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000211
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700212 TIntermAggregate *aggNode = NULL;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000213 if (left)
214 aggNode = left->getAsAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700215 if (!aggNode || aggNode->getOp() != EOpNull)
216 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000217 aggNode = new TIntermAggregate;
218 if (left)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700219 aggNode->getSequence()->push_back(left);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000220 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000221
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000222 if (right)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700223 aggNode->getSequence()->push_back(right);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000224
Jamie Madill075edd82013-07-08 13:30:19 -0400225 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000226
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000227 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000228}
229
230//
231// Turn an existing node into an aggregate.
232//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700233// Returns an aggregate, unless NULL was passed in for the existing node.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000234//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700235TIntermAggregate *TIntermediate::makeAggregate(
236 TIntermNode *node, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000237{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700238 if (node == NULL)
239 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000240
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700241 TIntermAggregate *aggNode = new TIntermAggregate;
242 aggNode->getSequence()->push_back(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000243
Jamie Madill075edd82013-07-08 13:30:19 -0400244 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000245
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000246 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000247}
248
Olli Etuaho7d7f8c42015-05-19 18:38:49 +0300249// If the input node is nullptr, return nullptr.
250// If the input node is a sequence (block) node, return it.
251// If the input node is not a sequence node, put it inside a sequence node and return that.
252TIntermAggregate *TIntermediate::ensureSequence(TIntermNode *node)
253{
254 if (node == nullptr)
255 return nullptr;
256 TIntermAggregate *aggNode = node->getAsAggregate();
257 if (aggNode != nullptr && aggNode->getOp() == EOpSequence)
258 return aggNode;
259
260 aggNode = makeAggregate(node, node->getLine());
261 aggNode->setOp(EOpSequence);
262 return aggNode;
263}
264
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000265//
266// For "if" test nodes. There are three children; a condition,
267// a true path, and a false path. The two paths are in the
268// nodePair.
269//
270// Returns the selection node created.
271//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700272TIntermNode *TIntermediate::addSelection(
273 TIntermTyped *cond, TIntermNodePair nodePair, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000274{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000275 //
276 // For compile time constant selections, prune the code and
277 // test now.
278 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000279
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700280 if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion())
281 {
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +0000282 if (cond->getAsConstantUnion()->getBConst(0) == true)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700283 {
284 return nodePair.node1 ? setAggregateOperator(
285 nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL;
286 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000287 else
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700288 {
289 return nodePair.node2 ? setAggregateOperator(
290 nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL;
291 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000292 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000293
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700294 TIntermSelection *node = new TIntermSelection(
Olli Etuaho7d7f8c42015-05-19 18:38:49 +0300295 cond, ensureSequence(nodePair.node1), ensureSequence(nodePair.node2));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000296 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000297
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000298 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000299}
300
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700301TIntermTyped *TIntermediate::addComma(
302 TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000303{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700304 if (left->getType().getQualifier() == EvqConst &&
305 right->getType().getQualifier() == EvqConst)
306 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000307 return right;
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700308 }
309 else
310 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000311 TIntermTyped *commaAggregate = growAggregate(left, right, line);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000312 commaAggregate->getAsAggregate()->setOp(EOpComma);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000313 commaAggregate->setType(right->getType());
alokp@chromium.org58e54292010-08-24 21:40:03 +0000314 commaAggregate->getTypePointer()->setQualifier(EvqTemporary);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000315 return commaAggregate;
316 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000317}
318
319//
320// For "?:" test nodes. There are three children; a condition,
321// a true path, and a false path. The two paths are specified
322// as separate parameters.
323//
Olli Etuaho52901742015-04-15 13:42:45 +0300324// Returns the selection node created, or one of trueBlock and falseBlock if the expression could be folded.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000325//
Olli Etuaho52901742015-04-15 13:42:45 +0300326TIntermTyped *TIntermediate::addSelection(TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock,
327 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000328{
Olli Etuaho52901742015-04-15 13:42:45 +0300329 // Right now it's safe to fold ternary operators only when all operands
330 // are constant. If only the condition is constant, it's theoretically
331 // possible to fold the ternary operator, but that requires making sure
332 // that the node returned from here won't be treated as a constant
333 // expression in case the node that gets eliminated was not a constant
334 // expression.
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700335 if (cond->getAsConstantUnion() &&
336 trueBlock->getAsConstantUnion() &&
337 falseBlock->getAsConstantUnion())
338 {
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +0000339 if (cond->getAsConstantUnion()->getBConst(0))
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000340 return trueBlock;
341 else
342 return falseBlock;
343 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000344
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000345 //
346 // Make a selection node.
347 //
Olli Etuaho52901742015-04-15 13:42:45 +0300348 TIntermSelection *node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
daniel@transgaming.com43affc52012-03-28 14:55:39 +0000349 node->getTypePointer()->setQualifier(EvqTemporary);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000350 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000351
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000352 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000353}
354
Olli Etuahoa3a36662015-02-17 13:46:51 +0200355TIntermSwitch *TIntermediate::addSwitch(
356 TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &line)
357{
Olli Etuaho3c1dfb52015-02-20 11:34:03 +0200358 TIntermSwitch *node = new TIntermSwitch(init, statementList);
359 node->setLine(line);
360
361 return node;
Olli Etuahoa3a36662015-02-17 13:46:51 +0200362}
363
364TIntermCase *TIntermediate::addCase(
365 TIntermTyped *condition, const TSourceLoc &line)
366{
Olli Etuaho3c1dfb52015-02-20 11:34:03 +0200367 TIntermCase *node = new TIntermCase(condition);
368 node->setLine(line);
369
370 return node;
Olli Etuahoa3a36662015-02-17 13:46:51 +0200371}
372
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000373//
374// Constant terminal nodes. Has a union that contains bool, float or int constants
375//
376// Returns the constant union node created.
377//
378
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700379TIntermConstantUnion *TIntermediate::addConstantUnion(
Jamie Madillb11e2482015-05-04 14:21:22 -0400380 TConstantUnion *constantUnion, const TType &type, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000381{
Jamie Madillb11e2482015-05-04 14:21:22 -0400382 TIntermConstantUnion *node = new TIntermConstantUnion(constantUnion, type);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000383 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000384
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000385 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000386}
387
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700388TIntermTyped *TIntermediate::addSwizzle(
389 TVectorFields &fields, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000390{
391
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700392 TIntermAggregate *node = new TIntermAggregate(EOpSequence);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000393
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000394 node->setLine(line);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700395 TIntermConstantUnion *constIntNode;
396 TIntermSequence *sequenceVector = node->getSequence();
Jamie Madill6ba6ead2015-05-04 14:21:21 -0400397 TConstantUnion *unionArray;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000398
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700399 for (int i = 0; i < fields.num; i++)
400 {
Jamie Madill6ba6ead2015-05-04 14:21:21 -0400401 unionArray = new TConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000402 unionArray->setIConst(fields.offsets[i]);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700403 constIntNode = addConstantUnion(
404 unionArray, TType(EbtInt, EbpUndefined, EvqConst), line);
405 sequenceVector->push_back(constIntNode);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000406 }
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
411//
412// Create loop nodes.
413//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700414TIntermNode *TIntermediate::addLoop(
415 TLoopType type, TIntermNode *init, TIntermTyped *cond, TIntermTyped *expr,
416 TIntermNode *body, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000417{
Olli Etuaho7d7f8c42015-05-19 18:38:49 +0300418 TIntermNode *node = new TIntermLoop(type, init, cond, expr, ensureSequence(body));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000419 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000420
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000421 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000422}
423
424//
425// Add branches.
426//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700427TIntermBranch* TIntermediate::addBranch(
428 TOperator branchOp, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000429{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000430 return addBranch(branchOp, 0, line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000431}
432
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700433TIntermBranch* TIntermediate::addBranch(
434 TOperator branchOp, TIntermTyped *expression, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000435{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700436 TIntermBranch *node = new TIntermBranch(branchOp, expression);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000437 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000438
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000439 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000440}
441
442//
443// This is to be executed once the final root is put on top by the parsing
444// process.
445//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700446bool TIntermediate::postProcess(TIntermNode *root)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000447{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700448 if (root == NULL)
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000449 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000450
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000451 //
452 // First, finish off the top level sequence, if any
453 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700454 TIntermAggregate *aggRoot = root->getAsAggregate();
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000455 if (aggRoot && aggRoot->getOp() == EOpNull)
alokp@chromium.org58e54292010-08-24 21:40:03 +0000456 aggRoot->setOp(EOpSequence);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000457
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000458 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000459}
Arun Patole274f0702015-05-05 13:33:30 +0530460
461TIntermTyped *TIntermediate::foldAggregateBuiltIn(TOperator op, TIntermAggregate *aggregate)
462{
463 switch (op)
464 {
Arun Patolebf790422015-05-18 17:53:04 +0530465 case EOpAtan:
466 case EOpPow:
467 case EOpMod:
Arun Patole274f0702015-05-05 13:33:30 +0530468 case EOpMin:
469 case EOpMax:
470 case EOpClamp:
Arun Patolebf790422015-05-18 17:53:04 +0530471 case EOpMix:
472 case EOpStep:
473 case EOpSmoothStep:
Arun Patole9d0b1f92015-05-20 14:27:17 +0530474 case EOpLessThan:
475 case EOpLessThanEqual:
476 case EOpGreaterThan:
477 case EOpGreaterThanEqual:
478 case EOpVectorEqual:
479 case EOpVectorNotEqual:
Arun Patole1155ddd2015-06-05 18:04:36 +0530480 case EOpDistance:
481 case EOpDot:
482 case EOpCross:
483 case EOpFaceForward:
484 case EOpReflect:
485 case EOpRefract:
Arun Patolebf790422015-05-18 17:53:04 +0530486 return TIntermConstantUnion::FoldAggregateBuiltIn(op, aggregate, mInfoSink);
Arun Patole274f0702015-05-05 13:33:30 +0530487 default:
488 // Constant folding not supported for the built-in.
489 return nullptr;
490 }
491
492 return nullptr;
493}