blob: 51a7b7dbef2a2312c00ef998469c02705775a019 [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.coma5d76232010-05-17 09:58:47 +000020TPrecision GetHighestPrecision( TPrecision left, TPrecision right, TInfoSink& infoSink ){
21 TPrecision highest = left > right ? left : right;
22
23 if (highest == EbpUndefined) {
24 infoSink.info.message(EPrefixInternalError, "Unknown or invalid precision for operands", 0);
25 }
26
27 return highest;
28}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000029////////////////////////////////////////////////////////////////////////////
30//
31// First set of functions are to help build the intermediate representation.
32// These functions are not member functions of the nodes.
33// They are called from parser productions.
34//
35/////////////////////////////////////////////////////////////////////////////
36
37//
38// Add a terminal node for an identifier in an expression.
39//
40// Returns the added node.
41//
42TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, TSourceLoc line)
43{
alokp@chromium.org2cf17712010-03-30 20:33:18 +000044 TIntermSymbol* node = new TIntermSymbol(id, name, type);
45 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000046
alokp@chromium.org2cf17712010-03-30 20:33:18 +000047 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000048}
49
50//
51// Connect two nodes with a new parent that does a binary operation on the nodes.
52//
53// Returns the added node.
54//
55TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line, TSymbolTable& symbolTable)
56{
alokp@chromium.org2cf17712010-03-30 20:33:18 +000057 switch (op) {
58 case EOpLessThan:
59 case EOpGreaterThan:
60 case EOpLessThanEqual:
61 case EOpGreaterThanEqual:
62 if (left->getType().isMatrix() || left->getType().isArray() || left->getType().isVector() || left->getType().getBasicType() == EbtStruct) {
63 return 0;
64 }
65 break;
66 case EOpLogicalOr:
67 case EOpLogicalXor:
68 case EOpLogicalAnd:
69 if (left->getType().getBasicType() != EbtBool || left->getType().isMatrix() || left->getType().isArray() || left->getType().isVector()) {
70 return 0;
71 }
72 break;
73 case EOpAdd:
74 case EOpSub:
75 case EOpDiv:
76 case EOpMul:
77 if (left->getType().getBasicType() == EbtStruct || left->getType().getBasicType() == EbtBool)
78 return 0;
79 default: break;
80 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000081
alokp@chromium.org2cf17712010-03-30 20:33:18 +000082 //
83 // First try converting the children to compatible types.
84 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000085
alokp@chromium.org2cf17712010-03-30 20:33:18 +000086 if (!(left->getType().getStruct() && right->getType().getStruct())) {
87 TIntermTyped* child = addConversion(op, left->getType(), right);
88 if (child)
89 right = child;
90 else {
91 child = addConversion(op, right->getType(), left);
92 if (child)
93 left = child;
94 else
95 return 0;
96 }
97 } else {
98 if (left->getType() != right->getType())
99 return 0;
100 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000101
102
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000103 //
104 // Need a new node holding things together then. Make
105 // one and promote it to the right type.
106 //
107 TIntermBinary* node = new TIntermBinary(op);
108 if (line == 0)
109 line = right->getLine();
110 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000111
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000112 node->setLeft(left);
113 node->setRight(right);
114 if (! node->promote(infoSink))
115 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000116
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000117 TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
118 TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000119
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000120 if (leftTempConstant)
121 leftTempConstant = left->getAsConstantUnion();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000122
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000123 if (rightTempConstant)
124 rightTempConstant = right->getAsConstantUnion();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000125
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000126 //
127 // See if we can fold constants.
128 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000129
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000130 TIntermTyped* typedReturnNode = 0;
131 if ( leftTempConstant && rightTempConstant) {
132 typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000133
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000134 if (typedReturnNode)
135 return typedReturnNode;
136 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000137
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000138 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000139}
140
141//
142// Connect two nodes through an assignment.
143//
144// Returns the added node.
145//
146TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line)
147{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000148 //
149 // Like adding binary math, except the conversion can only go
150 // from right to left.
151 //
152 TIntermBinary* node = new TIntermBinary(op);
153 if (line == 0)
154 line = left->getLine();
155 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000156
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000157 TIntermTyped* child = addConversion(op, left->getType(), right);
158 if (child == 0)
159 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000160
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000161 node->setLeft(left);
162 node->setRight(child);
163 if (! node->promote(infoSink))
164 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000165
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000166 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000167}
168
169//
170// Connect two nodes through an index operator, where the left node is the base
171// of an array or struct, and the right node is a direct or indirect offset.
172//
173// Returns the added node.
174// The caller should set the type of the returned node.
175//
176TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc line)
177{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000178 TIntermBinary* node = new TIntermBinary(op);
179 if (line == 0)
180 line = index->getLine();
181 node->setLine(line);
182 node->setLeft(base);
183 node->setRight(index);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000184
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000185 // caller should set the type
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000186
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000187 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000188}
189
190//
191// Add one node as the parent of another that it operates on.
192//
193// Returns the added node.
194//
195TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, TSourceLoc line, TSymbolTable& symbolTable)
196{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000197 TIntermUnary* node;
198 TIntermTyped* child = childNode->getAsTyped();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000199
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000200 if (child == 0) {
201 infoSink.info.message(EPrefixInternalError, "Bad type in AddUnaryMath", line);
202 return 0;
203 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000204
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000205 switch (op) {
206 case EOpLogicalNot:
207 if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) {
208 return 0;
209 }
210 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000211
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000212 case EOpPostIncrement:
213 case EOpPreIncrement:
214 case EOpPostDecrement:
215 case EOpPreDecrement:
216 case EOpNegative:
217 if (child->getType().getBasicType() == EbtStruct || child->getType().isArray())
218 return 0;
219 default: break;
220 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000221
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000222 //
223 // Do we need to promote the operand?
224 //
225 // Note: Implicit promotions were removed from the language.
226 //
227 TBasicType newType = EbtVoid;
228 switch (op) {
229 case EOpConstructInt: newType = EbtInt; break;
230 case EOpConstructBool: newType = EbtBool; break;
231 case EOpConstructFloat: newType = EbtFloat; break;
232 default: break;
233 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000234
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000235 if (newType != EbtVoid) {
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000236 child = addConversion(op, TType(newType, child->getPrecision(), EvqTemporary,
237 child->getNominalSize(),
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000238 child->isMatrix(),
239 child->isArray()),
240 child);
241 if (child == 0)
242 return 0;
243 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000244
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000245 //
246 // For constructors, we are now done, it's all in the conversion.
247 //
248 switch (op) {
249 case EOpConstructInt:
250 case EOpConstructBool:
251 case EOpConstructFloat:
252 return child;
253 default: break;
254 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000255
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000256 TIntermConstantUnion *childTempConstant = 0;
257 if (child->getAsConstantUnion())
258 childTempConstant = child->getAsConstantUnion();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000259
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000260 //
261 // Make a new node for the operator.
262 //
263 node = new TIntermUnary(op);
264 if (line == 0)
265 line = child->getLine();
266 node->setLine(line);
267 node->setOperand(child);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000268
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000269 if (! node->promote(infoSink))
270 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000271
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000272 if (childTempConstant) {
273 TIntermTyped* newChild = childTempConstant->fold(op, 0, infoSink);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000274
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000275 if (newChild)
276 return newChild;
277 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000278
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000279 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000280}
281
282//
283// This is the safe way to change the operator on an aggregate, as it
284// does lots of error checking and fixing. Especially for establishing
285// a function call's operation on it's set of parameters. Sequences
286// of instructions are also aggregates, but they just direnctly set
287// their operator to EOpSequence.
288//
289// Returns an aggregate node, which could be the one passed in if
290// it was already an aggregate.
291//
292TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, TSourceLoc line)
293{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000294 TIntermAggregate* aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000295
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000296 //
297 // Make sure we have an aggregate. If not turn it into one.
298 //
299 if (node) {
300 aggNode = node->getAsAggregate();
301 if (aggNode == 0 || aggNode->getOp() != EOpNull) {
302 //
303 // Make an aggregate containing this node.
304 //
305 aggNode = new TIntermAggregate();
306 aggNode->getSequence().push_back(node);
307 if (line == 0)
308 line = node->getLine();
309 }
310 } else
311 aggNode = new TIntermAggregate();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000312
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000313 //
314 // Set the operator.
315 //
316 aggNode->setOperator(op);
317 if (line != 0)
318 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000319
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000320 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000321}
322
323//
324// Convert one type to another.
325//
326// Returns the node representing the conversion, which could be the same
327// node passed in if no conversion was needed.
328//
329// Return 0 if a conversion can't be done.
330//
331TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TIntermTyped* node)
332{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000333 //
334 // Does the base type allow operation?
335 //
336 switch (node->getBasicType()) {
337 case EbtVoid:
338 case EbtSampler2D:
339 case EbtSamplerCube:
340 return 0;
341 default: break;
342 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000343
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000344 //
345 // Otherwise, if types are identical, no problem
346 //
347 if (type == node->getType())
348 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000349
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000350 //
351 // If one's a structure, then no conversions.
352 //
353 if (type.getStruct() || node->getType().getStruct())
354 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000355
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000356 //
357 // If one's an array, then no conversions.
358 //
359 if (type.isArray() || node->getType().isArray())
360 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000361
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000362 TBasicType promoteTo;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000363
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000364 switch (op) {
365 //
366 // Explicit conversions
367 //
368 case EOpConstructBool:
369 promoteTo = EbtBool;
370 break;
371 case EOpConstructFloat:
372 promoteTo = EbtFloat;
373 break;
374 case EOpConstructInt:
375 promoteTo = EbtInt;
376 break;
377 default:
378 //
379 // implicit conversions were removed from the language.
380 //
381 if (type.getBasicType() != node->getType().getBasicType())
382 return 0;
383 //
384 // Size and structure could still differ, but that's
385 // handled by operator promotion.
386 //
387 return node;
388 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000389
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000390 if (node->getAsConstantUnion()) {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000391
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000392 return (promoteConstantUnion(promoteTo, node->getAsConstantUnion()));
393 } else {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000394
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000395 //
396 // Add a new newNode for the conversion.
397 //
398 TIntermUnary* newNode = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000399
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000400 TOperator newOp = EOpNull;
401 switch (promoteTo) {
402 case EbtFloat:
403 switch (node->getBasicType()) {
404 case EbtInt: newOp = EOpConvIntToFloat; break;
405 case EbtBool: newOp = EOpConvBoolToFloat; break;
406 default:
407 infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
408 return 0;
409 }
410 break;
411 case EbtBool:
412 switch (node->getBasicType()) {
413 case EbtInt: newOp = EOpConvIntToBool; break;
414 case EbtFloat: newOp = EOpConvFloatToBool; break;
415 default:
416 infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
417 return 0;
418 }
419 break;
420 case EbtInt:
421 switch (node->getBasicType()) {
422 case EbtBool: newOp = EOpConvBoolToInt; break;
423 case EbtFloat: newOp = EOpConvFloatToInt; break;
424 default:
425 infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
426 return 0;
427 }
428 break;
429 default:
430 infoSink.info.message(EPrefixInternalError, "Bad promotion type", node->getLine());
431 return 0;
432 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000433
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000434 TType type(promoteTo, node->getPrecision(), EvqTemporary, node->getNominalSize(), node->isMatrix(), node->isArray());
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000435 newNode = new TIntermUnary(newOp, type);
436 newNode->setLine(node->getLine());
437 newNode->setOperand(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000438
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000439 return newNode;
440 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000441}
442
443//
444// Safe way to combine two nodes into an aggregate. Works with null pointers,
445// a node that's not a aggregate yet, etc.
446//
447// Returns the resulting aggregate, unless 0 was passed in for
448// both existing nodes.
449//
450TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, TSourceLoc line)
451{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000452 if (left == 0 && right == 0)
453 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000454
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000455 TIntermAggregate* aggNode = 0;
456 if (left)
457 aggNode = left->getAsAggregate();
458 if (!aggNode || aggNode->getOp() != EOpNull) {
459 aggNode = new TIntermAggregate;
460 if (left)
461 aggNode->getSequence().push_back(left);
462 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000463
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000464 if (right)
465 aggNode->getSequence().push_back(right);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000466
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000467 if (line != 0)
468 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000469
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000470 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000471}
472
473//
474// Turn an existing node into an aggregate.
475//
476// Returns an aggregate, unless 0 was passed in for the existing node.
477//
478TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, TSourceLoc line)
479{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000480 if (node == 0)
481 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000482
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000483 TIntermAggregate* aggNode = new TIntermAggregate;
484 aggNode->getSequence().push_back(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000485
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000486 if (line != 0)
487 aggNode->setLine(line);
488 else
489 aggNode->setLine(node->getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000490
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000491 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000492}
493
494//
495// For "if" test nodes. There are three children; a condition,
496// a true path, and a false path. The two paths are in the
497// nodePair.
498//
499// Returns the selection node created.
500//
501TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, TSourceLoc line)
502{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000503 //
504 // For compile time constant selections, prune the code and
505 // test now.
506 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000507
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000508 if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion()) {
509 if (cond->getAsTyped()->getAsConstantUnion()->getUnionArrayPointer()->getBConst())
510 return nodePair.node1;
511 else
512 return nodePair.node2;
513 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000514
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000515 TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2);
516 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000517
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000518 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000519}
520
521
522TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc line)
523{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000524 if (left->getType().getQualifier() == EvqConst && right->getType().getQualifier() == EvqConst) {
525 return right;
526 } else {
527 TIntermTyped *commaAggregate = growAggregate(left, right, line);
528 commaAggregate->getAsAggregate()->setOperator(EOpComma);
529 commaAggregate->setType(right->getType());
530 commaAggregate->getTypePointer()->changeQualifier(EvqTemporary);
531 return commaAggregate;
532 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000533}
534
535//
536// For "?:" test nodes. There are three children; a condition,
537// a true path, and a false path. The two paths are specified
538// as separate parameters.
539//
540// Returns the selection node created, or 0 if one could not be.
541//
542TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, TSourceLoc line)
543{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000544 //
545 // Get compatible types.
546 //
547 TIntermTyped* child = addConversion(EOpSequence, trueBlock->getType(), falseBlock);
548 if (child)
549 falseBlock = child;
550 else {
551 child = addConversion(EOpSequence, falseBlock->getType(), trueBlock);
552 if (child)
553 trueBlock = child;
554 else
555 return 0;
556 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000557
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000558 //
559 // See if all the operands are constant, then fold it otherwise not.
560 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000561
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000562 if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) {
563 if (cond->getAsConstantUnion()->getUnionArrayPointer()->getBConst())
564 return trueBlock;
565 else
566 return falseBlock;
567 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000568
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000569 //
570 // Make a selection node.
571 //
572 TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
573 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000574
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000575 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000576}
577
578//
579// Constant terminal nodes. Has a union that contains bool, float or int constants
580//
581// Returns the constant union node created.
582//
583
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000584TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, TSourceLoc line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000585{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000586 TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t);
587 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000588
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000589 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000590}
591
592TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, TSourceLoc line)
593{
594
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000595 TIntermAggregate* node = new TIntermAggregate(EOpSequence);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000596
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000597 node->setLine(line);
598 TIntermConstantUnion* constIntNode;
599 TIntermSequence &sequenceVector = node->getSequence();
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000600 ConstantUnion* unionArray;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000601
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000602 for (int i = 0; i < fields.num; i++) {
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000603 unionArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000604 unionArray->setIConst(fields.offsets[i]);
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000605 constIntNode = addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), line);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000606 sequenceVector.push_back(constIntNode);
607 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000608
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000609 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000610}
611
612//
613// Create loop nodes.
614//
615TIntermNode* TIntermediate::addLoop(TIntermNode *init, TIntermNode* body, TIntermTyped* test, TIntermTyped* terminal, bool testFirst, TSourceLoc line)
616{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000617 TIntermNode* node = new TIntermLoop(init, body, test, terminal, testFirst);
618 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000619
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000620 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000621}
622
623//
624// Add branches.
625//
626TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TSourceLoc line)
627{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000628 return addBranch(branchOp, 0, line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000629}
630
631TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, TSourceLoc line)
632{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000633 TIntermBranch* node = new TIntermBranch(branchOp, expression);
634 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000635
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000636 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000637}
638
639//
640// This is to be executed once the final root is put on top by the parsing
641// process.
642//
643bool TIntermediate::postProcess(TIntermNode* root, EShLanguage language)
644{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000645 if (root == 0)
646 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000647
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000648 //
649 // First, finish off the top level sequence, if any
650 //
651 TIntermAggregate* aggRoot = root->getAsAggregate();
652 if (aggRoot && aggRoot->getOp() == EOpNull)
653 aggRoot->setOperator(EOpSequence);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000654
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000655 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000656}
657
658//
659// This deletes the tree.
660//
661void TIntermediate::remove(TIntermNode* root)
662{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000663 if (root)
664 RemoveAllTreeNodes(root);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000665}
666
667////////////////////////////////////////////////////////////////
668//
669// Member functions of the nodes used for building the tree.
670//
671////////////////////////////////////////////////////////////////
672
673//
674// Say whether or not an operation node changes the value of a variable.
675//
676// Returns true if state is modified.
677//
678bool TIntermOperator::modifiesState() const
679{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000680 switch (op) {
681 case EOpPostIncrement:
682 case EOpPostDecrement:
683 case EOpPreIncrement:
684 case EOpPreDecrement:
685 case EOpAssign:
686 case EOpAddAssign:
687 case EOpSubAssign:
688 case EOpMulAssign:
689 case EOpVectorTimesMatrixAssign:
690 case EOpVectorTimesScalarAssign:
691 case EOpMatrixTimesScalarAssign:
692 case EOpMatrixTimesMatrixAssign:
693 case EOpDivAssign:
694 return true;
695 default:
696 return false;
697 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000698}
699
700//
701// returns true if the operator is for one of the constructors
702//
703bool TIntermOperator::isConstructor() const
704{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000705 switch (op) {
706 case EOpConstructVec2:
707 case EOpConstructVec3:
708 case EOpConstructVec4:
709 case EOpConstructMat2:
710 case EOpConstructMat3:
711 case EOpConstructMat4:
712 case EOpConstructFloat:
713 case EOpConstructIVec2:
714 case EOpConstructIVec3:
715 case EOpConstructIVec4:
716 case EOpConstructInt:
717 case EOpConstructBVec2:
718 case EOpConstructBVec3:
719 case EOpConstructBVec4:
720 case EOpConstructBool:
721 case EOpConstructStruct:
722 return true;
723 default:
724 return false;
725 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000726}
727//
728// Make sure the type of a unary operator is appropriate for its
729// combination of operation and operand type.
730//
731// Returns false in nothing makes sense.
732//
733bool TIntermUnary::promote(TInfoSink&)
734{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000735 switch (op) {
736 case EOpLogicalNot:
737 if (operand->getBasicType() != EbtBool)
738 return false;
739 break;
740 case EOpNegative:
741 case EOpPostIncrement:
742 case EOpPostDecrement:
743 case EOpPreIncrement:
744 case EOpPreDecrement:
745 if (operand->getBasicType() == EbtBool)
746 return false;
747 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000748
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000749 // operators for built-ins are already type checked against their prototype
750 case EOpAny:
751 case EOpAll:
752 case EOpVectorLogicalNot:
753 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000754
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000755 default:
756 if (operand->getBasicType() != EbtFloat)
757 return false;
758 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000759
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000760 setType(operand->getType());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000761
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000762 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000763}
764
765//
766// Establishes the type of the resultant operation, as well as
767// makes the operator the correct one for the operands.
768//
769// Returns false if operator can't work on operands.
770//
771bool TIntermBinary::promote(TInfoSink& infoSink)
772{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000773 int size = left->getNominalSize();
774 if (right->getNominalSize() > size)
775 size = right->getNominalSize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000776
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000777 TBasicType type = left->getBasicType();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000778
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000779 //
780 // Arrays have to be exact matches.
781 //
782 if ((left->isArray() || right->isArray()) && (left->getType() != right->getType()))
783 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000784
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000785 //
786 // Base assumption: just make the type the same as the left
787 // operand. Then only deviations from this need be coded.
788 //
daniel@transgaming.comfe565152010-04-10 05:29:07 +0000789 setType(left->getType());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000790
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000791 TPrecision highestPrecision = GetHighestPrecision(left->getPrecision(), right->getPrecision(), infoSink);
792 getTypePointer()->changePrecision(highestPrecision);
793
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000794 //
795 // Array operations.
796 //
797 if (left->isArray()) {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000798
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000799 switch (op) {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000800
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000801 //
802 // Promote to conditional
803 //
804 case EOpEqual:
805 case EOpNotEqual:
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000806 setType(TType(EbtBool, EbpUndefined));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000807 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000808
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000809 //
810 // Set array information.
811 //
812 case EOpAssign:
813 case EOpInitialize:
814 getTypePointer()->setArraySize(left->getType().getArraySize());
815 getTypePointer()->setArrayInformationType(left->getType().getArrayInformationType());
816 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000817
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000818 default:
819 return false;
820 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000821
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000822 return true;
823 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000824
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000825 //
826 // All scalars. Code after this test assumes this case is removed!
827 //
828 if (size == 1) {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000829
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000830 switch (op) {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000831
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000832 //
833 // Promote to conditional
834 //
835 case EOpEqual:
836 case EOpNotEqual:
837 case EOpLessThan:
838 case EOpGreaterThan:
839 case EOpLessThanEqual:
840 case EOpGreaterThanEqual:
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000841 setType(TType(EbtBool, EbpUndefined));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000842 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000843
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000844 //
845 // And and Or operate on conditionals
846 //
847 case EOpLogicalAnd:
848 case EOpLogicalOr:
849 if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool)
850 return false;
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000851 setType(TType(EbtBool, EbpUndefined));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000852 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000853
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000854 //
855 // Everything else should have matching types
856 //
857 default:
858 if (left->getBasicType() != right->getBasicType() ||
859 left->isMatrix() != right->isMatrix())
860 return false;
861 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000862
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000863 return true;
864 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000865
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000866 //
867 // Are the sizes compatible?
868 //
869 if ( left->getNominalSize() != size && left->getNominalSize() != 1 ||
870 right->getNominalSize() != size && right->getNominalSize() != 1)
871 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000872
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000873 //
874 // Can these two operands be combined?
875 //
876 switch (op) {
877 case EOpMul:
878 if (!left->isMatrix() && right->isMatrix()) {
879 if (left->isVector())
880 op = EOpVectorTimesMatrix;
881 else {
882 op = EOpMatrixTimesScalar;
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000883 setType(TType(type, highestPrecision, EvqTemporary, size, true));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000884 }
885 } else if (left->isMatrix() && !right->isMatrix()) {
886 if (right->isVector()) {
887 op = EOpMatrixTimesVector;
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000888 setType(TType(type, highestPrecision, EvqTemporary, size, false));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000889 } else {
890 op = EOpMatrixTimesScalar;
891 }
892 } else if (left->isMatrix() && right->isMatrix()) {
893 op = EOpMatrixTimesMatrix;
894 } else if (!left->isMatrix() && !right->isMatrix()) {
895 if (left->isVector() && right->isVector()) {
896 // leave as component product
897 } else if (left->isVector() || right->isVector()) {
898 op = EOpVectorTimesScalar;
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000899 setType(TType(type, highestPrecision, EvqTemporary, size, false));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000900 }
901 } else {
902 infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
903 return false;
904 }
905 break;
906 case EOpMulAssign:
907 if (!left->isMatrix() && right->isMatrix()) {
908 if (left->isVector())
909 op = EOpVectorTimesMatrixAssign;
910 else {
911 return false;
912 }
913 } else if (left->isMatrix() && !right->isMatrix()) {
914 if (right->isVector()) {
915 return false;
916 } else {
917 op = EOpMatrixTimesScalarAssign;
918 }
919 } else if (left->isMatrix() && right->isMatrix()) {
920 op = EOpMatrixTimesMatrixAssign;
921 } else if (!left->isMatrix() && !right->isMatrix()) {
922 if (left->isVector() && right->isVector()) {
923 // leave as component product
924 } else if (left->isVector() || right->isVector()) {
925 if (! left->isVector())
926 return false;
927 op = EOpVectorTimesScalarAssign;
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000928 setType(TType(type, highestPrecision, EvqTemporary, size, false));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000929 }
930 } else {
931 infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
932 return false;
933 }
934 break;
935 case EOpAssign:
936 case EOpInitialize:
937 if (left->getNominalSize() != right->getNominalSize())
938 return false;
939 // fall through
940 case EOpAdd:
941 case EOpSub:
942 case EOpDiv:
943 case EOpAddAssign:
944 case EOpSubAssign:
945 case EOpDivAssign:
946 if (left->isMatrix() && right->isVector() ||
947 left->isVector() && right->isMatrix() ||
948 left->getBasicType() != right->getBasicType())
949 return false;
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000950 setType(TType(type, highestPrecision, EvqTemporary, size, left->isMatrix() || right->isMatrix()));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000951 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000952
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000953 case EOpEqual:
954 case EOpNotEqual:
955 case EOpLessThan:
956 case EOpGreaterThan:
957 case EOpLessThanEqual:
958 case EOpGreaterThanEqual:
959 if (left->isMatrix() && right->isVector() ||
960 left->isVector() && right->isMatrix() ||
961 left->getBasicType() != right->getBasicType())
962 return false;
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000963 setType(TType(EbtBool, EbpUndefined));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000964 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000965
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000966 default:
967 return false;
968 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000969
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000970 //
971 // One more check for assignment. The Resulting type has to match the left operand.
972 //
973 switch (op) {
974 case EOpAssign:
975 case EOpInitialize:
976 case EOpAddAssign:
977 case EOpSubAssign:
978 case EOpMulAssign:
979 case EOpDivAssign:
980 if (getType() != left->getType())
981 return false;
982 break;
983 default:
984 break;
985 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000986
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000987 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000988}
989
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000990bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000991{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000992 TTypeList* fields = leftNodeType.getStruct();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000993
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000994 size_t structSize = fields->size();
995 int index = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000996
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000997 for (size_t j = 0; j < structSize; j++) {
998 int size = (*fields)[j].type->getObjectSize();
999 for (int i = 0; i < size; i++) {
1000 if ((*fields)[j].type->getBasicType() == EbtStruct) {
1001 if (!CompareStructure(*(*fields)[j].type, &rightUnionArray[index], &leftUnionArray[index]))
1002 return false;
1003 } else {
1004 if (leftUnionArray[index] != rightUnionArray[index])
1005 return false;
1006 index++;
1007 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001008
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001009 }
1010 }
1011 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001012}
1013
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001014bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001015{
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001016 if (leftNodeType.isArray()) {
1017 TType typeWithoutArrayness = leftNodeType;
1018 typeWithoutArrayness.clearArrayness();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001019
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001020 int arraySize = leftNodeType.getArraySize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001021
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001022 for (int i = 0; i < arraySize; ++i) {
1023 int offset = typeWithoutArrayness.getObjectSize() * i;
1024 if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset]))
1025 return false;
1026 }
1027 } else
1028 return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001029
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001030 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001031}
1032
1033//
1034// The fold functions see if an operation on a constant can be done in place,
1035// without generating run-time code.
1036//
1037// Returns the node to keep using, which may or may not be the node passed in.
1038//
1039
1040TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink)
1041{
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001042 ConstantUnion *unionArray = getUnionArrayPointer();
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001043 int objectSize = getType().getObjectSize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001044
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001045 if (constantNode) { // binary operations
1046 TIntermConstantUnion *node = constantNode->getAsConstantUnion();
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001047 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001048 TType returnType = getType();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001049
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001050 // for a case like float f = 1.2 + vec4(2,3,4,5);
1051 if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) {
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001052 rightUnionArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001053 for (int i = 0; i < objectSize; ++i)
1054 rightUnionArray[i] = *node->getUnionArrayPointer();
1055 returnType = getType();
1056 } else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) {
1057 // for a case like float f = vec4(2,3,4,5) + 1.2;
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001058 unionArray = new ConstantUnion[constantNode->getType().getObjectSize()];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001059 for (int i = 0; i < constantNode->getType().getObjectSize(); ++i)
1060 unionArray[i] = *getUnionArrayPointer();
1061 returnType = node->getType();
1062 objectSize = constantNode->getType().getObjectSize();
1063 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001064
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001065 ConstantUnion* tempConstArray = 0;
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001066 TIntermConstantUnion *tempNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001067
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001068 bool boolNodeFlag = false;
1069 switch(op) {
1070 case EOpAdd:
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001071 tempConstArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001072 {// support MSVC++6.0
1073 for (int i = 0; i < objectSize; i++)
1074 tempConstArray[i] = unionArray[i] + rightUnionArray[i];
1075 }
1076 break;
1077 case EOpSub:
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001078 tempConstArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001079 {// support MSVC++6.0
1080 for (int i = 0; i < objectSize; i++)
1081 tempConstArray[i] = unionArray[i] - rightUnionArray[i];
1082 }
1083 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001084
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001085 case EOpMul:
1086 case EOpVectorTimesScalar:
1087 case EOpMatrixTimesScalar:
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001088 tempConstArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001089 {// support MSVC++6.0
1090 for (int i = 0; i < objectSize; i++)
1091 tempConstArray[i] = unionArray[i] * rightUnionArray[i];
1092 }
1093 break;
1094 case EOpMatrixTimesMatrix:
1095 if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat) {
1096 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
1097 return 0;
1098 }
1099 {// support MSVC++6.0
1100 int size = getNominalSize();
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001101 tempConstArray = new ConstantUnion[size*size];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001102 for (int row = 0; row < size; row++) {
1103 for (int column = 0; column < size; column++) {
1104 tempConstArray[size * column + row].setFConst(0.0f);
1105 for (int i = 0; i < size; i++) {
1106 tempConstArray[size * column + row].setFConst(tempConstArray[size * column + row].getFConst() + unionArray[i * size + row].getFConst() * (rightUnionArray[column * size + i].getFConst()));
1107 }
1108 }
1109 }
1110 }
1111 break;
1112 case EOpDiv:
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001113 tempConstArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001114 {// support MSVC++6.0
1115 for (int i = 0; i < objectSize; i++) {
1116 switch (getType().getBasicType()) {
1117 case EbtFloat:
1118 if (rightUnionArray[i] == 0.0f) {
1119 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1120 tempConstArray[i].setFConst(FLT_MAX);
1121 } else
1122 tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst());
1123 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001124
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001125 case EbtInt:
1126 if (rightUnionArray[i] == 0) {
1127 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1128 tempConstArray[i].setIConst(INT_MAX);
1129 } else
1130 tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst());
1131 break;
1132 default:
1133 infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"/\"", getLine());
1134 return 0;
1135 }
1136 }
1137 }
1138 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001139
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001140 case EOpMatrixTimesVector:
1141 if (node->getBasicType() != EbtFloat) {
1142 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix times vector", getLine());
1143 return 0;
1144 }
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001145 tempConstArray = new ConstantUnion[getNominalSize()];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001146
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001147 {// support MSVC++6.0
1148 for (int size = getNominalSize(), i = 0; i < size; i++) {
1149 tempConstArray[i].setFConst(0.0f);
1150 for (int j = 0; j < size; j++) {
1151 tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j*size + i].getFConst()) * rightUnionArray[j].getFConst()));
1152 }
1153 }
1154 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001155
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001156 tempNode = new TIntermConstantUnion(tempConstArray, node->getType());
1157 tempNode->setLine(getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001158
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001159 return tempNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001160
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001161 case EOpVectorTimesMatrix:
1162 if (getType().getBasicType() != EbtFloat) {
1163 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for vector times matrix", getLine());
1164 return 0;
1165 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001166
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001167 tempConstArray = new ConstantUnion[getNominalSize()];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001168 {// support MSVC++6.0
1169 for (int size = getNominalSize(), i = 0; i < size; i++) {
1170 tempConstArray[i].setFConst(0.0f);
1171 for (int j = 0; j < size; j++) {
1172 tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j].getFConst()) * rightUnionArray[i*size + j].getFConst()));
1173 }
1174 }
1175 }
1176 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001177
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001178 case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001179 tempConstArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001180 {// support MSVC++6.0
1181 for (int i = 0; i < objectSize; i++)
1182 tempConstArray[i] = unionArray[i] && rightUnionArray[i];
1183 }
1184 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001185
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001186 case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001187 tempConstArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001188 {// support MSVC++6.0
1189 for (int i = 0; i < objectSize; i++)
1190 tempConstArray[i] = unionArray[i] || rightUnionArray[i];
1191 }
1192 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001193
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001194 case EOpLogicalXor:
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001195 tempConstArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001196 {// support MSVC++6.0
1197 for (int i = 0; i < objectSize; i++)
1198 switch (getType().getBasicType()) {
1199 case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break;
1200 default: assert(false && "Default missing");
1201 }
1202 }
1203 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001204
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001205 case EOpLessThan:
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 EOpGreaterThan:
1212 assert(objectSize == 1);
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001213 tempConstArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001214 tempConstArray->setBConst(*unionArray > *rightUnionArray);
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001215 returnType = TType(EbtBool, EbpUndefined, EvqConst);
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001216 break;
1217 case EOpLessThanEqual:
1218 {
1219 assert(objectSize == 1);
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001220 ConstantUnion constant;
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001221 constant.setBConst(*unionArray > *rightUnionArray);
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001222 tempConstArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001223 tempConstArray->setBConst(!constant.getBConst());
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001224 returnType = TType(EbtBool, EbpUndefined, EvqConst);
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001225 break;
1226 }
1227 case EOpGreaterThanEqual:
1228 {
1229 assert(objectSize == 1);
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001230 ConstantUnion constant;
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001231 constant.setBConst(*unionArray < *rightUnionArray);
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001232 tempConstArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001233 tempConstArray->setBConst(!constant.getBConst());
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001234 returnType = TType(EbtBool, EbpUndefined, EvqConst);
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001235 break;
1236 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001237
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001238 case EOpEqual:
1239 if (getType().getBasicType() == EbtStruct) {
1240 if (!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
1241 boolNodeFlag = true;
1242 } else {
1243 for (int i = 0; i < objectSize; i++) {
1244 if (unionArray[i] != rightUnionArray[i]) {
1245 boolNodeFlag = true;
1246 break; // break out of for loop
1247 }
1248 }
1249 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001250
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001251 tempConstArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001252 if (!boolNodeFlag) {
1253 tempConstArray->setBConst(true);
1254 }
1255 else {
1256 tempConstArray->setBConst(false);
1257 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001258
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001259 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001260 tempNode->setLine(getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001261
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001262 return tempNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001263
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001264 case EOpNotEqual:
1265 if (getType().getBasicType() == EbtStruct) {
1266 if (CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
1267 boolNodeFlag = true;
1268 } else {
1269 for (int i = 0; i < objectSize; i++) {
1270 if (unionArray[i] == rightUnionArray[i]) {
1271 boolNodeFlag = true;
1272 break; // break out of for loop
1273 }
1274 }
1275 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001276
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001277 tempConstArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001278 if (!boolNodeFlag) {
1279 tempConstArray->setBConst(true);
1280 }
1281 else {
1282 tempConstArray->setBConst(false);
1283 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001284
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001285 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001286 tempNode->setLine(getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001287
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001288 return tempNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001289
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001290 default:
1291 infoSink.info.message(EPrefixInternalError, "Invalid operator for constant folding", getLine());
1292 return 0;
1293 }
1294 tempNode = new TIntermConstantUnion(tempConstArray, returnType);
1295 tempNode->setLine(getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001296
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001297 return tempNode;
1298 } else {
1299 //
1300 // Do unary operations
1301 //
1302 TIntermConstantUnion *newNode = 0;
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001303 ConstantUnion* tempConstArray = new ConstantUnion[objectSize];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001304 for (int i = 0; i < objectSize; i++) {
1305 switch(op) {
1306 case EOpNegative:
1307 switch (getType().getBasicType()) {
1308 case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break;
1309 case EbtInt: tempConstArray[i].setIConst(-unionArray[i].getIConst()); break;
1310 default:
1311 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1312 return 0;
1313 }
1314 break;
1315 case EOpLogicalNot: // this code is written for possible future use, will not get executed currently
1316 switch (getType().getBasicType()) {
1317 case EbtBool: tempConstArray[i].setBConst(!unionArray[i].getBConst()); break;
1318 default:
1319 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1320 return 0;
1321 }
1322 break;
1323 default:
1324 return 0;
1325 }
1326 }
1327 newNode = new TIntermConstantUnion(tempConstArray, getType());
1328 newNode->setLine(getLine());
1329 return newNode;
1330 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001331
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001332 return this;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001333}
1334
1335TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node)
1336{
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001337 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001338 int size = node->getType().getObjectSize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001339
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001340 ConstantUnion *leftUnionArray = new ConstantUnion[size];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001341
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001342 for (int i=0; i < size; i++) {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001343
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001344 switch (promoteTo) {
1345 case EbtFloat:
1346 switch (node->getType().getBasicType()) {
1347 case EbtInt:
1348 leftUnionArray[i].setFConst(static_cast<float>(rightUnionArray[i].getIConst()));
1349 break;
1350 case EbtBool:
1351 leftUnionArray[i].setFConst(static_cast<float>(rightUnionArray[i].getBConst()));
1352 break;
1353 case EbtFloat:
1354 leftUnionArray[i] = rightUnionArray[i];
1355 break;
1356 default:
1357 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1358 return 0;
1359 }
1360 break;
1361 case EbtInt:
1362 switch (node->getType().getBasicType()) {
1363 case EbtInt:
1364 leftUnionArray[i] = rightUnionArray[i];
1365 break;
1366 case EbtBool:
1367 leftUnionArray[i].setIConst(static_cast<int>(rightUnionArray[i].getBConst()));
1368 break;
1369 case EbtFloat:
1370 leftUnionArray[i].setIConst(static_cast<int>(rightUnionArray[i].getFConst()));
1371 break;
1372 default:
1373 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1374 return 0;
1375 }
1376 break;
1377 case EbtBool:
1378 switch (node->getType().getBasicType()) {
1379 case EbtInt:
1380 leftUnionArray[i].setBConst(rightUnionArray[i].getIConst() != 0);
1381 break;
1382 case EbtBool:
1383 leftUnionArray[i] = rightUnionArray[i];
1384 break;
1385 case EbtFloat:
1386 leftUnionArray[i].setBConst(rightUnionArray[i].getFConst() != 0.0f);
1387 break;
1388 default:
1389 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1390 return 0;
1391 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001392
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001393 break;
1394 default:
1395 infoSink.info.message(EPrefixInternalError, "Incorrect data type found", node->getLine());
1396 return 0;
1397 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001398
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001399 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001400
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001401 const TType& t = node->getType();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001402
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001403 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 +00001404}
1405
1406void TIntermAggregate::addToPragmaTable(const TPragmaTable& pTable)
1407{
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001408 assert(!pragmaTable);
1409 pragmaTable = new TPragmaTable();
1410 *pragmaTable = pTable;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001411}