blob: edb34603591de338a95aa8a817e4aaa9ef91ccf4 [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
2// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
3// 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
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000015#include "compiler/localintermediate.h"
16#include "compiler/QualifierAlive.h"
17#include "compiler/RemoveTree.h"
18
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +000019bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000020
alokp@chromium.org32cfaf42010-08-23 21:01:13 +000021static TPrecision GetHigherPrecision( TPrecision left, TPrecision right ){
daniel@transgaming.com9abe9562010-06-24 13:02:21 +000022 return left > right ? left : right;
daniel@transgaming.coma5d76232010-05-17 09:58:47 +000023}
alokp@chromium.org32cfaf42010-08-23 21:01:13 +000024
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000025////////////////////////////////////////////////////////////////////////////
26//
27// First set of functions are to help build the intermediate representation.
28// These functions are not member functions of the nodes.
29// They are called from parser productions.
30//
31/////////////////////////////////////////////////////////////////////////////
32
33//
34// Add a terminal node for an identifier in an expression.
35//
36// Returns the added node.
37//
38TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, TSourceLoc line)
39{
alokp@chromium.org2cf17712010-03-30 20:33:18 +000040 TIntermSymbol* node = new TIntermSymbol(id, name, type);
41 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000042
alokp@chromium.org2cf17712010-03-30 20:33:18 +000043 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000044}
45
46//
47// Connect two nodes with a new parent that does a binary operation on the nodes.
48//
49// Returns the added node.
50//
51TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line, TSymbolTable& symbolTable)
52{
alokp@chromium.org2cf17712010-03-30 20:33:18 +000053 switch (op) {
alokp@chromium.org8f0f24a2010-09-01 21:06:24 +000054 case EOpEqual:
55 case EOpNotEqual:
56 if (left->isArray())
57 return 0;
58 break;
alokp@chromium.org2cf17712010-03-30 20:33:18 +000059 case EOpLessThan:
60 case EOpGreaterThan:
61 case EOpLessThanEqual:
62 case EOpGreaterThanEqual:
alokp@chromium.org8f0f24a2010-09-01 21:06:24 +000063 if (left->isMatrix() || left->isArray() || left->isVector() || left->getBasicType() == EbtStruct) {
alokp@chromium.org2cf17712010-03-30 20:33:18 +000064 return 0;
65 }
66 break;
67 case EOpLogicalOr:
68 case EOpLogicalXor:
69 case EOpLogicalAnd:
alokp@chromium.org8f0f24a2010-09-01 21:06:24 +000070 if (left->getBasicType() != EbtBool || left->isMatrix() || left->isArray() || left->isVector()) {
alokp@chromium.org2cf17712010-03-30 20:33:18 +000071 return 0;
72 }
73 break;
74 case EOpAdd:
75 case EOpSub:
76 case EOpDiv:
77 case EOpMul:
alokp@chromium.org8f0f24a2010-09-01 21:06:24 +000078 if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool)
alokp@chromium.org2cf17712010-03-30 20:33:18 +000079 return 0;
80 default: break;
81 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000082
alokp@chromium.org2cf17712010-03-30 20:33:18 +000083 //
84 // First try converting the children to compatible types.
85 //
alokp@chromium.org8f0f24a2010-09-01 21:06:24 +000086 if (left->getType().getStruct() && right->getType().getStruct()) {
87 if (left->getType() != right->getType())
88 return 0;
89 } else {
alokp@chromium.org2cf17712010-03-30 20:33:18 +000090 TIntermTyped* child = addConversion(op, left->getType(), right);
91 if (child)
92 right = child;
93 else {
94 child = addConversion(op, right->getType(), left);
95 if (child)
96 left = child;
97 else
98 return 0;
99 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000100 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000101
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000102 //
103 // Need a new node holding things together then. Make
104 // one and promote it to the right type.
105 //
106 TIntermBinary* node = new TIntermBinary(op);
107 if (line == 0)
108 line = right->getLine();
109 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000110
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000111 node->setLeft(left);
112 node->setRight(right);
alokp@chromium.org8f0f24a2010-09-01 21:06:24 +0000113 if (!node->promote(infoSink))
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000114 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000115
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000116 //
117 // See if we can fold constants.
118 //
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000119 TIntermTyped* typedReturnNode = 0;
alokp@chromium.org8f0f24a2010-09-01 21:06:24 +0000120 TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
121 TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
122 if (leftTempConstant && rightTempConstant) {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000123 typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000124
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000125 if (typedReturnNode)
126 return typedReturnNode;
127 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000128
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000129 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000130}
131
132//
133// Connect two nodes through an assignment.
134//
135// Returns the added node.
136//
137TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line)
138{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000139 //
140 // Like adding binary math, except the conversion can only go
141 // from right to left.
142 //
143 TIntermBinary* node = new TIntermBinary(op);
144 if (line == 0)
145 line = left->getLine();
146 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000147
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000148 TIntermTyped* child = addConversion(op, left->getType(), right);
149 if (child == 0)
150 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000151
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000152 node->setLeft(left);
153 node->setRight(child);
154 if (! node->promote(infoSink))
155 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000156
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000157 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000158}
159
160//
161// Connect two nodes through an index operator, where the left node is the base
162// of an array or struct, and the right node is a direct or indirect offset.
163//
164// Returns the added node.
165// The caller should set the type of the returned node.
166//
167TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc line)
168{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000169 TIntermBinary* node = new TIntermBinary(op);
170 if (line == 0)
171 line = index->getLine();
172 node->setLine(line);
173 node->setLeft(base);
174 node->setRight(index);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000175
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000176 // caller should set the type
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000177
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000178 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000179}
180
181//
182// Add one node as the parent of another that it operates on.
183//
184// Returns the added node.
185//
186TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, TSourceLoc line, TSymbolTable& symbolTable)
187{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000188 TIntermUnary* node;
189 TIntermTyped* child = childNode->getAsTyped();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000190
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000191 if (child == 0) {
192 infoSink.info.message(EPrefixInternalError, "Bad type in AddUnaryMath", line);
193 return 0;
194 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000195
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000196 switch (op) {
197 case EOpLogicalNot:
198 if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) {
199 return 0;
200 }
201 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000202
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000203 case EOpPostIncrement:
204 case EOpPreIncrement:
205 case EOpPostDecrement:
206 case EOpPreDecrement:
207 case EOpNegative:
208 if (child->getType().getBasicType() == EbtStruct || child->getType().isArray())
209 return 0;
210 default: break;
211 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000212
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000213 //
214 // Do we need to promote the operand?
215 //
216 // Note: Implicit promotions were removed from the language.
217 //
218 TBasicType newType = EbtVoid;
219 switch (op) {
220 case EOpConstructInt: newType = EbtInt; break;
221 case EOpConstructBool: newType = EbtBool; break;
222 case EOpConstructFloat: newType = EbtFloat; break;
223 default: break;
224 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000225
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000226 if (newType != EbtVoid) {
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000227 child = addConversion(op, TType(newType, child->getPrecision(), EvqTemporary,
228 child->getNominalSize(),
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000229 child->isMatrix(),
230 child->isArray()),
231 child);
232 if (child == 0)
233 return 0;
234 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000235
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000236 //
237 // For constructors, we are now done, it's all in the conversion.
238 //
239 switch (op) {
240 case EOpConstructInt:
241 case EOpConstructBool:
242 case EOpConstructFloat:
243 return child;
244 default: break;
245 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000246
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000247 TIntermConstantUnion *childTempConstant = 0;
248 if (child->getAsConstantUnion())
249 childTempConstant = child->getAsConstantUnion();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000250
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000251 //
252 // Make a new node for the operator.
253 //
254 node = new TIntermUnary(op);
255 if (line == 0)
256 line = child->getLine();
257 node->setLine(line);
258 node->setOperand(child);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000259
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000260 if (! node->promote(infoSink))
261 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000262
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000263 if (childTempConstant) {
264 TIntermTyped* newChild = childTempConstant->fold(op, 0, infoSink);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000265
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000266 if (newChild)
267 return newChild;
268 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000269
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000270 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000271}
272
273//
274// This is the safe way to change the operator on an aggregate, as it
275// does lots of error checking and fixing. Especially for establishing
276// a function call's operation on it's set of parameters. Sequences
277// of instructions are also aggregates, but they just direnctly set
278// their operator to EOpSequence.
279//
280// Returns an aggregate node, which could be the one passed in if
281// it was already an aggregate.
282//
283TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, TSourceLoc line)
284{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000285 TIntermAggregate* aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000286
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000287 //
288 // Make sure we have an aggregate. If not turn it into one.
289 //
290 if (node) {
291 aggNode = node->getAsAggregate();
292 if (aggNode == 0 || aggNode->getOp() != EOpNull) {
293 //
294 // Make an aggregate containing this node.
295 //
296 aggNode = new TIntermAggregate();
297 aggNode->getSequence().push_back(node);
298 if (line == 0)
299 line = node->getLine();
300 }
301 } else
302 aggNode = new TIntermAggregate();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000303
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000304 //
305 // Set the operator.
306 //
alokp@chromium.org58e54292010-08-24 21:40:03 +0000307 aggNode->setOp(op);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000308 if (line != 0)
309 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000310
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000311 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000312}
313
314//
315// Convert one type to another.
316//
317// Returns the node representing the conversion, which could be the same
318// node passed in if no conversion was needed.
319//
320// Return 0 if a conversion can't be done.
321//
322TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TIntermTyped* node)
323{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000324 //
325 // Does the base type allow operation?
326 //
327 switch (node->getBasicType()) {
328 case EbtVoid:
329 case EbtSampler2D:
330 case EbtSamplerCube:
331 return 0;
332 default: break;
333 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000334
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000335 //
336 // Otherwise, if types are identical, no problem
337 //
338 if (type == node->getType())
339 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000340
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000341 //
342 // If one's a structure, then no conversions.
343 //
344 if (type.getStruct() || node->getType().getStruct())
345 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000346
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000347 //
348 // If one's an array, then no conversions.
349 //
350 if (type.isArray() || node->getType().isArray())
351 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000352
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000353 TBasicType promoteTo;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000354
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000355 switch (op) {
356 //
357 // Explicit conversions
358 //
359 case EOpConstructBool:
360 promoteTo = EbtBool;
361 break;
362 case EOpConstructFloat:
363 promoteTo = EbtFloat;
364 break;
365 case EOpConstructInt:
366 promoteTo = EbtInt;
367 break;
368 default:
369 //
370 // implicit conversions were removed from the language.
371 //
372 if (type.getBasicType() != node->getType().getBasicType())
373 return 0;
374 //
375 // Size and structure could still differ, but that's
376 // handled by operator promotion.
377 //
378 return node;
379 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000380
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000381 if (node->getAsConstantUnion()) {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000382
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000383 return (promoteConstantUnion(promoteTo, node->getAsConstantUnion()));
384 } else {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000385
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000386 //
387 // Add a new newNode for the conversion.
388 //
389 TIntermUnary* newNode = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000390
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000391 TOperator newOp = EOpNull;
392 switch (promoteTo) {
393 case EbtFloat:
394 switch (node->getBasicType()) {
395 case EbtInt: newOp = EOpConvIntToFloat; break;
396 case EbtBool: newOp = EOpConvBoolToFloat; break;
397 default:
398 infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
399 return 0;
400 }
401 break;
402 case EbtBool:
403 switch (node->getBasicType()) {
404 case EbtInt: newOp = EOpConvIntToBool; break;
405 case EbtFloat: newOp = EOpConvFloatToBool; break;
406 default:
407 infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
408 return 0;
409 }
410 break;
411 case EbtInt:
412 switch (node->getBasicType()) {
413 case EbtBool: newOp = EOpConvBoolToInt; break;
414 case EbtFloat: newOp = EOpConvFloatToInt; break;
415 default:
416 infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
417 return 0;
418 }
419 break;
420 default:
421 infoSink.info.message(EPrefixInternalError, "Bad promotion type", node->getLine());
422 return 0;
423 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000424
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000425 TType type(promoteTo, node->getPrecision(), EvqTemporary, node->getNominalSize(), node->isMatrix(), node->isArray());
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000426 newNode = new TIntermUnary(newOp, type);
427 newNode->setLine(node->getLine());
428 newNode->setOperand(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000429
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000430 return newNode;
431 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000432}
433
434//
435// Safe way to combine two nodes into an aggregate. Works with null pointers,
436// a node that's not a aggregate yet, etc.
437//
438// Returns the resulting aggregate, unless 0 was passed in for
439// both existing nodes.
440//
441TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, TSourceLoc line)
442{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000443 if (left == 0 && right == 0)
444 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000445
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000446 TIntermAggregate* aggNode = 0;
447 if (left)
448 aggNode = left->getAsAggregate();
449 if (!aggNode || aggNode->getOp() != EOpNull) {
450 aggNode = new TIntermAggregate;
451 if (left)
452 aggNode->getSequence().push_back(left);
453 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000454
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000455 if (right)
456 aggNode->getSequence().push_back(right);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000457
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000458 if (line != 0)
459 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000460
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000461 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000462}
463
464//
465// Turn an existing node into an aggregate.
466//
467// Returns an aggregate, unless 0 was passed in for the existing node.
468//
469TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, TSourceLoc line)
470{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000471 if (node == 0)
472 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000473
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000474 TIntermAggregate* aggNode = new TIntermAggregate;
475 aggNode->getSequence().push_back(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000476
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000477 if (line != 0)
478 aggNode->setLine(line);
479 else
480 aggNode->setLine(node->getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000481
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000482 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000483}
484
485//
486// For "if" test nodes. There are three children; a condition,
487// a true path, and a false path. The two paths are in the
488// nodePair.
489//
490// Returns the selection node created.
491//
492TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, TSourceLoc line)
493{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000494 //
495 // For compile time constant selections, prune the code and
496 // test now.
497 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000498
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000499 if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion()) {
500 if (cond->getAsTyped()->getAsConstantUnion()->getUnionArrayPointer()->getBConst())
501 return nodePair.node1;
502 else
503 return nodePair.node2;
504 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000505
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000506 TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2);
507 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000508
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000509 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000510}
511
512
513TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc line)
514{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000515 if (left->getType().getQualifier() == EvqConst && right->getType().getQualifier() == EvqConst) {
516 return right;
517 } else {
518 TIntermTyped *commaAggregate = growAggregate(left, right, line);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000519 commaAggregate->getAsAggregate()->setOp(EOpComma);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000520 commaAggregate->setType(right->getType());
alokp@chromium.org58e54292010-08-24 21:40:03 +0000521 commaAggregate->getTypePointer()->setQualifier(EvqTemporary);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000522 return commaAggregate;
523 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000524}
525
526//
527// For "?:" test nodes. There are three children; a condition,
528// a true path, and a false path. The two paths are specified
529// as separate parameters.
530//
531// Returns the selection node created, or 0 if one could not be.
532//
533TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, TSourceLoc line)
534{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000535 //
536 // Get compatible types.
537 //
538 TIntermTyped* child = addConversion(EOpSequence, trueBlock->getType(), falseBlock);
539 if (child)
540 falseBlock = child;
541 else {
542 child = addConversion(EOpSequence, falseBlock->getType(), trueBlock);
543 if (child)
544 trueBlock = child;
545 else
546 return 0;
547 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000548
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000549 //
550 // See if all the operands are constant, then fold it otherwise not.
551 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000552
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000553 if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) {
554 if (cond->getAsConstantUnion()->getUnionArrayPointer()->getBConst())
555 return trueBlock;
556 else
557 return falseBlock;
558 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000559
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000560 //
561 // Make a selection node.
562 //
563 TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
564 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000565
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000566 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000567}
568
569//
570// Constant terminal nodes. Has a union that contains bool, float or int constants
571//
572// Returns the constant union node created.
573//
574
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000575TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, TSourceLoc line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000576{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000577 TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t);
578 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000579
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000580 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000581}
582
583TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, TSourceLoc line)
584{
585
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000586 TIntermAggregate* node = new TIntermAggregate(EOpSequence);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000587
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000588 node->setLine(line);
589 TIntermConstantUnion* constIntNode;
590 TIntermSequence &sequenceVector = node->getSequence();
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000591 ConstantUnion* unionArray;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000592
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000593 for (int i = 0; i < fields.num; i++) {
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000594 unionArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000595 unionArray->setIConst(fields.offsets[i]);
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000596 constIntNode = addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), line);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000597 sequenceVector.push_back(constIntNode);
598 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000599
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000600 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000601}
602
603//
604// Create loop nodes.
605//
606TIntermNode* TIntermediate::addLoop(TIntermNode *init, TIntermNode* body, TIntermTyped* test, TIntermTyped* terminal, bool testFirst, TSourceLoc line)
607{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000608 TIntermNode* node = new TIntermLoop(init, body, test, terminal, testFirst);
609 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000610
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000611 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000612}
613
614//
615// Add branches.
616//
617TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TSourceLoc line)
618{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000619 return addBranch(branchOp, 0, line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000620}
621
622TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, TSourceLoc line)
623{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000624 TIntermBranch* node = new TIntermBranch(branchOp, expression);
625 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000626
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000627 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000628}
629
630//
631// This is to be executed once the final root is put on top by the parsing
632// process.
633//
alokp@chromium.org07620a52010-09-23 17:53:56 +0000634bool TIntermediate::postProcess(TIntermNode* root)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000635{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000636 if (root == 0)
637 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000638
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000639 //
640 // First, finish off the top level sequence, if any
641 //
642 TIntermAggregate* aggRoot = root->getAsAggregate();
643 if (aggRoot && aggRoot->getOp() == EOpNull)
alokp@chromium.org58e54292010-08-24 21:40:03 +0000644 aggRoot->setOp(EOpSequence);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000645
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000646 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000647}
648
649//
650// This deletes the tree.
651//
652void TIntermediate::remove(TIntermNode* root)
653{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000654 if (root)
655 RemoveAllTreeNodes(root);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000656}
657
658////////////////////////////////////////////////////////////////
659//
660// Member functions of the nodes used for building the tree.
661//
662////////////////////////////////////////////////////////////////
663
664//
665// Say whether or not an operation node changes the value of a variable.
666//
667// Returns true if state is modified.
668//
669bool TIntermOperator::modifiesState() const
670{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000671 switch (op) {
672 case EOpPostIncrement:
673 case EOpPostDecrement:
674 case EOpPreIncrement:
675 case EOpPreDecrement:
676 case EOpAssign:
677 case EOpAddAssign:
678 case EOpSubAssign:
679 case EOpMulAssign:
680 case EOpVectorTimesMatrixAssign:
681 case EOpVectorTimesScalarAssign:
682 case EOpMatrixTimesScalarAssign:
683 case EOpMatrixTimesMatrixAssign:
684 case EOpDivAssign:
685 return true;
686 default:
687 return false;
688 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000689}
690
691//
692// returns true if the operator is for one of the constructors
693//
694bool TIntermOperator::isConstructor() const
695{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000696 switch (op) {
697 case EOpConstructVec2:
698 case EOpConstructVec3:
699 case EOpConstructVec4:
700 case EOpConstructMat2:
701 case EOpConstructMat3:
702 case EOpConstructMat4:
703 case EOpConstructFloat:
704 case EOpConstructIVec2:
705 case EOpConstructIVec3:
706 case EOpConstructIVec4:
707 case EOpConstructInt:
708 case EOpConstructBVec2:
709 case EOpConstructBVec3:
710 case EOpConstructBVec4:
711 case EOpConstructBool:
712 case EOpConstructStruct:
713 return true;
714 default:
715 return false;
716 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000717}
718//
719// Make sure the type of a unary operator is appropriate for its
720// combination of operation and operand type.
721//
722// Returns false in nothing makes sense.
723//
724bool TIntermUnary::promote(TInfoSink&)
725{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000726 switch (op) {
727 case EOpLogicalNot:
728 if (operand->getBasicType() != EbtBool)
729 return false;
730 break;
731 case EOpNegative:
732 case EOpPostIncrement:
733 case EOpPostDecrement:
734 case EOpPreIncrement:
735 case EOpPreDecrement:
736 if (operand->getBasicType() == EbtBool)
737 return false;
738 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000739
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000740 // operators for built-ins are already type checked against their prototype
741 case EOpAny:
742 case EOpAll:
743 case EOpVectorLogicalNot:
744 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000745
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000746 default:
747 if (operand->getBasicType() != EbtFloat)
748 return false;
749 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000750
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000751 setType(operand->getType());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000752
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000753 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000754}
755
756//
757// Establishes the type of the resultant operation, as well as
758// makes the operator the correct one for the operands.
759//
760// Returns false if operator can't work on operands.
761//
762bool TIntermBinary::promote(TInfoSink& infoSink)
763{
alokp@chromium.org8f0f24a2010-09-01 21:06:24 +0000764 // This function only handles scalars, vectors, and matrices.
765 if (left->isArray() || right->isArray()) {
766 infoSink.info.message(EPrefixInternalError, "Invalid operation for arrays", getLine());
767 return false;
768 }
769
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000770 // GLSL ES 2.0 does not support implicit type casting.
771 // So the basic type should always match.
772 if (left->getBasicType() != right->getBasicType())
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000773 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000774
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000775 //
776 // Base assumption: just make the type the same as the left
777 // operand. Then only deviations from this need be coded.
778 //
daniel@transgaming.comfe565152010-04-10 05:29:07 +0000779 setType(left->getType());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000780
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000781 // The result gets promoted to the highest precision.
782 TPrecision higherPrecision = GetHigherPrecision(left->getPrecision(), right->getPrecision());
alokp@chromium.org58e54292010-08-24 21:40:03 +0000783 getTypePointer()->setPrecision(higherPrecision);
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000784
785 // Binary operations results in temporary variables unless both
786 // operands are const.
787 if (left->getQualifier() != EvqConst || right->getQualifier() != EvqConst) {
alokp@chromium.org58e54292010-08-24 21:40:03 +0000788 getTypePointer()->setQualifier(EvqTemporary);
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000789 }
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000790
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000791 int size = std::max(left->getNominalSize(), right->getNominalSize());
792
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000793 //
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000794 // All scalars. Code after this test assumes this case is removed!
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000795 //
796 if (size == 1) {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000797 switch (op) {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000798 //
799 // Promote to conditional
800 //
801 case EOpEqual:
802 case EOpNotEqual:
803 case EOpLessThan:
804 case EOpGreaterThan:
805 case EOpLessThanEqual:
806 case EOpGreaterThanEqual:
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000807 setType(TType(EbtBool, EbpUndefined));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000808 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000809
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000810 //
811 // And and Or operate on conditionals
812 //
813 case EOpLogicalAnd:
814 case EOpLogicalOr:
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000815 // Both operands must be of type bool.
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000816 if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool)
817 return false;
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000818 setType(TType(EbtBool, EbpUndefined));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000819 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000820
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000821 default:
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000822 break;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000823 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000824 return true;
825 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000826
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000827 // If we reach here, at least one of the operands is vector or matrix.
828 // The other operand could be a scalar, vector, or matrix.
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000829 // Are the sizes compatible?
830 //
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000831 if (left->getNominalSize() != right->getNominalSize()) {
832 // If the nominal size of operands do not match:
833 // One of them must be scalar.
834 if (left->getNominalSize() != 1 && right->getNominalSize() != 1)
835 return false;
836 // Operator cannot be of type pure assignment.
837 if (op == EOpAssign || op == EOpInitialize)
838 return false;
839 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000840
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000841 //
842 // Can these two operands be combined?
843 //
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000844 TBasicType basicType = left->getBasicType();
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000845 switch (op) {
846 case EOpMul:
847 if (!left->isMatrix() && right->isMatrix()) {
848 if (left->isVector())
849 op = EOpVectorTimesMatrix;
850 else {
851 op = EOpMatrixTimesScalar;
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000852 setType(TType(basicType, higherPrecision, EvqTemporary, size, true));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000853 }
854 } else if (left->isMatrix() && !right->isMatrix()) {
855 if (right->isVector()) {
856 op = EOpMatrixTimesVector;
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000857 setType(TType(basicType, higherPrecision, EvqTemporary, size, false));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000858 } else {
859 op = EOpMatrixTimesScalar;
860 }
861 } else if (left->isMatrix() && right->isMatrix()) {
862 op = EOpMatrixTimesMatrix;
863 } else if (!left->isMatrix() && !right->isMatrix()) {
864 if (left->isVector() && right->isVector()) {
865 // leave as component product
866 } else if (left->isVector() || right->isVector()) {
867 op = EOpVectorTimesScalar;
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000868 setType(TType(basicType, higherPrecision, EvqTemporary, size, false));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000869 }
870 } else {
871 infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
872 return false;
873 }
874 break;
875 case EOpMulAssign:
876 if (!left->isMatrix() && right->isMatrix()) {
877 if (left->isVector())
878 op = EOpVectorTimesMatrixAssign;
879 else {
880 return false;
881 }
882 } else if (left->isMatrix() && !right->isMatrix()) {
883 if (right->isVector()) {
884 return false;
885 } else {
886 op = EOpMatrixTimesScalarAssign;
887 }
888 } else if (left->isMatrix() && right->isMatrix()) {
889 op = EOpMatrixTimesMatrixAssign;
890 } else if (!left->isMatrix() && !right->isMatrix()) {
891 if (left->isVector() && right->isVector()) {
892 // leave as component product
893 } else if (left->isVector() || right->isVector()) {
894 if (! left->isVector())
895 return false;
896 op = EOpVectorTimesScalarAssign;
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000897 setType(TType(basicType, higherPrecision, EvqTemporary, size, false));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000898 }
899 } else {
900 infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
901 return false;
902 }
903 break;
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000904
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000905 case EOpAssign:
906 case EOpInitialize:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000907 case EOpAdd:
908 case EOpSub:
909 case EOpDiv:
910 case EOpAddAssign:
911 case EOpSubAssign:
912 case EOpDivAssign:
913 if (left->isMatrix() && right->isVector() ||
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000914 left->isVector() && right->isMatrix())
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000915 return false;
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000916 setType(TType(basicType, higherPrecision, EvqTemporary, size, left->isMatrix() || right->isMatrix()));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000917 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000918
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000919 case EOpEqual:
920 case EOpNotEqual:
921 case EOpLessThan:
922 case EOpGreaterThan:
923 case EOpLessThanEqual:
924 case EOpGreaterThanEqual:
925 if (left->isMatrix() && right->isVector() ||
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000926 left->isVector() && right->isMatrix())
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000927 return false;
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000928 setType(TType(EbtBool, EbpUndefined));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000929 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000930
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000931 default:
932 return false;
933 }
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000934
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000935 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000936}
937
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000938bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000939{
alokp@chromium.org58e54292010-08-24 21:40:03 +0000940 const TTypeList* fields = leftNodeType.getStruct();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000941
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000942 size_t structSize = fields->size();
943 int index = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000944
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000945 for (size_t j = 0; j < structSize; j++) {
946 int size = (*fields)[j].type->getObjectSize();
947 for (int i = 0; i < size; i++) {
948 if ((*fields)[j].type->getBasicType() == EbtStruct) {
949 if (!CompareStructure(*(*fields)[j].type, &rightUnionArray[index], &leftUnionArray[index]))
950 return false;
951 } else {
952 if (leftUnionArray[index] != rightUnionArray[index])
953 return false;
954 index++;
955 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000956
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000957 }
958 }
959 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000960}
961
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000962bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000963{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000964 if (leftNodeType.isArray()) {
965 TType typeWithoutArrayness = leftNodeType;
966 typeWithoutArrayness.clearArrayness();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000967
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000968 int arraySize = leftNodeType.getArraySize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000969
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000970 for (int i = 0; i < arraySize; ++i) {
971 int offset = typeWithoutArrayness.getObjectSize() * i;
972 if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset]))
973 return false;
974 }
975 } else
976 return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000977
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000978 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000979}
980
981//
982// The fold functions see if an operation on a constant can be done in place,
983// without generating run-time code.
984//
985// Returns the node to keep using, which may or may not be the node passed in.
986//
987
988TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink)
989{
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000990 ConstantUnion *unionArray = getUnionArrayPointer();
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000991 int objectSize = getType().getObjectSize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000992
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000993 if (constantNode) { // binary operations
994 TIntermConstantUnion *node = constantNode->getAsConstantUnion();
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000995 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000996 TType returnType = getType();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000997
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000998 // for a case like float f = 1.2 + vec4(2,3,4,5);
999 if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) {
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001000 rightUnionArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001001 for (int i = 0; i < objectSize; ++i)
1002 rightUnionArray[i] = *node->getUnionArrayPointer();
1003 returnType = getType();
1004 } else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) {
1005 // for a case like float f = vec4(2,3,4,5) + 1.2;
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001006 unionArray = new ConstantUnion[constantNode->getType().getObjectSize()];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001007 for (int i = 0; i < constantNode->getType().getObjectSize(); ++i)
1008 unionArray[i] = *getUnionArrayPointer();
1009 returnType = node->getType();
1010 objectSize = constantNode->getType().getObjectSize();
1011 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001012
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001013 ConstantUnion* tempConstArray = 0;
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001014 TIntermConstantUnion *tempNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001015
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001016 bool boolNodeFlag = false;
1017 switch(op) {
1018 case EOpAdd:
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001019 tempConstArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001020 {// support MSVC++6.0
1021 for (int i = 0; i < objectSize; i++)
1022 tempConstArray[i] = unionArray[i] + rightUnionArray[i];
1023 }
1024 break;
1025 case EOpSub:
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001026 tempConstArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001027 {// support MSVC++6.0
1028 for (int i = 0; i < objectSize; i++)
1029 tempConstArray[i] = unionArray[i] - rightUnionArray[i];
1030 }
1031 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001032
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001033 case EOpMul:
1034 case EOpVectorTimesScalar:
1035 case EOpMatrixTimesScalar:
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001036 tempConstArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001037 {// support MSVC++6.0
1038 for (int i = 0; i < objectSize; i++)
1039 tempConstArray[i] = unionArray[i] * rightUnionArray[i];
1040 }
1041 break;
1042 case EOpMatrixTimesMatrix:
1043 if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat) {
1044 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
1045 return 0;
1046 }
1047 {// support MSVC++6.0
1048 int size = getNominalSize();
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001049 tempConstArray = new ConstantUnion[size*size];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001050 for (int row = 0; row < size; row++) {
1051 for (int column = 0; column < size; column++) {
1052 tempConstArray[size * column + row].setFConst(0.0f);
1053 for (int i = 0; i < size; i++) {
1054 tempConstArray[size * column + row].setFConst(tempConstArray[size * column + row].getFConst() + unionArray[i * size + row].getFConst() * (rightUnionArray[column * size + i].getFConst()));
1055 }
1056 }
1057 }
1058 }
1059 break;
1060 case EOpDiv:
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001061 tempConstArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001062 {// support MSVC++6.0
1063 for (int i = 0; i < objectSize; i++) {
1064 switch (getType().getBasicType()) {
1065 case EbtFloat:
1066 if (rightUnionArray[i] == 0.0f) {
1067 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1068 tempConstArray[i].setFConst(FLT_MAX);
1069 } else
1070 tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst());
1071 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001072
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001073 case EbtInt:
1074 if (rightUnionArray[i] == 0) {
1075 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1076 tempConstArray[i].setIConst(INT_MAX);
1077 } else
1078 tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst());
1079 break;
1080 default:
1081 infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"/\"", getLine());
1082 return 0;
1083 }
1084 }
1085 }
1086 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001087
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001088 case EOpMatrixTimesVector:
1089 if (node->getBasicType() != EbtFloat) {
1090 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix times vector", getLine());
1091 return 0;
1092 }
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001093 tempConstArray = new ConstantUnion[getNominalSize()];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001094
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001095 {// support MSVC++6.0
1096 for (int size = getNominalSize(), i = 0; i < size; i++) {
1097 tempConstArray[i].setFConst(0.0f);
1098 for (int j = 0; j < size; j++) {
1099 tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j*size + i].getFConst()) * rightUnionArray[j].getFConst()));
1100 }
1101 }
1102 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001103
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001104 tempNode = new TIntermConstantUnion(tempConstArray, node->getType());
1105 tempNode->setLine(getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001106
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001107 return tempNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001108
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001109 case EOpVectorTimesMatrix:
1110 if (getType().getBasicType() != EbtFloat) {
1111 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for vector times matrix", getLine());
1112 return 0;
1113 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001114
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001115 tempConstArray = new ConstantUnion[getNominalSize()];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001116 {// support MSVC++6.0
1117 for (int size = getNominalSize(), i = 0; i < size; i++) {
1118 tempConstArray[i].setFConst(0.0f);
1119 for (int j = 0; j < size; j++) {
1120 tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j].getFConst()) * rightUnionArray[i*size + j].getFConst()));
1121 }
1122 }
1123 }
1124 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001125
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001126 case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001127 tempConstArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001128 {// support MSVC++6.0
1129 for (int i = 0; i < objectSize; i++)
1130 tempConstArray[i] = unionArray[i] && rightUnionArray[i];
1131 }
1132 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001133
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001134 case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001135 tempConstArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001136 {// support MSVC++6.0
1137 for (int i = 0; i < objectSize; i++)
1138 tempConstArray[i] = unionArray[i] || rightUnionArray[i];
1139 }
1140 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001141
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001142 case EOpLogicalXor:
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001143 tempConstArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001144 {// support MSVC++6.0
1145 for (int i = 0; i < objectSize; i++)
1146 switch (getType().getBasicType()) {
1147 case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break;
1148 default: assert(false && "Default missing");
1149 }
1150 }
1151 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001152
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001153 case EOpLessThan:
1154 assert(objectSize == 1);
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001155 tempConstArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001156 tempConstArray->setBConst(*unionArray < *rightUnionArray);
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001157 returnType = TType(EbtBool, EbpUndefined, EvqConst);
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001158 break;
1159 case EOpGreaterThan:
1160 assert(objectSize == 1);
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001161 tempConstArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001162 tempConstArray->setBConst(*unionArray > *rightUnionArray);
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001163 returnType = TType(EbtBool, EbpUndefined, EvqConst);
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001164 break;
1165 case EOpLessThanEqual:
1166 {
1167 assert(objectSize == 1);
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001168 ConstantUnion constant;
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001169 constant.setBConst(*unionArray > *rightUnionArray);
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001170 tempConstArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001171 tempConstArray->setBConst(!constant.getBConst());
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001172 returnType = TType(EbtBool, EbpUndefined, EvqConst);
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001173 break;
1174 }
1175 case EOpGreaterThanEqual:
1176 {
1177 assert(objectSize == 1);
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001178 ConstantUnion constant;
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001179 constant.setBConst(*unionArray < *rightUnionArray);
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001180 tempConstArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001181 tempConstArray->setBConst(!constant.getBConst());
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001182 returnType = TType(EbtBool, EbpUndefined, EvqConst);
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001183 break;
1184 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001185
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001186 case EOpEqual:
1187 if (getType().getBasicType() == EbtStruct) {
1188 if (!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
1189 boolNodeFlag = true;
1190 } else {
1191 for (int i = 0; i < objectSize; i++) {
1192 if (unionArray[i] != rightUnionArray[i]) {
1193 boolNodeFlag = true;
1194 break; // break out of for loop
1195 }
1196 }
1197 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001198
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001199 tempConstArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001200 if (!boolNodeFlag) {
1201 tempConstArray->setBConst(true);
1202 }
1203 else {
1204 tempConstArray->setBConst(false);
1205 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001206
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001207 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001208 tempNode->setLine(getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001209
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001210 return tempNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001211
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001212 case EOpNotEqual:
1213 if (getType().getBasicType() == EbtStruct) {
1214 if (CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
1215 boolNodeFlag = true;
1216 } else {
1217 for (int i = 0; i < objectSize; i++) {
1218 if (unionArray[i] == rightUnionArray[i]) {
1219 boolNodeFlag = true;
1220 break; // break out of for loop
1221 }
1222 }
1223 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001224
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001225 tempConstArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001226 if (!boolNodeFlag) {
1227 tempConstArray->setBConst(true);
1228 }
1229 else {
1230 tempConstArray->setBConst(false);
1231 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001232
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001233 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001234 tempNode->setLine(getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001235
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001236 return tempNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001237
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001238 default:
1239 infoSink.info.message(EPrefixInternalError, "Invalid operator for constant folding", getLine());
1240 return 0;
1241 }
1242 tempNode = new TIntermConstantUnion(tempConstArray, returnType);
1243 tempNode->setLine(getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001244
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001245 return tempNode;
1246 } else {
1247 //
1248 // Do unary operations
1249 //
1250 TIntermConstantUnion *newNode = 0;
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001251 ConstantUnion* tempConstArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001252 for (int i = 0; i < objectSize; i++) {
1253 switch(op) {
1254 case EOpNegative:
1255 switch (getType().getBasicType()) {
1256 case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break;
1257 case EbtInt: tempConstArray[i].setIConst(-unionArray[i].getIConst()); break;
1258 default:
1259 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1260 return 0;
1261 }
1262 break;
1263 case EOpLogicalNot: // this code is written for possible future use, will not get executed currently
1264 switch (getType().getBasicType()) {
1265 case EbtBool: tempConstArray[i].setBConst(!unionArray[i].getBConst()); break;
1266 default:
1267 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1268 return 0;
1269 }
1270 break;
1271 default:
1272 return 0;
1273 }
1274 }
1275 newNode = new TIntermConstantUnion(tempConstArray, getType());
1276 newNode->setLine(getLine());
1277 return newNode;
1278 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001279
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001280 return this;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001281}
1282
1283TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node)
1284{
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001285 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001286 int size = node->getType().getObjectSize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001287
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001288 ConstantUnion *leftUnionArray = new ConstantUnion[size];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001289
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001290 for (int i=0; i < size; i++) {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001291
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001292 switch (promoteTo) {
1293 case EbtFloat:
1294 switch (node->getType().getBasicType()) {
1295 case EbtInt:
1296 leftUnionArray[i].setFConst(static_cast<float>(rightUnionArray[i].getIConst()));
1297 break;
1298 case EbtBool:
1299 leftUnionArray[i].setFConst(static_cast<float>(rightUnionArray[i].getBConst()));
1300 break;
1301 case EbtFloat:
1302 leftUnionArray[i] = rightUnionArray[i];
1303 break;
1304 default:
1305 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1306 return 0;
1307 }
1308 break;
1309 case EbtInt:
1310 switch (node->getType().getBasicType()) {
1311 case EbtInt:
1312 leftUnionArray[i] = rightUnionArray[i];
1313 break;
1314 case EbtBool:
1315 leftUnionArray[i].setIConst(static_cast<int>(rightUnionArray[i].getBConst()));
1316 break;
1317 case EbtFloat:
1318 leftUnionArray[i].setIConst(static_cast<int>(rightUnionArray[i].getFConst()));
1319 break;
1320 default:
1321 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1322 return 0;
1323 }
1324 break;
1325 case EbtBool:
1326 switch (node->getType().getBasicType()) {
1327 case EbtInt:
1328 leftUnionArray[i].setBConst(rightUnionArray[i].getIConst() != 0);
1329 break;
1330 case EbtBool:
1331 leftUnionArray[i] = rightUnionArray[i];
1332 break;
1333 case EbtFloat:
1334 leftUnionArray[i].setBConst(rightUnionArray[i].getFConst() != 0.0f);
1335 break;
1336 default:
1337 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1338 return 0;
1339 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001340
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001341 break;
1342 default:
1343 infoSink.info.message(EPrefixInternalError, "Incorrect data type found", node->getLine());
1344 return 0;
1345 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001346
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001347 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001348
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001349 const TType& t = node->getType();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001350
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001351 return addConstantUnion(leftUnionArray, TType(promoteTo, t.getPrecision(), t.getQualifier(), t.getNominalSize(), t.isMatrix(), t.isArray()), node->getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001352}
1353
1354void TIntermAggregate::addToPragmaTable(const TPragmaTable& pTable)
1355{
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001356 assert(!pragmaTable);
1357 pragmaTable = new TPragmaTable();
1358 *pragmaTable = pTable;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001359}