blob: 4a1e02fbf8b6a66323bd45065fa5d38728145816 [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) {
54 case EOpLessThan:
55 case EOpGreaterThan:
56 case EOpLessThanEqual:
57 case EOpGreaterThanEqual:
58 if (left->getType().isMatrix() || left->getType().isArray() || left->getType().isVector() || left->getType().getBasicType() == EbtStruct) {
59 return 0;
60 }
61 break;
62 case EOpLogicalOr:
63 case EOpLogicalXor:
64 case EOpLogicalAnd:
65 if (left->getType().getBasicType() != EbtBool || left->getType().isMatrix() || left->getType().isArray() || left->getType().isVector()) {
66 return 0;
67 }
68 break;
69 case EOpAdd:
70 case EOpSub:
71 case EOpDiv:
72 case EOpMul:
73 if (left->getType().getBasicType() == EbtStruct || left->getType().getBasicType() == EbtBool)
74 return 0;
75 default: break;
76 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000077
alokp@chromium.org2cf17712010-03-30 20:33:18 +000078 //
79 // First try converting the children to compatible types.
80 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000081
alokp@chromium.org2cf17712010-03-30 20:33:18 +000082 if (!(left->getType().getStruct() && right->getType().getStruct())) {
83 TIntermTyped* child = addConversion(op, left->getType(), right);
84 if (child)
85 right = child;
86 else {
87 child = addConversion(op, right->getType(), left);
88 if (child)
89 left = child;
90 else
91 return 0;
92 }
93 } else {
94 if (left->getType() != right->getType())
95 return 0;
96 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000097
98
alokp@chromium.org2cf17712010-03-30 20:33:18 +000099 //
100 // Need a new node holding things together then. Make
101 // one and promote it to the right type.
102 //
103 TIntermBinary* node = new TIntermBinary(op);
104 if (line == 0)
105 line = right->getLine();
106 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000107
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000108 node->setLeft(left);
109 node->setRight(right);
110 if (! node->promote(infoSink))
111 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000112
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000113 TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
114 TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
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 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000119
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000120 TIntermTyped* typedReturnNode = 0;
121 if ( leftTempConstant && rightTempConstant) {
122 typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000123
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000124 if (typedReturnNode)
125 return typedReturnNode;
126 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000127
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000128 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000129}
130
131//
132// Connect two nodes through an assignment.
133//
134// Returns the added node.
135//
136TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line)
137{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000138 //
139 // Like adding binary math, except the conversion can only go
140 // from right to left.
141 //
142 TIntermBinary* node = new TIntermBinary(op);
143 if (line == 0)
144 line = left->getLine();
145 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000146
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000147 TIntermTyped* child = addConversion(op, left->getType(), right);
148 if (child == 0)
149 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000150
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000151 node->setLeft(left);
152 node->setRight(child);
153 if (! node->promote(infoSink))
154 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000155
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000156 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000157}
158
159//
160// Connect two nodes through an index operator, where the left node is the base
161// of an array or struct, and the right node is a direct or indirect offset.
162//
163// Returns the added node.
164// The caller should set the type of the returned node.
165//
166TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc line)
167{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000168 TIntermBinary* node = new TIntermBinary(op);
169 if (line == 0)
170 line = index->getLine();
171 node->setLine(line);
172 node->setLeft(base);
173 node->setRight(index);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000174
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000175 // caller should set the type
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000176
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000177 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000178}
179
180//
181// Add one node as the parent of another that it operates on.
182//
183// Returns the added node.
184//
185TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, TSourceLoc line, TSymbolTable& symbolTable)
186{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000187 TIntermUnary* node;
188 TIntermTyped* child = childNode->getAsTyped();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000189
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000190 if (child == 0) {
191 infoSink.info.message(EPrefixInternalError, "Bad type in AddUnaryMath", line);
192 return 0;
193 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000194
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000195 switch (op) {
196 case EOpLogicalNot:
197 if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) {
198 return 0;
199 }
200 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000201
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000202 case EOpPostIncrement:
203 case EOpPreIncrement:
204 case EOpPostDecrement:
205 case EOpPreDecrement:
206 case EOpNegative:
207 if (child->getType().getBasicType() == EbtStruct || child->getType().isArray())
208 return 0;
209 default: break;
210 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000211
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000212 //
213 // Do we need to promote the operand?
214 //
215 // Note: Implicit promotions were removed from the language.
216 //
217 TBasicType newType = EbtVoid;
218 switch (op) {
219 case EOpConstructInt: newType = EbtInt; break;
220 case EOpConstructBool: newType = EbtBool; break;
221 case EOpConstructFloat: newType = EbtFloat; break;
222 default: break;
223 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000224
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000225 if (newType != EbtVoid) {
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000226 child = addConversion(op, TType(newType, child->getPrecision(), EvqTemporary,
227 child->getNominalSize(),
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000228 child->isMatrix(),
229 child->isArray()),
230 child);
231 if (child == 0)
232 return 0;
233 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000234
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000235 //
236 // For constructors, we are now done, it's all in the conversion.
237 //
238 switch (op) {
239 case EOpConstructInt:
240 case EOpConstructBool:
241 case EOpConstructFloat:
242 return child;
243 default: break;
244 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000245
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000246 TIntermConstantUnion *childTempConstant = 0;
247 if (child->getAsConstantUnion())
248 childTempConstant = child->getAsConstantUnion();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000249
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000250 //
251 // Make a new node for the operator.
252 //
253 node = new TIntermUnary(op);
254 if (line == 0)
255 line = child->getLine();
256 node->setLine(line);
257 node->setOperand(child);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000258
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000259 if (! node->promote(infoSink))
260 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000261
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000262 if (childTempConstant) {
263 TIntermTyped* newChild = childTempConstant->fold(op, 0, infoSink);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000264
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000265 if (newChild)
266 return newChild;
267 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000268
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000269 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000270}
271
272//
273// This is the safe way to change the operator on an aggregate, as it
274// does lots of error checking and fixing. Especially for establishing
275// a function call's operation on it's set of parameters. Sequences
276// of instructions are also aggregates, but they just direnctly set
277// their operator to EOpSequence.
278//
279// Returns an aggregate node, which could be the one passed in if
280// it was already an aggregate.
281//
282TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, TSourceLoc line)
283{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000284 TIntermAggregate* aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000285
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000286 //
287 // Make sure we have an aggregate. If not turn it into one.
288 //
289 if (node) {
290 aggNode = node->getAsAggregate();
291 if (aggNode == 0 || aggNode->getOp() != EOpNull) {
292 //
293 // Make an aggregate containing this node.
294 //
295 aggNode = new TIntermAggregate();
296 aggNode->getSequence().push_back(node);
297 if (line == 0)
298 line = node->getLine();
299 }
300 } else
301 aggNode = new TIntermAggregate();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000302
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000303 //
304 // Set the operator.
305 //
306 aggNode->setOperator(op);
307 if (line != 0)
308 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000309
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000310 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000311}
312
313//
314// Convert one type to another.
315//
316// Returns the node representing the conversion, which could be the same
317// node passed in if no conversion was needed.
318//
319// Return 0 if a conversion can't be done.
320//
321TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TIntermTyped* node)
322{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000323 //
324 // Does the base type allow operation?
325 //
326 switch (node->getBasicType()) {
327 case EbtVoid:
328 case EbtSampler2D:
329 case EbtSamplerCube:
330 return 0;
331 default: break;
332 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000333
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000334 //
335 // Otherwise, if types are identical, no problem
336 //
337 if (type == node->getType())
338 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000339
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000340 //
341 // If one's a structure, then no conversions.
342 //
343 if (type.getStruct() || node->getType().getStruct())
344 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000345
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000346 //
347 // If one's an array, then no conversions.
348 //
349 if (type.isArray() || node->getType().isArray())
350 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000351
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000352 TBasicType promoteTo;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000353
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000354 switch (op) {
355 //
356 // Explicit conversions
357 //
358 case EOpConstructBool:
359 promoteTo = EbtBool;
360 break;
361 case EOpConstructFloat:
362 promoteTo = EbtFloat;
363 break;
364 case EOpConstructInt:
365 promoteTo = EbtInt;
366 break;
367 default:
368 //
369 // implicit conversions were removed from the language.
370 //
371 if (type.getBasicType() != node->getType().getBasicType())
372 return 0;
373 //
374 // Size and structure could still differ, but that's
375 // handled by operator promotion.
376 //
377 return node;
378 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000379
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000380 if (node->getAsConstantUnion()) {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000381
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000382 return (promoteConstantUnion(promoteTo, node->getAsConstantUnion()));
383 } else {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000384
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000385 //
386 // Add a new newNode for the conversion.
387 //
388 TIntermUnary* newNode = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000389
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000390 TOperator newOp = EOpNull;
391 switch (promoteTo) {
392 case EbtFloat:
393 switch (node->getBasicType()) {
394 case EbtInt: newOp = EOpConvIntToFloat; break;
395 case EbtBool: newOp = EOpConvBoolToFloat; break;
396 default:
397 infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
398 return 0;
399 }
400 break;
401 case EbtBool:
402 switch (node->getBasicType()) {
403 case EbtInt: newOp = EOpConvIntToBool; break;
404 case EbtFloat: newOp = EOpConvFloatToBool; break;
405 default:
406 infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
407 return 0;
408 }
409 break;
410 case EbtInt:
411 switch (node->getBasicType()) {
412 case EbtBool: newOp = EOpConvBoolToInt; break;
413 case EbtFloat: newOp = EOpConvFloatToInt; break;
414 default:
415 infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
416 return 0;
417 }
418 break;
419 default:
420 infoSink.info.message(EPrefixInternalError, "Bad promotion type", node->getLine());
421 return 0;
422 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000423
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000424 TType type(promoteTo, node->getPrecision(), EvqTemporary, node->getNominalSize(), node->isMatrix(), node->isArray());
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000425 newNode = new TIntermUnary(newOp, type);
426 newNode->setLine(node->getLine());
427 newNode->setOperand(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000428
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000429 return newNode;
430 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000431}
432
433//
434// Safe way to combine two nodes into an aggregate. Works with null pointers,
435// a node that's not a aggregate yet, etc.
436//
437// Returns the resulting aggregate, unless 0 was passed in for
438// both existing nodes.
439//
440TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, TSourceLoc line)
441{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000442 if (left == 0 && right == 0)
443 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000444
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000445 TIntermAggregate* aggNode = 0;
446 if (left)
447 aggNode = left->getAsAggregate();
448 if (!aggNode || aggNode->getOp() != EOpNull) {
449 aggNode = new TIntermAggregate;
450 if (left)
451 aggNode->getSequence().push_back(left);
452 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000453
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000454 if (right)
455 aggNode->getSequence().push_back(right);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000456
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000457 if (line != 0)
458 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000459
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000460 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000461}
462
463//
464// Turn an existing node into an aggregate.
465//
466// Returns an aggregate, unless 0 was passed in for the existing node.
467//
468TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, TSourceLoc line)
469{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000470 if (node == 0)
471 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000472
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000473 TIntermAggregate* aggNode = new TIntermAggregate;
474 aggNode->getSequence().push_back(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000475
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000476 if (line != 0)
477 aggNode->setLine(line);
478 else
479 aggNode->setLine(node->getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000480
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000481 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000482}
483
484//
485// For "if" test nodes. There are three children; a condition,
486// a true path, and a false path. The two paths are in the
487// nodePair.
488//
489// Returns the selection node created.
490//
491TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, TSourceLoc line)
492{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000493 //
494 // For compile time constant selections, prune the code and
495 // test now.
496 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000497
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000498 if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion()) {
499 if (cond->getAsTyped()->getAsConstantUnion()->getUnionArrayPointer()->getBConst())
500 return nodePair.node1;
501 else
502 return nodePair.node2;
503 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000504
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000505 TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2);
506 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000507
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000508 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000509}
510
511
512TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc line)
513{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000514 if (left->getType().getQualifier() == EvqConst && right->getType().getQualifier() == EvqConst) {
515 return right;
516 } else {
517 TIntermTyped *commaAggregate = growAggregate(left, right, line);
518 commaAggregate->getAsAggregate()->setOperator(EOpComma);
519 commaAggregate->setType(right->getType());
520 commaAggregate->getTypePointer()->changeQualifier(EvqTemporary);
521 return commaAggregate;
522 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000523}
524
525//
526// For "?:" test nodes. There are three children; a condition,
527// a true path, and a false path. The two paths are specified
528// as separate parameters.
529//
530// Returns the selection node created, or 0 if one could not be.
531//
532TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, TSourceLoc line)
533{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000534 //
535 // Get compatible types.
536 //
537 TIntermTyped* child = addConversion(EOpSequence, trueBlock->getType(), falseBlock);
538 if (child)
539 falseBlock = child;
540 else {
541 child = addConversion(EOpSequence, falseBlock->getType(), trueBlock);
542 if (child)
543 trueBlock = child;
544 else
545 return 0;
546 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000547
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000548 //
549 // See if all the operands are constant, then fold it otherwise not.
550 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000551
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000552 if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) {
553 if (cond->getAsConstantUnion()->getUnionArrayPointer()->getBConst())
554 return trueBlock;
555 else
556 return falseBlock;
557 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000558
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000559 //
560 // Make a selection node.
561 //
562 TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
563 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000564
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000565 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000566}
567
568//
569// Constant terminal nodes. Has a union that contains bool, float or int constants
570//
571// Returns the constant union node created.
572//
573
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000574TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, TSourceLoc line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000575{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000576 TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t);
577 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000578
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000579 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000580}
581
582TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, TSourceLoc line)
583{
584
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000585 TIntermAggregate* node = new TIntermAggregate(EOpSequence);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000586
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000587 node->setLine(line);
588 TIntermConstantUnion* constIntNode;
589 TIntermSequence &sequenceVector = node->getSequence();
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000590 ConstantUnion* unionArray;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000591
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000592 for (int i = 0; i < fields.num; i++) {
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000593 unionArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000594 unionArray->setIConst(fields.offsets[i]);
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000595 constIntNode = addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), line);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000596 sequenceVector.push_back(constIntNode);
597 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000598
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000599 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000600}
601
602//
603// Create loop nodes.
604//
605TIntermNode* TIntermediate::addLoop(TIntermNode *init, TIntermNode* body, TIntermTyped* test, TIntermTyped* terminal, bool testFirst, TSourceLoc line)
606{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000607 TIntermNode* node = new TIntermLoop(init, body, test, terminal, testFirst);
608 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000609
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000610 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000611}
612
613//
614// Add branches.
615//
616TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TSourceLoc line)
617{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000618 return addBranch(branchOp, 0, line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000619}
620
621TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, TSourceLoc line)
622{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000623 TIntermBranch* node = new TIntermBranch(branchOp, expression);
624 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000625
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000626 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000627}
628
629//
630// This is to be executed once the final root is put on top by the parsing
631// process.
632//
633bool TIntermediate::postProcess(TIntermNode* root, EShLanguage language)
634{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000635 if (root == 0)
636 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000637
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000638 //
639 // First, finish off the top level sequence, if any
640 //
641 TIntermAggregate* aggRoot = root->getAsAggregate();
642 if (aggRoot && aggRoot->getOp() == EOpNull)
643 aggRoot->setOperator(EOpSequence);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000644
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000645 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000646}
647
648//
649// This deletes the tree.
650//
651void TIntermediate::remove(TIntermNode* root)
652{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000653 if (root)
654 RemoveAllTreeNodes(root);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000655}
656
657////////////////////////////////////////////////////////////////
658//
659// Member functions of the nodes used for building the tree.
660//
661////////////////////////////////////////////////////////////////
662
663//
664// Say whether or not an operation node changes the value of a variable.
665//
666// Returns true if state is modified.
667//
668bool TIntermOperator::modifiesState() const
669{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000670 switch (op) {
671 case EOpPostIncrement:
672 case EOpPostDecrement:
673 case EOpPreIncrement:
674 case EOpPreDecrement:
675 case EOpAssign:
676 case EOpAddAssign:
677 case EOpSubAssign:
678 case EOpMulAssign:
679 case EOpVectorTimesMatrixAssign:
680 case EOpVectorTimesScalarAssign:
681 case EOpMatrixTimesScalarAssign:
682 case EOpMatrixTimesMatrixAssign:
683 case EOpDivAssign:
684 return true;
685 default:
686 return false;
687 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000688}
689
690//
691// returns true if the operator is for one of the constructors
692//
693bool TIntermOperator::isConstructor() const
694{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000695 switch (op) {
696 case EOpConstructVec2:
697 case EOpConstructVec3:
698 case EOpConstructVec4:
699 case EOpConstructMat2:
700 case EOpConstructMat3:
701 case EOpConstructMat4:
702 case EOpConstructFloat:
703 case EOpConstructIVec2:
704 case EOpConstructIVec3:
705 case EOpConstructIVec4:
706 case EOpConstructInt:
707 case EOpConstructBVec2:
708 case EOpConstructBVec3:
709 case EOpConstructBVec4:
710 case EOpConstructBool:
711 case EOpConstructStruct:
712 return true;
713 default:
714 return false;
715 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000716}
717//
718// Make sure the type of a unary operator is appropriate for its
719// combination of operation and operand type.
720//
721// Returns false in nothing makes sense.
722//
723bool TIntermUnary::promote(TInfoSink&)
724{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000725 switch (op) {
726 case EOpLogicalNot:
727 if (operand->getBasicType() != EbtBool)
728 return false;
729 break;
730 case EOpNegative:
731 case EOpPostIncrement:
732 case EOpPostDecrement:
733 case EOpPreIncrement:
734 case EOpPreDecrement:
735 if (operand->getBasicType() == EbtBool)
736 return false;
737 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000738
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000739 // operators for built-ins are already type checked against their prototype
740 case EOpAny:
741 case EOpAll:
742 case EOpVectorLogicalNot:
743 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000744
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000745 default:
746 if (operand->getBasicType() != EbtFloat)
747 return false;
748 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000749
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000750 setType(operand->getType());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000751
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000752 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000753}
754
755//
756// Establishes the type of the resultant operation, as well as
757// makes the operator the correct one for the operands.
758//
759// Returns false if operator can't work on operands.
760//
761bool TIntermBinary::promote(TInfoSink& infoSink)
762{
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000763 // GLSL ES 2.0 does not support implicit type casting.
764 // So the basic type should always match.
765 if (left->getBasicType() != right->getBasicType())
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000766 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000767
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000768 //
769 // Base assumption: just make the type the same as the left
770 // operand. Then only deviations from this need be coded.
771 //
daniel@transgaming.comfe565152010-04-10 05:29:07 +0000772 setType(left->getType());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000773
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000774 // The result gets promoted to the highest precision.
775 TPrecision higherPrecision = GetHigherPrecision(left->getPrecision(), right->getPrecision());
776 getTypePointer()->changePrecision(higherPrecision);
777
778 // Binary operations results in temporary variables unless both
779 // operands are const.
780 if (left->getQualifier() != EvqConst || right->getQualifier() != EvqConst) {
781 getTypePointer()->changeQualifier(EvqTemporary);
782 }
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000783
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000784 //
785 // Array operations.
786 //
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000787 if (left->isArray() || right->isArray()) {
788 //
789 // Arrays types have to be exact matches.
790 //
791 if (left->getType() != right->getType())
792 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000793
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000794 switch (op) {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000795 //
796 // Promote to conditional
797 //
798 case EOpEqual:
799 case EOpNotEqual:
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000800 setType(TType(EbtBool, EbpUndefined));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000801 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000802
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000803 //
804 // Set array information.
805 //
806 case EOpAssign:
807 case EOpInitialize:
808 getTypePointer()->setArraySize(left->getType().getArraySize());
809 getTypePointer()->setArrayInformationType(left->getType().getArrayInformationType());
810 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000811
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000812 default:
813 return false;
814 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000815 return true;
816 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000817
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000818 int size = std::max(left->getNominalSize(), right->getNominalSize());
819
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000820 //
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000821 // All scalars. Code after this test assumes this case is removed!
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000822 //
823 if (size == 1) {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000824 switch (op) {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000825 //
826 // Promote to conditional
827 //
828 case EOpEqual:
829 case EOpNotEqual:
830 case EOpLessThan:
831 case EOpGreaterThan:
832 case EOpLessThanEqual:
833 case EOpGreaterThanEqual:
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000834 setType(TType(EbtBool, EbpUndefined));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000835 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000836
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000837 //
838 // And and Or operate on conditionals
839 //
840 case EOpLogicalAnd:
841 case EOpLogicalOr:
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000842 // Both operands must be of type bool.
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000843 if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool)
844 return false;
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000845 setType(TType(EbtBool, EbpUndefined));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000846 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000847
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000848 default:
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000849 break;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000850 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000851 return true;
852 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000853
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000854 // If we reach here, at least one of the operands is vector or matrix.
855 // The other operand could be a scalar, vector, or matrix.
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000856 // Are the sizes compatible?
857 //
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000858 if (left->getNominalSize() != right->getNominalSize()) {
859 // If the nominal size of operands do not match:
860 // One of them must be scalar.
861 if (left->getNominalSize() != 1 && right->getNominalSize() != 1)
862 return false;
863 // Operator cannot be of type pure assignment.
864 if (op == EOpAssign || op == EOpInitialize)
865 return false;
866 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000867
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000868 //
869 // Can these two operands be combined?
870 //
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000871 TBasicType basicType = left->getBasicType();
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000872 switch (op) {
873 case EOpMul:
874 if (!left->isMatrix() && right->isMatrix()) {
875 if (left->isVector())
876 op = EOpVectorTimesMatrix;
877 else {
878 op = EOpMatrixTimesScalar;
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000879 setType(TType(basicType, higherPrecision, EvqTemporary, size, true));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000880 }
881 } else if (left->isMatrix() && !right->isMatrix()) {
882 if (right->isVector()) {
883 op = EOpMatrixTimesVector;
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000884 setType(TType(basicType, higherPrecision, EvqTemporary, size, false));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000885 } else {
886 op = EOpMatrixTimesScalar;
887 }
888 } else if (left->isMatrix() && right->isMatrix()) {
889 op = EOpMatrixTimesMatrix;
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 op = EOpVectorTimesScalar;
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000895 setType(TType(basicType, higherPrecision, EvqTemporary, size, false));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000896 }
897 } else {
898 infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
899 return false;
900 }
901 break;
902 case EOpMulAssign:
903 if (!left->isMatrix() && right->isMatrix()) {
904 if (left->isVector())
905 op = EOpVectorTimesMatrixAssign;
906 else {
907 return false;
908 }
909 } else if (left->isMatrix() && !right->isMatrix()) {
910 if (right->isVector()) {
911 return false;
912 } else {
913 op = EOpMatrixTimesScalarAssign;
914 }
915 } else if (left->isMatrix() && right->isMatrix()) {
916 op = EOpMatrixTimesMatrixAssign;
917 } else if (!left->isMatrix() && !right->isMatrix()) {
918 if (left->isVector() && right->isVector()) {
919 // leave as component product
920 } else if (left->isVector() || right->isVector()) {
921 if (! left->isVector())
922 return false;
923 op = EOpVectorTimesScalarAssign;
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000924 setType(TType(basicType, higherPrecision, EvqTemporary, size, false));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000925 }
926 } else {
927 infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
928 return false;
929 }
930 break;
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000931
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000932 case EOpAssign:
933 case EOpInitialize:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000934 case EOpAdd:
935 case EOpSub:
936 case EOpDiv:
937 case EOpAddAssign:
938 case EOpSubAssign:
939 case EOpDivAssign:
940 if (left->isMatrix() && right->isVector() ||
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000941 left->isVector() && right->isMatrix())
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000942 return false;
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000943 setType(TType(basicType, higherPrecision, EvqTemporary, size, left->isMatrix() || right->isMatrix()));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000944 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000945
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000946 case EOpEqual:
947 case EOpNotEqual:
948 case EOpLessThan:
949 case EOpGreaterThan:
950 case EOpLessThanEqual:
951 case EOpGreaterThanEqual:
952 if (left->isMatrix() && right->isVector() ||
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000953 left->isVector() && right->isMatrix())
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000954 return false;
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000955 setType(TType(EbtBool, EbpUndefined));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000956 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000957
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000958 default:
959 return false;
960 }
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000961
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000962 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000963}
964
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000965bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000966{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000967 TTypeList* fields = leftNodeType.getStruct();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000968
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000969 size_t structSize = fields->size();
970 int index = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000971
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000972 for (size_t j = 0; j < structSize; j++) {
973 int size = (*fields)[j].type->getObjectSize();
974 for (int i = 0; i < size; i++) {
975 if ((*fields)[j].type->getBasicType() == EbtStruct) {
976 if (!CompareStructure(*(*fields)[j].type, &rightUnionArray[index], &leftUnionArray[index]))
977 return false;
978 } else {
979 if (leftUnionArray[index] != rightUnionArray[index])
980 return false;
981 index++;
982 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000983
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000984 }
985 }
986 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000987}
988
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000989bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000990{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000991 if (leftNodeType.isArray()) {
992 TType typeWithoutArrayness = leftNodeType;
993 typeWithoutArrayness.clearArrayness();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000994
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000995 int arraySize = leftNodeType.getArraySize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000996
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000997 for (int i = 0; i < arraySize; ++i) {
998 int offset = typeWithoutArrayness.getObjectSize() * i;
999 if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset]))
1000 return false;
1001 }
1002 } else
1003 return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001004
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001005 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001006}
1007
1008//
1009// The fold functions see if an operation on a constant can be done in place,
1010// without generating run-time code.
1011//
1012// Returns the node to keep using, which may or may not be the node passed in.
1013//
1014
1015TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink)
1016{
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001017 ConstantUnion *unionArray = getUnionArrayPointer();
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001018 int objectSize = getType().getObjectSize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001019
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001020 if (constantNode) { // binary operations
1021 TIntermConstantUnion *node = constantNode->getAsConstantUnion();
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001022 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001023 TType returnType = getType();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001024
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001025 // for a case like float f = 1.2 + vec4(2,3,4,5);
1026 if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) {
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001027 rightUnionArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001028 for (int i = 0; i < objectSize; ++i)
1029 rightUnionArray[i] = *node->getUnionArrayPointer();
1030 returnType = getType();
1031 } else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) {
1032 // for a case like float f = vec4(2,3,4,5) + 1.2;
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001033 unionArray = new ConstantUnion[constantNode->getType().getObjectSize()];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001034 for (int i = 0; i < constantNode->getType().getObjectSize(); ++i)
1035 unionArray[i] = *getUnionArrayPointer();
1036 returnType = node->getType();
1037 objectSize = constantNode->getType().getObjectSize();
1038 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001039
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001040 ConstantUnion* tempConstArray = 0;
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001041 TIntermConstantUnion *tempNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001042
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001043 bool boolNodeFlag = false;
1044 switch(op) {
1045 case EOpAdd:
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001046 tempConstArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001047 {// support MSVC++6.0
1048 for (int i = 0; i < objectSize; i++)
1049 tempConstArray[i] = unionArray[i] + rightUnionArray[i];
1050 }
1051 break;
1052 case EOpSub:
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001053 tempConstArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001054 {// support MSVC++6.0
1055 for (int i = 0; i < objectSize; i++)
1056 tempConstArray[i] = unionArray[i] - rightUnionArray[i];
1057 }
1058 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001059
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001060 case EOpMul:
1061 case EOpVectorTimesScalar:
1062 case EOpMatrixTimesScalar:
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001063 tempConstArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001064 {// support MSVC++6.0
1065 for (int i = 0; i < objectSize; i++)
1066 tempConstArray[i] = unionArray[i] * rightUnionArray[i];
1067 }
1068 break;
1069 case EOpMatrixTimesMatrix:
1070 if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat) {
1071 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
1072 return 0;
1073 }
1074 {// support MSVC++6.0
1075 int size = getNominalSize();
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001076 tempConstArray = new ConstantUnion[size*size];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001077 for (int row = 0; row < size; row++) {
1078 for (int column = 0; column < size; column++) {
1079 tempConstArray[size * column + row].setFConst(0.0f);
1080 for (int i = 0; i < size; i++) {
1081 tempConstArray[size * column + row].setFConst(tempConstArray[size * column + row].getFConst() + unionArray[i * size + row].getFConst() * (rightUnionArray[column * size + i].getFConst()));
1082 }
1083 }
1084 }
1085 }
1086 break;
1087 case EOpDiv:
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001088 tempConstArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001089 {// support MSVC++6.0
1090 for (int i = 0; i < objectSize; i++) {
1091 switch (getType().getBasicType()) {
1092 case EbtFloat:
1093 if (rightUnionArray[i] == 0.0f) {
1094 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1095 tempConstArray[i].setFConst(FLT_MAX);
1096 } else
1097 tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst());
1098 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001099
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001100 case EbtInt:
1101 if (rightUnionArray[i] == 0) {
1102 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1103 tempConstArray[i].setIConst(INT_MAX);
1104 } else
1105 tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst());
1106 break;
1107 default:
1108 infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"/\"", getLine());
1109 return 0;
1110 }
1111 }
1112 }
1113 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001114
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001115 case EOpMatrixTimesVector:
1116 if (node->getBasicType() != EbtFloat) {
1117 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix times vector", getLine());
1118 return 0;
1119 }
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001120 tempConstArray = new ConstantUnion[getNominalSize()];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001121
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001122 {// support MSVC++6.0
1123 for (int size = getNominalSize(), i = 0; i < size; i++) {
1124 tempConstArray[i].setFConst(0.0f);
1125 for (int j = 0; j < size; j++) {
1126 tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j*size + i].getFConst()) * rightUnionArray[j].getFConst()));
1127 }
1128 }
1129 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001130
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001131 tempNode = new TIntermConstantUnion(tempConstArray, node->getType());
1132 tempNode->setLine(getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001133
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001134 return tempNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001135
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001136 case EOpVectorTimesMatrix:
1137 if (getType().getBasicType() != EbtFloat) {
1138 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for vector times matrix", getLine());
1139 return 0;
1140 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001141
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001142 tempConstArray = new ConstantUnion[getNominalSize()];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001143 {// support MSVC++6.0
1144 for (int size = getNominalSize(), i = 0; i < size; i++) {
1145 tempConstArray[i].setFConst(0.0f);
1146 for (int j = 0; j < size; j++) {
1147 tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j].getFConst()) * rightUnionArray[i*size + j].getFConst()));
1148 }
1149 }
1150 }
1151 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001152
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001153 case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001154 tempConstArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001155 {// support MSVC++6.0
1156 for (int i = 0; i < objectSize; i++)
1157 tempConstArray[i] = unionArray[i] && rightUnionArray[i];
1158 }
1159 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001160
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001161 case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001162 tempConstArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001163 {// support MSVC++6.0
1164 for (int i = 0; i < objectSize; i++)
1165 tempConstArray[i] = unionArray[i] || rightUnionArray[i];
1166 }
1167 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001168
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001169 case EOpLogicalXor:
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001170 tempConstArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001171 {// support MSVC++6.0
1172 for (int i = 0; i < objectSize; i++)
1173 switch (getType().getBasicType()) {
1174 case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break;
1175 default: assert(false && "Default missing");
1176 }
1177 }
1178 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001179
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001180 case EOpLessThan:
1181 assert(objectSize == 1);
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001182 tempConstArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001183 tempConstArray->setBConst(*unionArray < *rightUnionArray);
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001184 returnType = TType(EbtBool, EbpUndefined, EvqConst);
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001185 break;
1186 case EOpGreaterThan:
1187 assert(objectSize == 1);
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001188 tempConstArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001189 tempConstArray->setBConst(*unionArray > *rightUnionArray);
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001190 returnType = TType(EbtBool, EbpUndefined, EvqConst);
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001191 break;
1192 case EOpLessThanEqual:
1193 {
1194 assert(objectSize == 1);
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001195 ConstantUnion constant;
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001196 constant.setBConst(*unionArray > *rightUnionArray);
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001197 tempConstArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001198 tempConstArray->setBConst(!constant.getBConst());
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001199 returnType = TType(EbtBool, EbpUndefined, EvqConst);
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001200 break;
1201 }
1202 case EOpGreaterThanEqual:
1203 {
1204 assert(objectSize == 1);
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001205 ConstantUnion constant;
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001206 constant.setBConst(*unionArray < *rightUnionArray);
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001207 tempConstArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001208 tempConstArray->setBConst(!constant.getBConst());
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001209 returnType = TType(EbtBool, EbpUndefined, EvqConst);
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001210 break;
1211 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001212
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001213 case EOpEqual:
1214 if (getType().getBasicType() == EbtStruct) {
1215 if (!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
1216 boolNodeFlag = true;
1217 } else {
1218 for (int i = 0; i < objectSize; i++) {
1219 if (unionArray[i] != rightUnionArray[i]) {
1220 boolNodeFlag = true;
1221 break; // break out of for loop
1222 }
1223 }
1224 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001225
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001226 tempConstArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001227 if (!boolNodeFlag) {
1228 tempConstArray->setBConst(true);
1229 }
1230 else {
1231 tempConstArray->setBConst(false);
1232 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001233
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001234 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001235 tempNode->setLine(getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001236
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001237 return tempNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001238
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001239 case EOpNotEqual:
1240 if (getType().getBasicType() == EbtStruct) {
1241 if (CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
1242 boolNodeFlag = true;
1243 } else {
1244 for (int i = 0; i < objectSize; i++) {
1245 if (unionArray[i] == rightUnionArray[i]) {
1246 boolNodeFlag = true;
1247 break; // break out of for loop
1248 }
1249 }
1250 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001251
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001252 tempConstArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001253 if (!boolNodeFlag) {
1254 tempConstArray->setBConst(true);
1255 }
1256 else {
1257 tempConstArray->setBConst(false);
1258 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001259
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001260 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001261 tempNode->setLine(getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001262
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001263 return tempNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001264
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001265 default:
1266 infoSink.info.message(EPrefixInternalError, "Invalid operator for constant folding", getLine());
1267 return 0;
1268 }
1269 tempNode = new TIntermConstantUnion(tempConstArray, returnType);
1270 tempNode->setLine(getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001271
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001272 return tempNode;
1273 } else {
1274 //
1275 // Do unary operations
1276 //
1277 TIntermConstantUnion *newNode = 0;
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001278 ConstantUnion* tempConstArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001279 for (int i = 0; i < objectSize; i++) {
1280 switch(op) {
1281 case EOpNegative:
1282 switch (getType().getBasicType()) {
1283 case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break;
1284 case EbtInt: tempConstArray[i].setIConst(-unionArray[i].getIConst()); break;
1285 default:
1286 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1287 return 0;
1288 }
1289 break;
1290 case EOpLogicalNot: // this code is written for possible future use, will not get executed currently
1291 switch (getType().getBasicType()) {
1292 case EbtBool: tempConstArray[i].setBConst(!unionArray[i].getBConst()); break;
1293 default:
1294 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1295 return 0;
1296 }
1297 break;
1298 default:
1299 return 0;
1300 }
1301 }
1302 newNode = new TIntermConstantUnion(tempConstArray, getType());
1303 newNode->setLine(getLine());
1304 return newNode;
1305 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001306
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001307 return this;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001308}
1309
1310TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node)
1311{
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001312 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001313 int size = node->getType().getObjectSize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001314
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001315 ConstantUnion *leftUnionArray = new ConstantUnion[size];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001316
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001317 for (int i=0; i < size; i++) {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001318
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001319 switch (promoteTo) {
1320 case EbtFloat:
1321 switch (node->getType().getBasicType()) {
1322 case EbtInt:
1323 leftUnionArray[i].setFConst(static_cast<float>(rightUnionArray[i].getIConst()));
1324 break;
1325 case EbtBool:
1326 leftUnionArray[i].setFConst(static_cast<float>(rightUnionArray[i].getBConst()));
1327 break;
1328 case EbtFloat:
1329 leftUnionArray[i] = rightUnionArray[i];
1330 break;
1331 default:
1332 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1333 return 0;
1334 }
1335 break;
1336 case EbtInt:
1337 switch (node->getType().getBasicType()) {
1338 case EbtInt:
1339 leftUnionArray[i] = rightUnionArray[i];
1340 break;
1341 case EbtBool:
1342 leftUnionArray[i].setIConst(static_cast<int>(rightUnionArray[i].getBConst()));
1343 break;
1344 case EbtFloat:
1345 leftUnionArray[i].setIConst(static_cast<int>(rightUnionArray[i].getFConst()));
1346 break;
1347 default:
1348 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1349 return 0;
1350 }
1351 break;
1352 case EbtBool:
1353 switch (node->getType().getBasicType()) {
1354 case EbtInt:
1355 leftUnionArray[i].setBConst(rightUnionArray[i].getIConst() != 0);
1356 break;
1357 case EbtBool:
1358 leftUnionArray[i] = rightUnionArray[i];
1359 break;
1360 case EbtFloat:
1361 leftUnionArray[i].setBConst(rightUnionArray[i].getFConst() != 0.0f);
1362 break;
1363 default:
1364 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1365 return 0;
1366 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001367
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001368 break;
1369 default:
1370 infoSink.info.message(EPrefixInternalError, "Incorrect data type found", node->getLine());
1371 return 0;
1372 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001373
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001374 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001375
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001376 const TType& t = node->getType();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001377
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001378 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 +00001379}
1380
1381void TIntermAggregate::addToPragmaTable(const TPragmaTable& pTable)
1382{
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001383 assert(!pragmaTable);
1384 pragmaTable = new TPragmaTable();
1385 *pragmaTable = pTable;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001386}