blob: f65bc80adda2e0d5e486c11258d851a819e6440a [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>
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000013
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000014#include "compiler/localintermediate.h"
15#include "compiler/QualifierAlive.h"
16#include "compiler/RemoveTree.h"
17
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +000018bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000019
daniel@transgaming.com9abe9562010-06-24 13:02:21 +000020TPrecision GetHighestPrecision( TPrecision left, TPrecision right ){
21 return left > right ? left : right;
daniel@transgaming.coma5d76232010-05-17 09:58:47 +000022}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000023////////////////////////////////////////////////////////////////////////////
24//
25// First set of functions are to help build the intermediate representation.
26// These functions are not member functions of the nodes.
27// They are called from parser productions.
28//
29/////////////////////////////////////////////////////////////////////////////
30
31//
32// Add a terminal node for an identifier in an expression.
33//
34// Returns the added node.
35//
36TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, TSourceLoc line)
37{
alokp@chromium.org2cf17712010-03-30 20:33:18 +000038 TIntermSymbol* node = new TIntermSymbol(id, name, type);
39 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000040
alokp@chromium.org2cf17712010-03-30 20:33:18 +000041 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000042}
43
44//
45// Connect two nodes with a new parent that does a binary operation on the nodes.
46//
47// Returns the added node.
48//
49TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line, TSymbolTable& symbolTable)
50{
alokp@chromium.org2cf17712010-03-30 20:33:18 +000051 switch (op) {
52 case EOpLessThan:
53 case EOpGreaterThan:
54 case EOpLessThanEqual:
55 case EOpGreaterThanEqual:
56 if (left->getType().isMatrix() || left->getType().isArray() || left->getType().isVector() || left->getType().getBasicType() == EbtStruct) {
57 return 0;
58 }
59 break;
60 case EOpLogicalOr:
61 case EOpLogicalXor:
62 case EOpLogicalAnd:
63 if (left->getType().getBasicType() != EbtBool || left->getType().isMatrix() || left->getType().isArray() || left->getType().isVector()) {
64 return 0;
65 }
66 break;
67 case EOpAdd:
68 case EOpSub:
69 case EOpDiv:
70 case EOpMul:
71 if (left->getType().getBasicType() == EbtStruct || left->getType().getBasicType() == EbtBool)
72 return 0;
73 default: break;
74 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000075
alokp@chromium.org2cf17712010-03-30 20:33:18 +000076 //
77 // First try converting the children to compatible types.
78 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000079
alokp@chromium.org2cf17712010-03-30 20:33:18 +000080 if (!(left->getType().getStruct() && right->getType().getStruct())) {
81 TIntermTyped* child = addConversion(op, left->getType(), right);
82 if (child)
83 right = child;
84 else {
85 child = addConversion(op, right->getType(), left);
86 if (child)
87 left = child;
88 else
89 return 0;
90 }
91 } else {
92 if (left->getType() != right->getType())
93 return 0;
94 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000095
96
alokp@chromium.org2cf17712010-03-30 20:33:18 +000097 //
98 // Need a new node holding things together then. Make
99 // one and promote it to the right type.
100 //
101 TIntermBinary* node = new TIntermBinary(op);
102 if (line == 0)
103 line = right->getLine();
104 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000105
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000106 node->setLeft(left);
107 node->setRight(right);
108 if (! node->promote(infoSink))
109 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000110
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000111 TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
112 TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000113
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000114 if (leftTempConstant)
115 leftTempConstant = left->getAsConstantUnion();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000116
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000117 if (rightTempConstant)
118 rightTempConstant = right->getAsConstantUnion();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000119
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000120 //
121 // See if we can fold constants.
122 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000123
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000124 TIntermTyped* typedReturnNode = 0;
125 if ( leftTempConstant && rightTempConstant) {
126 typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000127
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000128 if (typedReturnNode)
129 return typedReturnNode;
130 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000131
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000132 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000133}
134
135//
136// Connect two nodes through an assignment.
137//
138// Returns the added node.
139//
140TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line)
141{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000142 //
143 // Like adding binary math, except the conversion can only go
144 // from right to left.
145 //
146 TIntermBinary* node = new TIntermBinary(op);
147 if (line == 0)
148 line = left->getLine();
149 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000150
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000151 TIntermTyped* child = addConversion(op, left->getType(), right);
152 if (child == 0)
153 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000154
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000155 node->setLeft(left);
156 node->setRight(child);
157 if (! node->promote(infoSink))
158 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000159
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000160 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000161}
162
163//
164// Connect two nodes through an index operator, where the left node is the base
165// of an array or struct, and the right node is a direct or indirect offset.
166//
167// Returns the added node.
168// The caller should set the type of the returned node.
169//
170TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc line)
171{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000172 TIntermBinary* node = new TIntermBinary(op);
173 if (line == 0)
174 line = index->getLine();
175 node->setLine(line);
176 node->setLeft(base);
177 node->setRight(index);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000178
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000179 // caller should set the type
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000180
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000181 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000182}
183
184//
185// Add one node as the parent of another that it operates on.
186//
187// Returns the added node.
188//
189TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, TSourceLoc line, TSymbolTable& symbolTable)
190{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000191 TIntermUnary* node;
192 TIntermTyped* child = childNode->getAsTyped();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000193
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000194 if (child == 0) {
195 infoSink.info.message(EPrefixInternalError, "Bad type in AddUnaryMath", line);
196 return 0;
197 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000198
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000199 switch (op) {
200 case EOpLogicalNot:
201 if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) {
202 return 0;
203 }
204 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000205
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000206 case EOpPostIncrement:
207 case EOpPreIncrement:
208 case EOpPostDecrement:
209 case EOpPreDecrement:
210 case EOpNegative:
211 if (child->getType().getBasicType() == EbtStruct || child->getType().isArray())
212 return 0;
213 default: break;
214 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000215
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000216 //
217 // Do we need to promote the operand?
218 //
219 // Note: Implicit promotions were removed from the language.
220 //
221 TBasicType newType = EbtVoid;
222 switch (op) {
223 case EOpConstructInt: newType = EbtInt; break;
224 case EOpConstructBool: newType = EbtBool; break;
225 case EOpConstructFloat: newType = EbtFloat; break;
226 default: break;
227 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000228
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000229 if (newType != EbtVoid) {
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000230 child = addConversion(op, TType(newType, child->getPrecision(), EvqTemporary,
231 child->getNominalSize(),
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000232 child->isMatrix(),
233 child->isArray()),
234 child);
235 if (child == 0)
236 return 0;
237 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000238
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000239 //
240 // For constructors, we are now done, it's all in the conversion.
241 //
242 switch (op) {
243 case EOpConstructInt:
244 case EOpConstructBool:
245 case EOpConstructFloat:
246 return child;
247 default: break;
248 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000249
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000250 TIntermConstantUnion *childTempConstant = 0;
251 if (child->getAsConstantUnion())
252 childTempConstant = child->getAsConstantUnion();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000253
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000254 //
255 // Make a new node for the operator.
256 //
257 node = new TIntermUnary(op);
258 if (line == 0)
259 line = child->getLine();
260 node->setLine(line);
261 node->setOperand(child);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000262
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000263 if (! node->promote(infoSink))
264 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000265
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000266 if (childTempConstant) {
267 TIntermTyped* newChild = childTempConstant->fold(op, 0, infoSink);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000268
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000269 if (newChild)
270 return newChild;
271 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000272
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000273 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000274}
275
276//
277// This is the safe way to change the operator on an aggregate, as it
278// does lots of error checking and fixing. Especially for establishing
279// a function call's operation on it's set of parameters. Sequences
280// of instructions are also aggregates, but they just direnctly set
281// their operator to EOpSequence.
282//
283// Returns an aggregate node, which could be the one passed in if
284// it was already an aggregate.
285//
286TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, TSourceLoc line)
287{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000288 TIntermAggregate* aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000289
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000290 //
291 // Make sure we have an aggregate. If not turn it into one.
292 //
293 if (node) {
294 aggNode = node->getAsAggregate();
295 if (aggNode == 0 || aggNode->getOp() != EOpNull) {
296 //
297 // Make an aggregate containing this node.
298 //
299 aggNode = new TIntermAggregate();
300 aggNode->getSequence().push_back(node);
301 if (line == 0)
302 line = node->getLine();
303 }
304 } else
305 aggNode = new TIntermAggregate();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000306
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000307 //
308 // Set the operator.
309 //
310 aggNode->setOperator(op);
311 if (line != 0)
312 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000313
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000314 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000315}
316
317//
318// Convert one type to another.
319//
320// Returns the node representing the conversion, which could be the same
321// node passed in if no conversion was needed.
322//
323// Return 0 if a conversion can't be done.
324//
325TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TIntermTyped* node)
326{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000327 //
328 // Does the base type allow operation?
329 //
330 switch (node->getBasicType()) {
331 case EbtVoid:
332 case EbtSampler2D:
333 case EbtSamplerCube:
334 return 0;
335 default: break;
336 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000337
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000338 //
339 // Otherwise, if types are identical, no problem
340 //
341 if (type == node->getType())
342 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000343
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000344 //
345 // If one's a structure, then no conversions.
346 //
347 if (type.getStruct() || node->getType().getStruct())
348 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000349
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000350 //
351 // If one's an array, then no conversions.
352 //
353 if (type.isArray() || node->getType().isArray())
354 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000355
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000356 TBasicType promoteTo;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000357
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000358 switch (op) {
359 //
360 // Explicit conversions
361 //
362 case EOpConstructBool:
363 promoteTo = EbtBool;
364 break;
365 case EOpConstructFloat:
366 promoteTo = EbtFloat;
367 break;
368 case EOpConstructInt:
369 promoteTo = EbtInt;
370 break;
371 default:
372 //
373 // implicit conversions were removed from the language.
374 //
375 if (type.getBasicType() != node->getType().getBasicType())
376 return 0;
377 //
378 // Size and structure could still differ, but that's
379 // handled by operator promotion.
380 //
381 return node;
382 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000383
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000384 if (node->getAsConstantUnion()) {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000385
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000386 return (promoteConstantUnion(promoteTo, node->getAsConstantUnion()));
387 } else {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000388
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000389 //
390 // Add a new newNode for the conversion.
391 //
392 TIntermUnary* newNode = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000393
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000394 TOperator newOp = EOpNull;
395 switch (promoteTo) {
396 case EbtFloat:
397 switch (node->getBasicType()) {
398 case EbtInt: newOp = EOpConvIntToFloat; break;
399 case EbtBool: newOp = EOpConvBoolToFloat; break;
400 default:
401 infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
402 return 0;
403 }
404 break;
405 case EbtBool:
406 switch (node->getBasicType()) {
407 case EbtInt: newOp = EOpConvIntToBool; break;
408 case EbtFloat: newOp = EOpConvFloatToBool; break;
409 default:
410 infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
411 return 0;
412 }
413 break;
414 case EbtInt:
415 switch (node->getBasicType()) {
416 case EbtBool: newOp = EOpConvBoolToInt; break;
417 case EbtFloat: newOp = EOpConvFloatToInt; break;
418 default:
419 infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
420 return 0;
421 }
422 break;
423 default:
424 infoSink.info.message(EPrefixInternalError, "Bad promotion type", node->getLine());
425 return 0;
426 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000427
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000428 TType type(promoteTo, node->getPrecision(), EvqTemporary, node->getNominalSize(), node->isMatrix(), node->isArray());
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000429 newNode = new TIntermUnary(newOp, type);
430 newNode->setLine(node->getLine());
431 newNode->setOperand(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000432
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000433 return newNode;
434 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000435}
436
437//
438// Safe way to combine two nodes into an aggregate. Works with null pointers,
439// a node that's not a aggregate yet, etc.
440//
441// Returns the resulting aggregate, unless 0 was passed in for
442// both existing nodes.
443//
444TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, TSourceLoc line)
445{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000446 if (left == 0 && right == 0)
447 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000448
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000449 TIntermAggregate* aggNode = 0;
450 if (left)
451 aggNode = left->getAsAggregate();
452 if (!aggNode || aggNode->getOp() != EOpNull) {
453 aggNode = new TIntermAggregate;
454 if (left)
455 aggNode->getSequence().push_back(left);
456 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000457
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000458 if (right)
459 aggNode->getSequence().push_back(right);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000460
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000461 if (line != 0)
462 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000463
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000464 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000465}
466
467//
468// Turn an existing node into an aggregate.
469//
470// Returns an aggregate, unless 0 was passed in for the existing node.
471//
472TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, TSourceLoc line)
473{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000474 if (node == 0)
475 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000476
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000477 TIntermAggregate* aggNode = new TIntermAggregate;
478 aggNode->getSequence().push_back(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000479
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000480 if (line != 0)
481 aggNode->setLine(line);
482 else
483 aggNode->setLine(node->getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000484
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000485 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000486}
487
488//
489// For "if" test nodes. There are three children; a condition,
490// a true path, and a false path. The two paths are in the
491// nodePair.
492//
493// Returns the selection node created.
494//
495TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, TSourceLoc line)
496{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000497 //
498 // For compile time constant selections, prune the code and
499 // test now.
500 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000501
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000502 if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion()) {
503 if (cond->getAsTyped()->getAsConstantUnion()->getUnionArrayPointer()->getBConst())
504 return nodePair.node1;
505 else
506 return nodePair.node2;
507 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000508
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000509 TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2);
510 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000511
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000512 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000513}
514
515
516TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc line)
517{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000518 if (left->getType().getQualifier() == EvqConst && right->getType().getQualifier() == EvqConst) {
519 return right;
520 } else {
521 TIntermTyped *commaAggregate = growAggregate(left, right, line);
522 commaAggregate->getAsAggregate()->setOperator(EOpComma);
523 commaAggregate->setType(right->getType());
524 commaAggregate->getTypePointer()->changeQualifier(EvqTemporary);
525 return commaAggregate;
526 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000527}
528
529//
530// For "?:" test nodes. There are three children; a condition,
531// a true path, and a false path. The two paths are specified
532// as separate parameters.
533//
534// Returns the selection node created, or 0 if one could not be.
535//
536TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, TSourceLoc line)
537{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000538 //
539 // Get compatible types.
540 //
541 TIntermTyped* child = addConversion(EOpSequence, trueBlock->getType(), falseBlock);
542 if (child)
543 falseBlock = child;
544 else {
545 child = addConversion(EOpSequence, falseBlock->getType(), trueBlock);
546 if (child)
547 trueBlock = child;
548 else
549 return 0;
550 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000551
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000552 //
553 // See if all the operands are constant, then fold it otherwise not.
554 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000555
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000556 if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) {
557 if (cond->getAsConstantUnion()->getUnionArrayPointer()->getBConst())
558 return trueBlock;
559 else
560 return falseBlock;
561 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000562
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000563 //
564 // Make a selection node.
565 //
566 TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
567 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000568
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000569 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000570}
571
572//
573// Constant terminal nodes. Has a union that contains bool, float or int constants
574//
575// Returns the constant union node created.
576//
577
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000578TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, TSourceLoc line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000579{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000580 TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t);
581 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000582
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000583 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000584}
585
586TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, TSourceLoc line)
587{
588
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000589 TIntermAggregate* node = new TIntermAggregate(EOpSequence);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000590
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000591 node->setLine(line);
592 TIntermConstantUnion* constIntNode;
593 TIntermSequence &sequenceVector = node->getSequence();
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000594 ConstantUnion* unionArray;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000595
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000596 for (int i = 0; i < fields.num; i++) {
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000597 unionArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000598 unionArray->setIConst(fields.offsets[i]);
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000599 constIntNode = addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), line);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000600 sequenceVector.push_back(constIntNode);
601 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000602
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000603 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000604}
605
606//
607// Create loop nodes.
608//
609TIntermNode* TIntermediate::addLoop(TIntermNode *init, TIntermNode* body, TIntermTyped* test, TIntermTyped* terminal, bool testFirst, TSourceLoc line)
610{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000611 TIntermNode* node = new TIntermLoop(init, body, test, terminal, testFirst);
612 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000613
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000614 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000615}
616
617//
618// Add branches.
619//
620TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TSourceLoc line)
621{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000622 return addBranch(branchOp, 0, line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000623}
624
625TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, TSourceLoc line)
626{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000627 TIntermBranch* node = new TIntermBranch(branchOp, expression);
628 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000629
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000630 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000631}
632
633//
634// This is to be executed once the final root is put on top by the parsing
635// process.
636//
637bool TIntermediate::postProcess(TIntermNode* root, EShLanguage language)
638{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000639 if (root == 0)
640 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000641
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000642 //
643 // First, finish off the top level sequence, if any
644 //
645 TIntermAggregate* aggRoot = root->getAsAggregate();
646 if (aggRoot && aggRoot->getOp() == EOpNull)
647 aggRoot->setOperator(EOpSequence);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000648
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000649 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000650}
651
652//
653// This deletes the tree.
654//
655void TIntermediate::remove(TIntermNode* root)
656{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000657 if (root)
658 RemoveAllTreeNodes(root);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000659}
660
661////////////////////////////////////////////////////////////////
662//
663// Member functions of the nodes used for building the tree.
664//
665////////////////////////////////////////////////////////////////
666
667//
668// Say whether or not an operation node changes the value of a variable.
669//
670// Returns true if state is modified.
671//
672bool TIntermOperator::modifiesState() const
673{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000674 switch (op) {
675 case EOpPostIncrement:
676 case EOpPostDecrement:
677 case EOpPreIncrement:
678 case EOpPreDecrement:
679 case EOpAssign:
680 case EOpAddAssign:
681 case EOpSubAssign:
682 case EOpMulAssign:
683 case EOpVectorTimesMatrixAssign:
684 case EOpVectorTimesScalarAssign:
685 case EOpMatrixTimesScalarAssign:
686 case EOpMatrixTimesMatrixAssign:
687 case EOpDivAssign:
688 return true;
689 default:
690 return false;
691 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000692}
693
694//
695// returns true if the operator is for one of the constructors
696//
697bool TIntermOperator::isConstructor() const
698{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000699 switch (op) {
700 case EOpConstructVec2:
701 case EOpConstructVec3:
702 case EOpConstructVec4:
703 case EOpConstructMat2:
704 case EOpConstructMat3:
705 case EOpConstructMat4:
706 case EOpConstructFloat:
707 case EOpConstructIVec2:
708 case EOpConstructIVec3:
709 case EOpConstructIVec4:
710 case EOpConstructInt:
711 case EOpConstructBVec2:
712 case EOpConstructBVec3:
713 case EOpConstructBVec4:
714 case EOpConstructBool:
715 case EOpConstructStruct:
716 return true;
717 default:
718 return false;
719 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000720}
721//
722// Make sure the type of a unary operator is appropriate for its
723// combination of operation and operand type.
724//
725// Returns false in nothing makes sense.
726//
727bool TIntermUnary::promote(TInfoSink&)
728{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000729 switch (op) {
730 case EOpLogicalNot:
731 if (operand->getBasicType() != EbtBool)
732 return false;
733 break;
734 case EOpNegative:
735 case EOpPostIncrement:
736 case EOpPostDecrement:
737 case EOpPreIncrement:
738 case EOpPreDecrement:
739 if (operand->getBasicType() == EbtBool)
740 return false;
741 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000742
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000743 // operators for built-ins are already type checked against their prototype
744 case EOpAny:
745 case EOpAll:
746 case EOpVectorLogicalNot:
747 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000748
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000749 default:
750 if (operand->getBasicType() != EbtFloat)
751 return false;
752 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000753
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000754 setType(operand->getType());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000755
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000756 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000757}
758
759//
760// Establishes the type of the resultant operation, as well as
761// makes the operator the correct one for the operands.
762//
763// Returns false if operator can't work on operands.
764//
765bool TIntermBinary::promote(TInfoSink& infoSink)
766{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000767 int size = left->getNominalSize();
768 if (right->getNominalSize() > size)
769 size = right->getNominalSize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000770
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000771 TBasicType type = left->getBasicType();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000772
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000773 //
774 // Arrays have to be exact matches.
775 //
776 if ((left->isArray() || right->isArray()) && (left->getType() != right->getType()))
777 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000778
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000779 //
780 // Base assumption: just make the type the same as the left
781 // operand. Then only deviations from this need be coded.
782 //
daniel@transgaming.comfe565152010-04-10 05:29:07 +0000783 setType(left->getType());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000784
daniel@transgaming.com9abe9562010-06-24 13:02:21 +0000785 TPrecision highestPrecision = GetHighestPrecision(left->getPrecision(), right->getPrecision());
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000786 getTypePointer()->changePrecision(highestPrecision);
787
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000788 //
789 // Array operations.
790 //
791 if (left->isArray()) {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000792
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000793 switch (op) {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000794
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 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000815
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000816 return true;
817 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000818
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000819 //
820 // All scalars. Code after this test assumes this case is removed!
821 //
822 if (size == 1) {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000823
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000824 switch (op) {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000825
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000826 //
827 // Promote to conditional
828 //
829 case EOpEqual:
830 case EOpNotEqual:
831 case EOpLessThan:
832 case EOpGreaterThan:
833 case EOpLessThanEqual:
834 case EOpGreaterThanEqual:
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000835 setType(TType(EbtBool, EbpUndefined));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000836 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000837
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000838 //
839 // And and Or operate on conditionals
840 //
841 case EOpLogicalAnd:
842 case EOpLogicalOr:
843 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 //
849 // Everything else should have matching types
850 //
851 default:
852 if (left->getBasicType() != right->getBasicType() ||
853 left->isMatrix() != right->isMatrix())
854 return false;
855 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000856
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000857 return true;
858 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000859
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000860 //
861 // Are the sizes compatible?
862 //
863 if ( left->getNominalSize() != size && left->getNominalSize() != 1 ||
864 right->getNominalSize() != size && right->getNominalSize() != 1)
865 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000866
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000867 //
868 // Can these two operands be combined?
869 //
870 switch (op) {
871 case EOpMul:
872 if (!left->isMatrix() && right->isMatrix()) {
873 if (left->isVector())
874 op = EOpVectorTimesMatrix;
875 else {
876 op = EOpMatrixTimesScalar;
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000877 setType(TType(type, highestPrecision, EvqTemporary, size, true));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000878 }
879 } else if (left->isMatrix() && !right->isMatrix()) {
880 if (right->isVector()) {
881 op = EOpMatrixTimesVector;
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000882 setType(TType(type, highestPrecision, EvqTemporary, size, false));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000883 } else {
884 op = EOpMatrixTimesScalar;
885 }
886 } else if (left->isMatrix() && right->isMatrix()) {
887 op = EOpMatrixTimesMatrix;
888 } else if (!left->isMatrix() && !right->isMatrix()) {
889 if (left->isVector() && right->isVector()) {
890 // leave as component product
891 } else if (left->isVector() || right->isVector()) {
892 op = EOpVectorTimesScalar;
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000893 setType(TType(type, highestPrecision, EvqTemporary, size, false));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000894 }
895 } else {
896 infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
897 return false;
898 }
899 break;
900 case EOpMulAssign:
901 if (!left->isMatrix() && right->isMatrix()) {
902 if (left->isVector())
903 op = EOpVectorTimesMatrixAssign;
904 else {
905 return false;
906 }
907 } else if (left->isMatrix() && !right->isMatrix()) {
908 if (right->isVector()) {
909 return false;
910 } else {
911 op = EOpMatrixTimesScalarAssign;
912 }
913 } else if (left->isMatrix() && right->isMatrix()) {
914 op = EOpMatrixTimesMatrixAssign;
915 } else if (!left->isMatrix() && !right->isMatrix()) {
916 if (left->isVector() && right->isVector()) {
917 // leave as component product
918 } else if (left->isVector() || right->isVector()) {
919 if (! left->isVector())
920 return false;
921 op = EOpVectorTimesScalarAssign;
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000922 setType(TType(type, highestPrecision, EvqTemporary, size, false));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000923 }
924 } else {
925 infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
926 return false;
927 }
928 break;
929 case EOpAssign:
930 case EOpInitialize:
931 if (left->getNominalSize() != right->getNominalSize())
932 return false;
933 // fall through
934 case EOpAdd:
935 case EOpSub:
936 case EOpDiv:
937 case EOpAddAssign:
938 case EOpSubAssign:
939 case EOpDivAssign:
940 if (left->isMatrix() && right->isVector() ||
941 left->isVector() && right->isMatrix() ||
942 left->getBasicType() != right->getBasicType())
943 return false;
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000944 setType(TType(type, highestPrecision, EvqTemporary, size, left->isMatrix() || right->isMatrix()));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000945 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000946
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000947 case EOpEqual:
948 case EOpNotEqual:
949 case EOpLessThan:
950 case EOpGreaterThan:
951 case EOpLessThanEqual:
952 case EOpGreaterThanEqual:
953 if (left->isMatrix() && right->isVector() ||
954 left->isVector() && right->isMatrix() ||
955 left->getBasicType() != right->getBasicType())
956 return false;
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000957 setType(TType(EbtBool, EbpUndefined));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000958 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000959
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000960 default:
961 return false;
962 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000963
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000964 //
965 // One more check for assignment. The Resulting type has to match the left operand.
966 //
967 switch (op) {
968 case EOpAssign:
969 case EOpInitialize:
970 case EOpAddAssign:
971 case EOpSubAssign:
972 case EOpMulAssign:
973 case EOpDivAssign:
974 if (getType() != left->getType())
975 return false;
976 break;
977 default:
978 break;
979 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000980
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000981 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000982}
983
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000984bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000985{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000986 TTypeList* fields = leftNodeType.getStruct();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000987
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000988 size_t structSize = fields->size();
989 int index = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000990
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000991 for (size_t j = 0; j < structSize; j++) {
992 int size = (*fields)[j].type->getObjectSize();
993 for (int i = 0; i < size; i++) {
994 if ((*fields)[j].type->getBasicType() == EbtStruct) {
995 if (!CompareStructure(*(*fields)[j].type, &rightUnionArray[index], &leftUnionArray[index]))
996 return false;
997 } else {
998 if (leftUnionArray[index] != rightUnionArray[index])
999 return false;
1000 index++;
1001 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001002
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001003 }
1004 }
1005 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001006}
1007
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001008bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001009{
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001010 if (leftNodeType.isArray()) {
1011 TType typeWithoutArrayness = leftNodeType;
1012 typeWithoutArrayness.clearArrayness();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001013
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001014 int arraySize = leftNodeType.getArraySize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001015
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001016 for (int i = 0; i < arraySize; ++i) {
1017 int offset = typeWithoutArrayness.getObjectSize() * i;
1018 if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset]))
1019 return false;
1020 }
1021 } else
1022 return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001023
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001024 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001025}
1026
1027//
1028// The fold functions see if an operation on a constant can be done in place,
1029// without generating run-time code.
1030//
1031// Returns the node to keep using, which may or may not be the node passed in.
1032//
1033
1034TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink)
1035{
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001036 ConstantUnion *unionArray = getUnionArrayPointer();
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001037 int objectSize = getType().getObjectSize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001038
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001039 if (constantNode) { // binary operations
1040 TIntermConstantUnion *node = constantNode->getAsConstantUnion();
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001041 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001042 TType returnType = getType();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001043
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001044 // for a case like float f = 1.2 + vec4(2,3,4,5);
1045 if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) {
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001046 rightUnionArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001047 for (int i = 0; i < objectSize; ++i)
1048 rightUnionArray[i] = *node->getUnionArrayPointer();
1049 returnType = getType();
1050 } else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) {
1051 // for a case like float f = vec4(2,3,4,5) + 1.2;
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001052 unionArray = new ConstantUnion[constantNode->getType().getObjectSize()];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001053 for (int i = 0; i < constantNode->getType().getObjectSize(); ++i)
1054 unionArray[i] = *getUnionArrayPointer();
1055 returnType = node->getType();
1056 objectSize = constantNode->getType().getObjectSize();
1057 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001058
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001059 ConstantUnion* tempConstArray = 0;
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001060 TIntermConstantUnion *tempNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001061
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001062 bool boolNodeFlag = false;
1063 switch(op) {
1064 case EOpAdd:
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001065 tempConstArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001066 {// support MSVC++6.0
1067 for (int i = 0; i < objectSize; i++)
1068 tempConstArray[i] = unionArray[i] + rightUnionArray[i];
1069 }
1070 break;
1071 case EOpSub:
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001072 tempConstArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001073 {// support MSVC++6.0
1074 for (int i = 0; i < objectSize; i++)
1075 tempConstArray[i] = unionArray[i] - rightUnionArray[i];
1076 }
1077 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001078
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001079 case EOpMul:
1080 case EOpVectorTimesScalar:
1081 case EOpMatrixTimesScalar:
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001082 tempConstArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001083 {// support MSVC++6.0
1084 for (int i = 0; i < objectSize; i++)
1085 tempConstArray[i] = unionArray[i] * rightUnionArray[i];
1086 }
1087 break;
1088 case EOpMatrixTimesMatrix:
1089 if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat) {
1090 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
1091 return 0;
1092 }
1093 {// support MSVC++6.0
1094 int size = getNominalSize();
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001095 tempConstArray = new ConstantUnion[size*size];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001096 for (int row = 0; row < size; row++) {
1097 for (int column = 0; column < size; column++) {
1098 tempConstArray[size * column + row].setFConst(0.0f);
1099 for (int i = 0; i < size; i++) {
1100 tempConstArray[size * column + row].setFConst(tempConstArray[size * column + row].getFConst() + unionArray[i * size + row].getFConst() * (rightUnionArray[column * size + i].getFConst()));
1101 }
1102 }
1103 }
1104 }
1105 break;
1106 case EOpDiv:
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001107 tempConstArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001108 {// support MSVC++6.0
1109 for (int i = 0; i < objectSize; i++) {
1110 switch (getType().getBasicType()) {
1111 case EbtFloat:
1112 if (rightUnionArray[i] == 0.0f) {
1113 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1114 tempConstArray[i].setFConst(FLT_MAX);
1115 } else
1116 tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst());
1117 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001118
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001119 case EbtInt:
1120 if (rightUnionArray[i] == 0) {
1121 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1122 tempConstArray[i].setIConst(INT_MAX);
1123 } else
1124 tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst());
1125 break;
1126 default:
1127 infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"/\"", getLine());
1128 return 0;
1129 }
1130 }
1131 }
1132 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001133
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001134 case EOpMatrixTimesVector:
1135 if (node->getBasicType() != EbtFloat) {
1136 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix times vector", getLine());
1137 return 0;
1138 }
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001139 tempConstArray = new ConstantUnion[getNominalSize()];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001140
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001141 {// support MSVC++6.0
1142 for (int size = getNominalSize(), i = 0; i < size; i++) {
1143 tempConstArray[i].setFConst(0.0f);
1144 for (int j = 0; j < size; j++) {
1145 tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j*size + i].getFConst()) * rightUnionArray[j].getFConst()));
1146 }
1147 }
1148 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001149
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001150 tempNode = new TIntermConstantUnion(tempConstArray, node->getType());
1151 tempNode->setLine(getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001152
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001153 return tempNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001154
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001155 case EOpVectorTimesMatrix:
1156 if (getType().getBasicType() != EbtFloat) {
1157 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for vector times matrix", getLine());
1158 return 0;
1159 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001160
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001161 tempConstArray = new ConstantUnion[getNominalSize()];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001162 {// support MSVC++6.0
1163 for (int size = getNominalSize(), i = 0; i < size; i++) {
1164 tempConstArray[i].setFConst(0.0f);
1165 for (int j = 0; j < size; j++) {
1166 tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j].getFConst()) * rightUnionArray[i*size + j].getFConst()));
1167 }
1168 }
1169 }
1170 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001171
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001172 case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001173 tempConstArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001174 {// support MSVC++6.0
1175 for (int i = 0; i < objectSize; i++)
1176 tempConstArray[i] = unionArray[i] && rightUnionArray[i];
1177 }
1178 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001179
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001180 case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001181 tempConstArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001182 {// support MSVC++6.0
1183 for (int i = 0; i < objectSize; i++)
1184 tempConstArray[i] = unionArray[i] || rightUnionArray[i];
1185 }
1186 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001187
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001188 case EOpLogicalXor:
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001189 tempConstArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001190 {// support MSVC++6.0
1191 for (int i = 0; i < objectSize; i++)
1192 switch (getType().getBasicType()) {
1193 case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break;
1194 default: assert(false && "Default missing");
1195 }
1196 }
1197 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001198
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001199 case EOpLessThan:
1200 assert(objectSize == 1);
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001201 tempConstArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001202 tempConstArray->setBConst(*unionArray < *rightUnionArray);
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001203 returnType = TType(EbtBool, EbpUndefined, EvqConst);
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001204 break;
1205 case EOpGreaterThan:
1206 assert(objectSize == 1);
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001207 tempConstArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001208 tempConstArray->setBConst(*unionArray > *rightUnionArray);
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 case EOpLessThanEqual:
1212 {
1213 assert(objectSize == 1);
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001214 ConstantUnion constant;
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001215 constant.setBConst(*unionArray > *rightUnionArray);
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001216 tempConstArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001217 tempConstArray->setBConst(!constant.getBConst());
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001218 returnType = TType(EbtBool, EbpUndefined, EvqConst);
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001219 break;
1220 }
1221 case EOpGreaterThanEqual:
1222 {
1223 assert(objectSize == 1);
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001224 ConstantUnion constant;
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001225 constant.setBConst(*unionArray < *rightUnionArray);
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001226 tempConstArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001227 tempConstArray->setBConst(!constant.getBConst());
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001228 returnType = TType(EbtBool, EbpUndefined, EvqConst);
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001229 break;
1230 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001231
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001232 case EOpEqual:
1233 if (getType().getBasicType() == EbtStruct) {
1234 if (!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
1235 boolNodeFlag = true;
1236 } else {
1237 for (int i = 0; i < objectSize; i++) {
1238 if (unionArray[i] != rightUnionArray[i]) {
1239 boolNodeFlag = true;
1240 break; // break out of for loop
1241 }
1242 }
1243 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001244
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001245 tempConstArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001246 if (!boolNodeFlag) {
1247 tempConstArray->setBConst(true);
1248 }
1249 else {
1250 tempConstArray->setBConst(false);
1251 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001252
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001253 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001254 tempNode->setLine(getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001255
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001256 return tempNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001257
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001258 case EOpNotEqual:
1259 if (getType().getBasicType() == EbtStruct) {
1260 if (CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
1261 boolNodeFlag = true;
1262 } else {
1263 for (int i = 0; i < objectSize; i++) {
1264 if (unionArray[i] == rightUnionArray[i]) {
1265 boolNodeFlag = true;
1266 break; // break out of for loop
1267 }
1268 }
1269 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001270
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001271 tempConstArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001272 if (!boolNodeFlag) {
1273 tempConstArray->setBConst(true);
1274 }
1275 else {
1276 tempConstArray->setBConst(false);
1277 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001278
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001279 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001280 tempNode->setLine(getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001281
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001282 return tempNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001283
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001284 default:
1285 infoSink.info.message(EPrefixInternalError, "Invalid operator for constant folding", getLine());
1286 return 0;
1287 }
1288 tempNode = new TIntermConstantUnion(tempConstArray, returnType);
1289 tempNode->setLine(getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001290
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001291 return tempNode;
1292 } else {
1293 //
1294 // Do unary operations
1295 //
1296 TIntermConstantUnion *newNode = 0;
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001297 ConstantUnion* tempConstArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001298 for (int i = 0; i < objectSize; i++) {
1299 switch(op) {
1300 case EOpNegative:
1301 switch (getType().getBasicType()) {
1302 case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break;
1303 case EbtInt: tempConstArray[i].setIConst(-unionArray[i].getIConst()); break;
1304 default:
1305 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1306 return 0;
1307 }
1308 break;
1309 case EOpLogicalNot: // this code is written for possible future use, will not get executed currently
1310 switch (getType().getBasicType()) {
1311 case EbtBool: tempConstArray[i].setBConst(!unionArray[i].getBConst()); break;
1312 default:
1313 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1314 return 0;
1315 }
1316 break;
1317 default:
1318 return 0;
1319 }
1320 }
1321 newNode = new TIntermConstantUnion(tempConstArray, getType());
1322 newNode->setLine(getLine());
1323 return newNode;
1324 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001325
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001326 return this;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001327}
1328
1329TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node)
1330{
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001331 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001332 int size = node->getType().getObjectSize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001333
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001334 ConstantUnion *leftUnionArray = new ConstantUnion[size];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001335
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001336 for (int i=0; i < size; i++) {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001337
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001338 switch (promoteTo) {
1339 case EbtFloat:
1340 switch (node->getType().getBasicType()) {
1341 case EbtInt:
1342 leftUnionArray[i].setFConst(static_cast<float>(rightUnionArray[i].getIConst()));
1343 break;
1344 case EbtBool:
1345 leftUnionArray[i].setFConst(static_cast<float>(rightUnionArray[i].getBConst()));
1346 break;
1347 case EbtFloat:
1348 leftUnionArray[i] = rightUnionArray[i];
1349 break;
1350 default:
1351 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1352 return 0;
1353 }
1354 break;
1355 case EbtInt:
1356 switch (node->getType().getBasicType()) {
1357 case EbtInt:
1358 leftUnionArray[i] = rightUnionArray[i];
1359 break;
1360 case EbtBool:
1361 leftUnionArray[i].setIConst(static_cast<int>(rightUnionArray[i].getBConst()));
1362 break;
1363 case EbtFloat:
1364 leftUnionArray[i].setIConst(static_cast<int>(rightUnionArray[i].getFConst()));
1365 break;
1366 default:
1367 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1368 return 0;
1369 }
1370 break;
1371 case EbtBool:
1372 switch (node->getType().getBasicType()) {
1373 case EbtInt:
1374 leftUnionArray[i].setBConst(rightUnionArray[i].getIConst() != 0);
1375 break;
1376 case EbtBool:
1377 leftUnionArray[i] = rightUnionArray[i];
1378 break;
1379 case EbtFloat:
1380 leftUnionArray[i].setBConst(rightUnionArray[i].getFConst() != 0.0f);
1381 break;
1382 default:
1383 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1384 return 0;
1385 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001386
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001387 break;
1388 default:
1389 infoSink.info.message(EPrefixInternalError, "Incorrect data type found", node->getLine());
1390 return 0;
1391 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001392
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001393 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001394
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001395 const TType& t = node->getType();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001396
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001397 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 +00001398}
1399
1400void TIntermAggregate::addToPragmaTable(const TPragmaTable& pTable)
1401{
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001402 assert(!pragmaTable);
1403 pragmaTable = new TPragmaTable();
1404 *pragmaTable = pTable;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001405}