blob: f1044b4157b8278276796a53cffa0da5ae1b1149 [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>
12
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000013#include "compiler/localintermediate.h"
14#include "compiler/QualifierAlive.h"
15#include "compiler/RemoveTree.h"
16
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +000017bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000018
daniel@transgaming.coma5d76232010-05-17 09:58:47 +000019TPrecision GetHighestPrecision( TPrecision left, TPrecision right, TInfoSink& infoSink ){
20 TPrecision highest = left > right ? left : right;
21
22 if (highest == EbpUndefined) {
23 infoSink.info.message(EPrefixInternalError, "Unknown or invalid precision for operands", 0);
24 }
25
26 return highest;
27}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000028////////////////////////////////////////////////////////////////////////////
29//
30// First set of functions are to help build the intermediate representation.
31// These functions are not member functions of the nodes.
32// They are called from parser productions.
33//
34/////////////////////////////////////////////////////////////////////////////
35
36//
37// Add a terminal node for an identifier in an expression.
38//
39// Returns the added node.
40//
41TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, TSourceLoc line)
42{
alokp@chromium.org2cf17712010-03-30 20:33:18 +000043 TIntermSymbol* node = new TIntermSymbol(id, name, type);
44 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000045
alokp@chromium.org2cf17712010-03-30 20:33:18 +000046 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000047}
48
49//
50// Connect two nodes with a new parent that does a binary operation on the nodes.
51//
52// Returns the added node.
53//
54TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line, TSymbolTable& symbolTable)
55{
alokp@chromium.org2cf17712010-03-30 20:33:18 +000056 switch (op) {
57 case EOpLessThan:
58 case EOpGreaterThan:
59 case EOpLessThanEqual:
60 case EOpGreaterThanEqual:
61 if (left->getType().isMatrix() || left->getType().isArray() || left->getType().isVector() || left->getType().getBasicType() == EbtStruct) {
62 return 0;
63 }
64 break;
65 case EOpLogicalOr:
66 case EOpLogicalXor:
67 case EOpLogicalAnd:
68 if (left->getType().getBasicType() != EbtBool || left->getType().isMatrix() || left->getType().isArray() || left->getType().isVector()) {
69 return 0;
70 }
71 break;
72 case EOpAdd:
73 case EOpSub:
74 case EOpDiv:
75 case EOpMul:
76 if (left->getType().getBasicType() == EbtStruct || left->getType().getBasicType() == EbtBool)
77 return 0;
78 default: break;
79 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000080
alokp@chromium.org2cf17712010-03-30 20:33:18 +000081 //
82 // First try converting the children to compatible types.
83 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000084
alokp@chromium.org2cf17712010-03-30 20:33:18 +000085 if (!(left->getType().getStruct() && right->getType().getStruct())) {
86 TIntermTyped* child = addConversion(op, left->getType(), right);
87 if (child)
88 right = child;
89 else {
90 child = addConversion(op, right->getType(), left);
91 if (child)
92 left = child;
93 else
94 return 0;
95 }
96 } else {
97 if (left->getType() != right->getType())
98 return 0;
99 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000100
101
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);
113 if (! node->promote(infoSink))
114 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000115
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000116 TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
117 TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000118
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000119 if (leftTempConstant)
120 leftTempConstant = left->getAsConstantUnion();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000121
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000122 if (rightTempConstant)
123 rightTempConstant = right->getAsConstantUnion();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000124
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000125 //
126 // See if we can fold constants.
127 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000128
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000129 TIntermTyped* typedReturnNode = 0;
130 if ( leftTempConstant && rightTempConstant) {
131 typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000132
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000133 if (typedReturnNode)
134 return typedReturnNode;
135 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000136
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000137 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000138}
139
140//
141// Connect two nodes through an assignment.
142//
143// Returns the added node.
144//
145TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line)
146{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000147 //
148 // Like adding binary math, except the conversion can only go
149 // from right to left.
150 //
151 TIntermBinary* node = new TIntermBinary(op);
152 if (line == 0)
153 line = left->getLine();
154 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000155
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000156 TIntermTyped* child = addConversion(op, left->getType(), right);
157 if (child == 0)
158 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000159
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000160 node->setLeft(left);
161 node->setRight(child);
162 if (! node->promote(infoSink))
163 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000164
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000165 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000166}
167
168//
169// Connect two nodes through an index operator, where the left node is the base
170// of an array or struct, and the right node is a direct or indirect offset.
171//
172// Returns the added node.
173// The caller should set the type of the returned node.
174//
175TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc line)
176{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000177 TIntermBinary* node = new TIntermBinary(op);
178 if (line == 0)
179 line = index->getLine();
180 node->setLine(line);
181 node->setLeft(base);
182 node->setRight(index);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000183
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000184 // caller should set the type
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000185
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000186 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000187}
188
189//
190// Add one node as the parent of another that it operates on.
191//
192// Returns the added node.
193//
194TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, TSourceLoc line, TSymbolTable& symbolTable)
195{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000196 TIntermUnary* node;
197 TIntermTyped* child = childNode->getAsTyped();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000198
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000199 if (child == 0) {
200 infoSink.info.message(EPrefixInternalError, "Bad type in AddUnaryMath", line);
201 return 0;
202 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000203
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000204 switch (op) {
205 case EOpLogicalNot:
206 if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) {
207 return 0;
208 }
209 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000210
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000211 case EOpPostIncrement:
212 case EOpPreIncrement:
213 case EOpPostDecrement:
214 case EOpPreDecrement:
215 case EOpNegative:
216 if (child->getType().getBasicType() == EbtStruct || child->getType().isArray())
217 return 0;
218 default: break;
219 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000220
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000221 //
222 // Do we need to promote the operand?
223 //
224 // Note: Implicit promotions were removed from the language.
225 //
226 TBasicType newType = EbtVoid;
227 switch (op) {
228 case EOpConstructInt: newType = EbtInt; break;
229 case EOpConstructBool: newType = EbtBool; break;
230 case EOpConstructFloat: newType = EbtFloat; break;
231 default: break;
232 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000233
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000234 if (newType != EbtVoid) {
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000235 child = addConversion(op, TType(newType, child->getPrecision(), EvqTemporary,
236 child->getNominalSize(),
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000237 child->isMatrix(),
238 child->isArray()),
239 child);
240 if (child == 0)
241 return 0;
242 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000243
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000244 //
245 // For constructors, we are now done, it's all in the conversion.
246 //
247 switch (op) {
248 case EOpConstructInt:
249 case EOpConstructBool:
250 case EOpConstructFloat:
251 return child;
252 default: break;
253 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000254
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000255 TIntermConstantUnion *childTempConstant = 0;
256 if (child->getAsConstantUnion())
257 childTempConstant = child->getAsConstantUnion();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000258
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000259 //
260 // Make a new node for the operator.
261 //
262 node = new TIntermUnary(op);
263 if (line == 0)
264 line = child->getLine();
265 node->setLine(line);
266 node->setOperand(child);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000267
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000268 if (! node->promote(infoSink))
269 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000270
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000271 if (childTempConstant) {
272 TIntermTyped* newChild = childTempConstant->fold(op, 0, infoSink);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000273
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000274 if (newChild)
275 return newChild;
276 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000277
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000278 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000279}
280
281//
282// This is the safe way to change the operator on an aggregate, as it
283// does lots of error checking and fixing. Especially for establishing
284// a function call's operation on it's set of parameters. Sequences
285// of instructions are also aggregates, but they just direnctly set
286// their operator to EOpSequence.
287//
288// Returns an aggregate node, which could be the one passed in if
289// it was already an aggregate.
290//
291TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, TSourceLoc line)
292{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000293 TIntermAggregate* aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000294
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000295 //
296 // Make sure we have an aggregate. If not turn it into one.
297 //
298 if (node) {
299 aggNode = node->getAsAggregate();
300 if (aggNode == 0 || aggNode->getOp() != EOpNull) {
301 //
302 // Make an aggregate containing this node.
303 //
304 aggNode = new TIntermAggregate();
305 aggNode->getSequence().push_back(node);
306 if (line == 0)
307 line = node->getLine();
308 }
309 } else
310 aggNode = new TIntermAggregate();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000311
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000312 //
313 // Set the operator.
314 //
315 aggNode->setOperator(op);
316 if (line != 0)
317 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000318
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000319 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000320}
321
322//
323// Convert one type to another.
324//
325// Returns the node representing the conversion, which could be the same
326// node passed in if no conversion was needed.
327//
328// Return 0 if a conversion can't be done.
329//
330TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TIntermTyped* node)
331{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000332 //
333 // Does the base type allow operation?
334 //
335 switch (node->getBasicType()) {
336 case EbtVoid:
337 case EbtSampler2D:
338 case EbtSamplerCube:
339 return 0;
340 default: break;
341 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000342
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000343 //
344 // Otherwise, if types are identical, no problem
345 //
346 if (type == node->getType())
347 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000348
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000349 //
350 // If one's a structure, then no conversions.
351 //
352 if (type.getStruct() || node->getType().getStruct())
353 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000354
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000355 //
356 // If one's an array, then no conversions.
357 //
358 if (type.isArray() || node->getType().isArray())
359 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000360
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000361 TBasicType promoteTo;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000362
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000363 switch (op) {
364 //
365 // Explicit conversions
366 //
367 case EOpConstructBool:
368 promoteTo = EbtBool;
369 break;
370 case EOpConstructFloat:
371 promoteTo = EbtFloat;
372 break;
373 case EOpConstructInt:
374 promoteTo = EbtInt;
375 break;
376 default:
377 //
378 // implicit conversions were removed from the language.
379 //
380 if (type.getBasicType() != node->getType().getBasicType())
381 return 0;
382 //
383 // Size and structure could still differ, but that's
384 // handled by operator promotion.
385 //
386 return node;
387 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000388
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000389 if (node->getAsConstantUnion()) {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000390
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000391 return (promoteConstantUnion(promoteTo, node->getAsConstantUnion()));
392 } else {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000393
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000394 //
395 // Add a new newNode for the conversion.
396 //
397 TIntermUnary* newNode = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000398
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000399 TOperator newOp = EOpNull;
400 switch (promoteTo) {
401 case EbtFloat:
402 switch (node->getBasicType()) {
403 case EbtInt: newOp = EOpConvIntToFloat; break;
404 case EbtBool: newOp = EOpConvBoolToFloat; break;
405 default:
406 infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
407 return 0;
408 }
409 break;
410 case EbtBool:
411 switch (node->getBasicType()) {
412 case EbtInt: newOp = EOpConvIntToBool; break;
413 case EbtFloat: newOp = EOpConvFloatToBool; break;
414 default:
415 infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
416 return 0;
417 }
418 break;
419 case EbtInt:
420 switch (node->getBasicType()) {
421 case EbtBool: newOp = EOpConvBoolToInt; break;
422 case EbtFloat: newOp = EOpConvFloatToInt; break;
423 default:
424 infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
425 return 0;
426 }
427 break;
428 default:
429 infoSink.info.message(EPrefixInternalError, "Bad promotion type", node->getLine());
430 return 0;
431 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000432
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000433 TType type(promoteTo, node->getPrecision(), EvqTemporary, node->getNominalSize(), node->isMatrix(), node->isArray());
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000434 newNode = new TIntermUnary(newOp, type);
435 newNode->setLine(node->getLine());
436 newNode->setOperand(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000437
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000438 return newNode;
439 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000440}
441
442//
443// Safe way to combine two nodes into an aggregate. Works with null pointers,
444// a node that's not a aggregate yet, etc.
445//
446// Returns the resulting aggregate, unless 0 was passed in for
447// both existing nodes.
448//
449TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, TSourceLoc line)
450{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000451 if (left == 0 && right == 0)
452 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000453
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000454 TIntermAggregate* aggNode = 0;
455 if (left)
456 aggNode = left->getAsAggregate();
457 if (!aggNode || aggNode->getOp() != EOpNull) {
458 aggNode = new TIntermAggregate;
459 if (left)
460 aggNode->getSequence().push_back(left);
461 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000462
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000463 if (right)
464 aggNode->getSequence().push_back(right);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000465
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000466 if (line != 0)
467 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000468
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000469 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000470}
471
472//
473// Turn an existing node into an aggregate.
474//
475// Returns an aggregate, unless 0 was passed in for the existing node.
476//
477TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, TSourceLoc line)
478{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000479 if (node == 0)
480 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000481
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000482 TIntermAggregate* aggNode = new TIntermAggregate;
483 aggNode->getSequence().push_back(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000484
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000485 if (line != 0)
486 aggNode->setLine(line);
487 else
488 aggNode->setLine(node->getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000489
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000490 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000491}
492
493//
494// For "if" test nodes. There are three children; a condition,
495// a true path, and a false path. The two paths are in the
496// nodePair.
497//
498// Returns the selection node created.
499//
500TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, TSourceLoc line)
501{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000502 //
503 // For compile time constant selections, prune the code and
504 // test now.
505 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000506
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000507 if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion()) {
508 if (cond->getAsTyped()->getAsConstantUnion()->getUnionArrayPointer()->getBConst())
509 return nodePair.node1;
510 else
511 return nodePair.node2;
512 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000513
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000514 TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2);
515 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000516
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000517 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000518}
519
520
521TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc line)
522{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000523 if (left->getType().getQualifier() == EvqConst && right->getType().getQualifier() == EvqConst) {
524 return right;
525 } else {
526 TIntermTyped *commaAggregate = growAggregate(left, right, line);
527 commaAggregate->getAsAggregate()->setOperator(EOpComma);
528 commaAggregate->setType(right->getType());
529 commaAggregate->getTypePointer()->changeQualifier(EvqTemporary);
530 return commaAggregate;
531 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000532}
533
534//
535// For "?:" test nodes. There are three children; a condition,
536// a true path, and a false path. The two paths are specified
537// as separate parameters.
538//
539// Returns the selection node created, or 0 if one could not be.
540//
541TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, TSourceLoc line)
542{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000543 //
544 // Get compatible types.
545 //
546 TIntermTyped* child = addConversion(EOpSequence, trueBlock->getType(), falseBlock);
547 if (child)
548 falseBlock = child;
549 else {
550 child = addConversion(EOpSequence, falseBlock->getType(), trueBlock);
551 if (child)
552 trueBlock = child;
553 else
554 return 0;
555 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000556
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000557 //
558 // See if all the operands are constant, then fold it otherwise not.
559 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000560
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000561 if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) {
562 if (cond->getAsConstantUnion()->getUnionArrayPointer()->getBConst())
563 return trueBlock;
564 else
565 return falseBlock;
566 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000567
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000568 //
569 // Make a selection node.
570 //
571 TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
572 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000573
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000574 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000575}
576
577//
578// Constant terminal nodes. Has a union that contains bool, float or int constants
579//
580// Returns the constant union node created.
581//
582
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000583TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, TSourceLoc line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000584{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000585 TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t);
586 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000587
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000588 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000589}
590
591TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, TSourceLoc line)
592{
593
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000594 TIntermAggregate* node = new TIntermAggregate(EOpSequence);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000595
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000596 node->setLine(line);
597 TIntermConstantUnion* constIntNode;
598 TIntermSequence &sequenceVector = node->getSequence();
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000599 ConstantUnion* unionArray;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000600
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000601 for (int i = 0; i < fields.num; i++) {
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000602 unionArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000603 unionArray->setIConst(fields.offsets[i]);
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000604 constIntNode = addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), line);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000605 sequenceVector.push_back(constIntNode);
606 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000607
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000608 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000609}
610
611//
612// Create loop nodes.
613//
614TIntermNode* TIntermediate::addLoop(TIntermNode *init, TIntermNode* body, TIntermTyped* test, TIntermTyped* terminal, bool testFirst, TSourceLoc line)
615{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000616 TIntermNode* node = new TIntermLoop(init, body, test, terminal, testFirst);
617 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000618
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000619 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000620}
621
622//
623// Add branches.
624//
625TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TSourceLoc line)
626{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000627 return addBranch(branchOp, 0, line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000628}
629
630TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, TSourceLoc line)
631{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000632 TIntermBranch* node = new TIntermBranch(branchOp, expression);
633 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000634
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000635 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000636}
637
638//
639// This is to be executed once the final root is put on top by the parsing
640// process.
641//
642bool TIntermediate::postProcess(TIntermNode* root, EShLanguage language)
643{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000644 if (root == 0)
645 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000646
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000647 //
648 // First, finish off the top level sequence, if any
649 //
650 TIntermAggregate* aggRoot = root->getAsAggregate();
651 if (aggRoot && aggRoot->getOp() == EOpNull)
652 aggRoot->setOperator(EOpSequence);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000653
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000654 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000655}
656
657//
658// This deletes the tree.
659//
660void TIntermediate::remove(TIntermNode* root)
661{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000662 if (root)
663 RemoveAllTreeNodes(root);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000664}
665
666////////////////////////////////////////////////////////////////
667//
668// Member functions of the nodes used for building the tree.
669//
670////////////////////////////////////////////////////////////////
671
672//
673// Say whether or not an operation node changes the value of a variable.
674//
675// Returns true if state is modified.
676//
677bool TIntermOperator::modifiesState() const
678{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000679 switch (op) {
680 case EOpPostIncrement:
681 case EOpPostDecrement:
682 case EOpPreIncrement:
683 case EOpPreDecrement:
684 case EOpAssign:
685 case EOpAddAssign:
686 case EOpSubAssign:
687 case EOpMulAssign:
688 case EOpVectorTimesMatrixAssign:
689 case EOpVectorTimesScalarAssign:
690 case EOpMatrixTimesScalarAssign:
691 case EOpMatrixTimesMatrixAssign:
692 case EOpDivAssign:
693 return true;
694 default:
695 return false;
696 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000697}
698
699//
700// returns true if the operator is for one of the constructors
701//
702bool TIntermOperator::isConstructor() const
703{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000704 switch (op) {
705 case EOpConstructVec2:
706 case EOpConstructVec3:
707 case EOpConstructVec4:
708 case EOpConstructMat2:
709 case EOpConstructMat3:
710 case EOpConstructMat4:
711 case EOpConstructFloat:
712 case EOpConstructIVec2:
713 case EOpConstructIVec3:
714 case EOpConstructIVec4:
715 case EOpConstructInt:
716 case EOpConstructBVec2:
717 case EOpConstructBVec3:
718 case EOpConstructBVec4:
719 case EOpConstructBool:
720 case EOpConstructStruct:
721 return true;
722 default:
723 return false;
724 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000725}
726//
727// Make sure the type of a unary operator is appropriate for its
728// combination of operation and operand type.
729//
730// Returns false in nothing makes sense.
731//
732bool TIntermUnary::promote(TInfoSink&)
733{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000734 switch (op) {
735 case EOpLogicalNot:
736 if (operand->getBasicType() != EbtBool)
737 return false;
738 break;
739 case EOpNegative:
740 case EOpPostIncrement:
741 case EOpPostDecrement:
742 case EOpPreIncrement:
743 case EOpPreDecrement:
744 if (operand->getBasicType() == EbtBool)
745 return false;
746 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000747
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000748 // operators for built-ins are already type checked against their prototype
749 case EOpAny:
750 case EOpAll:
751 case EOpVectorLogicalNot:
752 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000753
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000754 default:
755 if (operand->getBasicType() != EbtFloat)
756 return false;
757 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000758
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000759 setType(operand->getType());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000760
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000761 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000762}
763
764//
765// Establishes the type of the resultant operation, as well as
766// makes the operator the correct one for the operands.
767//
768// Returns false if operator can't work on operands.
769//
770bool TIntermBinary::promote(TInfoSink& infoSink)
771{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000772 int size = left->getNominalSize();
773 if (right->getNominalSize() > size)
774 size = right->getNominalSize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000775
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000776 TBasicType type = left->getBasicType();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000777
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000778 //
779 // Arrays have to be exact matches.
780 //
781 if ((left->isArray() || right->isArray()) && (left->getType() != right->getType()))
782 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000783
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000784 //
785 // Base assumption: just make the type the same as the left
786 // operand. Then only deviations from this need be coded.
787 //
daniel@transgaming.comfe565152010-04-10 05:29:07 +0000788 setType(left->getType());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000789
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000790 TPrecision highestPrecision = GetHighestPrecision(left->getPrecision(), right->getPrecision(), infoSink);
791 getTypePointer()->changePrecision(highestPrecision);
792
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000793 //
794 // Array operations.
795 //
796 if (left->isArray()) {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000797
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000798 switch (op) {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000799
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000800 //
801 // Promote to conditional
802 //
803 case EOpEqual:
804 case EOpNotEqual:
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000805 setType(TType(EbtBool, EbpUndefined));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000806 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000807
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000808 //
809 // Set array information.
810 //
811 case EOpAssign:
812 case EOpInitialize:
813 getTypePointer()->setArraySize(left->getType().getArraySize());
814 getTypePointer()->setArrayInformationType(left->getType().getArrayInformationType());
815 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000816
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000817 default:
818 return false;
819 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000820
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000821 return true;
822 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000823
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000824 //
825 // All scalars. Code after this test assumes this case is removed!
826 //
827 if (size == 1) {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000828
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000829 switch (op) {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000830
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000831 //
832 // Promote to conditional
833 //
834 case EOpEqual:
835 case EOpNotEqual:
836 case EOpLessThan:
837 case EOpGreaterThan:
838 case EOpLessThanEqual:
839 case EOpGreaterThanEqual:
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000840 setType(TType(EbtBool, EbpUndefined));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000841 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000842
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000843 //
844 // And and Or operate on conditionals
845 //
846 case EOpLogicalAnd:
847 case EOpLogicalOr:
848 if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool)
849 return false;
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000850 setType(TType(EbtBool, EbpUndefined));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000851 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000852
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000853 //
854 // Everything else should have matching types
855 //
856 default:
857 if (left->getBasicType() != right->getBasicType() ||
858 left->isMatrix() != right->isMatrix())
859 return false;
860 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000861
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000862 return true;
863 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000864
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000865 //
866 // Are the sizes compatible?
867 //
868 if ( left->getNominalSize() != size && left->getNominalSize() != 1 ||
869 right->getNominalSize() != size && right->getNominalSize() != 1)
870 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000871
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000872 //
873 // Can these two operands be combined?
874 //
875 switch (op) {
876 case EOpMul:
877 if (!left->isMatrix() && right->isMatrix()) {
878 if (left->isVector())
879 op = EOpVectorTimesMatrix;
880 else {
881 op = EOpMatrixTimesScalar;
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000882 setType(TType(type, highestPrecision, EvqTemporary, size, true));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000883 }
884 } else if (left->isMatrix() && !right->isMatrix()) {
885 if (right->isVector()) {
886 op = EOpMatrixTimesVector;
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000887 setType(TType(type, highestPrecision, EvqTemporary, size, false));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000888 } else {
889 op = EOpMatrixTimesScalar;
890 }
891 } else if (left->isMatrix() && right->isMatrix()) {
892 op = EOpMatrixTimesMatrix;
893 } else if (!left->isMatrix() && !right->isMatrix()) {
894 if (left->isVector() && right->isVector()) {
895 // leave as component product
896 } else if (left->isVector() || right->isVector()) {
897 op = EOpVectorTimesScalar;
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000898 setType(TType(type, highestPrecision, EvqTemporary, size, false));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000899 }
900 } else {
901 infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
902 return false;
903 }
904 break;
905 case EOpMulAssign:
906 if (!left->isMatrix() && right->isMatrix()) {
907 if (left->isVector())
908 op = EOpVectorTimesMatrixAssign;
909 else {
910 return false;
911 }
912 } else if (left->isMatrix() && !right->isMatrix()) {
913 if (right->isVector()) {
914 return false;
915 } else {
916 op = EOpMatrixTimesScalarAssign;
917 }
918 } else if (left->isMatrix() && right->isMatrix()) {
919 op = EOpMatrixTimesMatrixAssign;
920 } else if (!left->isMatrix() && !right->isMatrix()) {
921 if (left->isVector() && right->isVector()) {
922 // leave as component product
923 } else if (left->isVector() || right->isVector()) {
924 if (! left->isVector())
925 return false;
926 op = EOpVectorTimesScalarAssign;
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000927 setType(TType(type, highestPrecision, EvqTemporary, size, false));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000928 }
929 } else {
930 infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
931 return false;
932 }
933 break;
934 case EOpAssign:
935 case EOpInitialize:
936 if (left->getNominalSize() != right->getNominalSize())
937 return false;
938 // fall through
939 case EOpAdd:
940 case EOpSub:
941 case EOpDiv:
942 case EOpAddAssign:
943 case EOpSubAssign:
944 case EOpDivAssign:
945 if (left->isMatrix() && right->isVector() ||
946 left->isVector() && right->isMatrix() ||
947 left->getBasicType() != right->getBasicType())
948 return false;
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000949 setType(TType(type, highestPrecision, EvqTemporary, size, left->isMatrix() || right->isMatrix()));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000950 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000951
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000952 case EOpEqual:
953 case EOpNotEqual:
954 case EOpLessThan:
955 case EOpGreaterThan:
956 case EOpLessThanEqual:
957 case EOpGreaterThanEqual:
958 if (left->isMatrix() && right->isVector() ||
959 left->isVector() && right->isMatrix() ||
960 left->getBasicType() != right->getBasicType())
961 return false;
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000962 setType(TType(EbtBool, EbpUndefined));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000963 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000964
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000965 default:
966 return false;
967 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000968
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000969 //
970 // One more check for assignment. The Resulting type has to match the left operand.
971 //
972 switch (op) {
973 case EOpAssign:
974 case EOpInitialize:
975 case EOpAddAssign:
976 case EOpSubAssign:
977 case EOpMulAssign:
978 case EOpDivAssign:
979 if (getType() != left->getType())
980 return false;
981 break;
982 default:
983 break;
984 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000985
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000986 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000987}
988
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000989bool CompareStruct(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 TTypeList* fields = leftNodeType.getStruct();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000992
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000993 size_t structSize = fields->size();
994 int index = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000995
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000996 for (size_t j = 0; j < structSize; j++) {
997 int size = (*fields)[j].type->getObjectSize();
998 for (int i = 0; i < size; i++) {
999 if ((*fields)[j].type->getBasicType() == EbtStruct) {
1000 if (!CompareStructure(*(*fields)[j].type, &rightUnionArray[index], &leftUnionArray[index]))
1001 return false;
1002 } else {
1003 if (leftUnionArray[index] != rightUnionArray[index])
1004 return false;
1005 index++;
1006 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001007
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001008 }
1009 }
1010 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001011}
1012
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001013bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001014{
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001015 if (leftNodeType.isArray()) {
1016 TType typeWithoutArrayness = leftNodeType;
1017 typeWithoutArrayness.clearArrayness();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001018
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001019 int arraySize = leftNodeType.getArraySize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001020
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001021 for (int i = 0; i < arraySize; ++i) {
1022 int offset = typeWithoutArrayness.getObjectSize() * i;
1023 if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset]))
1024 return false;
1025 }
1026 } else
1027 return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001028
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001029 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001030}
1031
1032//
1033// The fold functions see if an operation on a constant can be done in place,
1034// without generating run-time code.
1035//
1036// Returns the node to keep using, which may or may not be the node passed in.
1037//
1038
1039TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink)
1040{
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001041 ConstantUnion *unionArray = getUnionArrayPointer();
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001042 int objectSize = getType().getObjectSize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001043
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001044 if (constantNode) { // binary operations
1045 TIntermConstantUnion *node = constantNode->getAsConstantUnion();
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001046 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001047 TType returnType = getType();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001048
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001049 // for a case like float f = 1.2 + vec4(2,3,4,5);
1050 if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) {
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001051 rightUnionArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001052 for (int i = 0; i < objectSize; ++i)
1053 rightUnionArray[i] = *node->getUnionArrayPointer();
1054 returnType = getType();
1055 } else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) {
1056 // for a case like float f = vec4(2,3,4,5) + 1.2;
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001057 unionArray = new ConstantUnion[constantNode->getType().getObjectSize()];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001058 for (int i = 0; i < constantNode->getType().getObjectSize(); ++i)
1059 unionArray[i] = *getUnionArrayPointer();
1060 returnType = node->getType();
1061 objectSize = constantNode->getType().getObjectSize();
1062 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001063
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001064 ConstantUnion* tempConstArray = 0;
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001065 TIntermConstantUnion *tempNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001066
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001067 bool boolNodeFlag = false;
1068 switch(op) {
1069 case EOpAdd:
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001070 tempConstArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001071 {// support MSVC++6.0
1072 for (int i = 0; i < objectSize; i++)
1073 tempConstArray[i] = unionArray[i] + rightUnionArray[i];
1074 }
1075 break;
1076 case EOpSub:
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001077 tempConstArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001078 {// support MSVC++6.0
1079 for (int i = 0; i < objectSize; i++)
1080 tempConstArray[i] = unionArray[i] - rightUnionArray[i];
1081 }
1082 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001083
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001084 case EOpMul:
1085 case EOpVectorTimesScalar:
1086 case EOpMatrixTimesScalar:
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001087 tempConstArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001088 {// support MSVC++6.0
1089 for (int i = 0; i < objectSize; i++)
1090 tempConstArray[i] = unionArray[i] * rightUnionArray[i];
1091 }
1092 break;
1093 case EOpMatrixTimesMatrix:
1094 if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat) {
1095 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
1096 return 0;
1097 }
1098 {// support MSVC++6.0
1099 int size = getNominalSize();
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001100 tempConstArray = new ConstantUnion[size*size];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001101 for (int row = 0; row < size; row++) {
1102 for (int column = 0; column < size; column++) {
1103 tempConstArray[size * column + row].setFConst(0.0f);
1104 for (int i = 0; i < size; i++) {
1105 tempConstArray[size * column + row].setFConst(tempConstArray[size * column + row].getFConst() + unionArray[i * size + row].getFConst() * (rightUnionArray[column * size + i].getFConst()));
1106 }
1107 }
1108 }
1109 }
1110 break;
1111 case EOpDiv:
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001112 tempConstArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001113 {// support MSVC++6.0
1114 for (int i = 0; i < objectSize; i++) {
1115 switch (getType().getBasicType()) {
1116 case EbtFloat:
1117 if (rightUnionArray[i] == 0.0f) {
1118 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1119 tempConstArray[i].setFConst(FLT_MAX);
1120 } else
1121 tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst());
1122 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001123
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001124 case EbtInt:
1125 if (rightUnionArray[i] == 0) {
1126 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1127 tempConstArray[i].setIConst(INT_MAX);
1128 } else
1129 tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst());
1130 break;
1131 default:
1132 infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"/\"", getLine());
1133 return 0;
1134 }
1135 }
1136 }
1137 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001138
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001139 case EOpMatrixTimesVector:
1140 if (node->getBasicType() != EbtFloat) {
1141 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix times vector", getLine());
1142 return 0;
1143 }
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001144 tempConstArray = new ConstantUnion[getNominalSize()];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001145
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001146 {// support MSVC++6.0
1147 for (int size = getNominalSize(), i = 0; i < size; i++) {
1148 tempConstArray[i].setFConst(0.0f);
1149 for (int j = 0; j < size; j++) {
1150 tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j*size + i].getFConst()) * rightUnionArray[j].getFConst()));
1151 }
1152 }
1153 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001154
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001155 tempNode = new TIntermConstantUnion(tempConstArray, node->getType());
1156 tempNode->setLine(getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001157
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001158 return tempNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001159
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001160 case EOpVectorTimesMatrix:
1161 if (getType().getBasicType() != EbtFloat) {
1162 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for vector times matrix", getLine());
1163 return 0;
1164 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001165
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001166 tempConstArray = new ConstantUnion[getNominalSize()];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001167 {// support MSVC++6.0
1168 for (int size = getNominalSize(), i = 0; i < size; i++) {
1169 tempConstArray[i].setFConst(0.0f);
1170 for (int j = 0; j < size; j++) {
1171 tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j].getFConst()) * rightUnionArray[i*size + j].getFConst()));
1172 }
1173 }
1174 }
1175 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001176
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001177 case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001178 tempConstArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001179 {// support MSVC++6.0
1180 for (int i = 0; i < objectSize; i++)
1181 tempConstArray[i] = unionArray[i] && rightUnionArray[i];
1182 }
1183 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001184
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001185 case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001186 tempConstArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001187 {// support MSVC++6.0
1188 for (int i = 0; i < objectSize; i++)
1189 tempConstArray[i] = unionArray[i] || rightUnionArray[i];
1190 }
1191 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001192
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001193 case EOpLogicalXor:
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001194 tempConstArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001195 {// support MSVC++6.0
1196 for (int i = 0; i < objectSize; i++)
1197 switch (getType().getBasicType()) {
1198 case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break;
1199 default: assert(false && "Default missing");
1200 }
1201 }
1202 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001203
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001204 case EOpLessThan:
1205 assert(objectSize == 1);
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001206 tempConstArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001207 tempConstArray->setBConst(*unionArray < *rightUnionArray);
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001208 returnType = TType(EbtBool, EbpUndefined, EvqConst);
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001209 break;
1210 case EOpGreaterThan:
1211 assert(objectSize == 1);
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001212 tempConstArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001213 tempConstArray->setBConst(*unionArray > *rightUnionArray);
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001214 returnType = TType(EbtBool, EbpUndefined, EvqConst);
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001215 break;
1216 case EOpLessThanEqual:
1217 {
1218 assert(objectSize == 1);
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001219 ConstantUnion constant;
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001220 constant.setBConst(*unionArray > *rightUnionArray);
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001221 tempConstArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001222 tempConstArray->setBConst(!constant.getBConst());
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001223 returnType = TType(EbtBool, EbpUndefined, EvqConst);
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001224 break;
1225 }
1226 case EOpGreaterThanEqual:
1227 {
1228 assert(objectSize == 1);
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001229 ConstantUnion constant;
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001230 constant.setBConst(*unionArray < *rightUnionArray);
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001231 tempConstArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001232 tempConstArray->setBConst(!constant.getBConst());
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001233 returnType = TType(EbtBool, EbpUndefined, EvqConst);
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001234 break;
1235 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001236
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001237 case EOpEqual:
1238 if (getType().getBasicType() == EbtStruct) {
1239 if (!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
1240 boolNodeFlag = true;
1241 } else {
1242 for (int i = 0; i < objectSize; i++) {
1243 if (unionArray[i] != rightUnionArray[i]) {
1244 boolNodeFlag = true;
1245 break; // break out of for loop
1246 }
1247 }
1248 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001249
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001250 tempConstArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001251 if (!boolNodeFlag) {
1252 tempConstArray->setBConst(true);
1253 }
1254 else {
1255 tempConstArray->setBConst(false);
1256 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001257
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001258 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001259 tempNode->setLine(getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001260
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001261 return tempNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001262
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001263 case EOpNotEqual:
1264 if (getType().getBasicType() == EbtStruct) {
1265 if (CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
1266 boolNodeFlag = true;
1267 } else {
1268 for (int i = 0; i < objectSize; i++) {
1269 if (unionArray[i] == rightUnionArray[i]) {
1270 boolNodeFlag = true;
1271 break; // break out of for loop
1272 }
1273 }
1274 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001275
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001276 tempConstArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001277 if (!boolNodeFlag) {
1278 tempConstArray->setBConst(true);
1279 }
1280 else {
1281 tempConstArray->setBConst(false);
1282 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001283
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001284 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001285 tempNode->setLine(getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001286
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001287 return tempNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001288
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001289 default:
1290 infoSink.info.message(EPrefixInternalError, "Invalid operator for constant folding", getLine());
1291 return 0;
1292 }
1293 tempNode = new TIntermConstantUnion(tempConstArray, returnType);
1294 tempNode->setLine(getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001295
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001296 return tempNode;
1297 } else {
1298 //
1299 // Do unary operations
1300 //
1301 TIntermConstantUnion *newNode = 0;
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001302 ConstantUnion* tempConstArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001303 for (int i = 0; i < objectSize; i++) {
1304 switch(op) {
1305 case EOpNegative:
1306 switch (getType().getBasicType()) {
1307 case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break;
1308 case EbtInt: tempConstArray[i].setIConst(-unionArray[i].getIConst()); break;
1309 default:
1310 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1311 return 0;
1312 }
1313 break;
1314 case EOpLogicalNot: // this code is written for possible future use, will not get executed currently
1315 switch (getType().getBasicType()) {
1316 case EbtBool: tempConstArray[i].setBConst(!unionArray[i].getBConst()); break;
1317 default:
1318 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1319 return 0;
1320 }
1321 break;
1322 default:
1323 return 0;
1324 }
1325 }
1326 newNode = new TIntermConstantUnion(tempConstArray, getType());
1327 newNode->setLine(getLine());
1328 return newNode;
1329 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001330
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001331 return this;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001332}
1333
1334TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node)
1335{
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001336 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001337 int size = node->getType().getObjectSize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001338
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001339 ConstantUnion *leftUnionArray = new ConstantUnion[size];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001340
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001341 for (int i=0; i < size; i++) {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001342
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001343 switch (promoteTo) {
1344 case EbtFloat:
1345 switch (node->getType().getBasicType()) {
1346 case EbtInt:
1347 leftUnionArray[i].setFConst(static_cast<float>(rightUnionArray[i].getIConst()));
1348 break;
1349 case EbtBool:
1350 leftUnionArray[i].setFConst(static_cast<float>(rightUnionArray[i].getBConst()));
1351 break;
1352 case EbtFloat:
1353 leftUnionArray[i] = rightUnionArray[i];
1354 break;
1355 default:
1356 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1357 return 0;
1358 }
1359 break;
1360 case EbtInt:
1361 switch (node->getType().getBasicType()) {
1362 case EbtInt:
1363 leftUnionArray[i] = rightUnionArray[i];
1364 break;
1365 case EbtBool:
1366 leftUnionArray[i].setIConst(static_cast<int>(rightUnionArray[i].getBConst()));
1367 break;
1368 case EbtFloat:
1369 leftUnionArray[i].setIConst(static_cast<int>(rightUnionArray[i].getFConst()));
1370 break;
1371 default:
1372 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1373 return 0;
1374 }
1375 break;
1376 case EbtBool:
1377 switch (node->getType().getBasicType()) {
1378 case EbtInt:
1379 leftUnionArray[i].setBConst(rightUnionArray[i].getIConst() != 0);
1380 break;
1381 case EbtBool:
1382 leftUnionArray[i] = rightUnionArray[i];
1383 break;
1384 case EbtFloat:
1385 leftUnionArray[i].setBConst(rightUnionArray[i].getFConst() != 0.0f);
1386 break;
1387 default:
1388 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1389 return 0;
1390 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001391
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001392 break;
1393 default:
1394 infoSink.info.message(EPrefixInternalError, "Incorrect data type found", node->getLine());
1395 return 0;
1396 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001397
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001398 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001399
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001400 const TType& t = node->getType();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001401
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001402 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 +00001403}
1404
1405void TIntermAggregate::addToPragmaTable(const TPragmaTable& pTable)
1406{
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001407 assert(!pragmaTable);
1408 pragmaTable = new TPragmaTable();
1409 *pragmaTable = pTable;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001410}