1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 //
16 // Build the intermediate representation.
17 //
18
19 #include <float.h>
20 #include <limits.h>
21 #include <algorithm>
22
23 #include "localintermediate.h"
24 #include "SymbolTable.h"
25 #include "Common/Math.hpp"
26
27 bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray);
28
GetHigherPrecision(TPrecision left,TPrecision right)29 static TPrecision GetHigherPrecision( TPrecision left, TPrecision right ){
30 return left > right ? left : right;
31 }
32
ValidateMultiplication(TOperator op,const TType & left,const TType & right)33 static bool ValidateMultiplication(TOperator op, const TType &left, const TType &right)
34 {
35 switch(op)
36 {
37 case EOpMul:
38 case EOpMulAssign:
39 return left.getNominalSize() == right.getNominalSize() &&
40 left.getSecondarySize() == right.getSecondarySize();
41 case EOpVectorTimesScalar:
42 case EOpVectorTimesScalarAssign:
43 return true;
44 case EOpVectorTimesMatrix:
45 return left.getNominalSize() == right.getSecondarySize();
46 case EOpVectorTimesMatrixAssign:
47 return left.getNominalSize() == right.getSecondarySize() &&
48 left.getNominalSize() == right.getNominalSize();
49 case EOpMatrixTimesVector:
50 return left.getNominalSize() == right.getNominalSize();
51 case EOpMatrixTimesScalar:
52 case EOpMatrixTimesScalarAssign:
53 return true;
54 case EOpMatrixTimesMatrix:
55 return left.getNominalSize() == right.getSecondarySize();
56 case EOpMatrixTimesMatrixAssign:
57 return left.getNominalSize() == right.getNominalSize() &&
58 left.getSecondarySize() == right.getSecondarySize();
59 default:
60 UNREACHABLE(op);
61 return false;
62 }
63 }
64
getOperatorString(TOperator op)65 const char* getOperatorString(TOperator op) {
66 switch (op) {
67 case EOpInitialize: return "=";
68 case EOpAssign: return "=";
69 case EOpAddAssign: return "+=";
70 case EOpSubAssign: return "-=";
71 case EOpDivAssign: return "/=";
72 case EOpIModAssign: return "%=";
73 case EOpBitShiftLeftAssign: return "<<=";
74 case EOpBitShiftRightAssign: return ">>=";
75 case EOpBitwiseAndAssign: return "&=";
76 case EOpBitwiseXorAssign: return "^=";
77 case EOpBitwiseOrAssign: return "|=";
78
79 // Fall-through.
80 case EOpMulAssign:
81 case EOpVectorTimesMatrixAssign:
82 case EOpVectorTimesScalarAssign:
83 case EOpMatrixTimesScalarAssign:
84 case EOpMatrixTimesMatrixAssign: return "*=";
85
86 // Fall-through.
87 case EOpIndexDirect:
88 case EOpIndexIndirect: return "[]";
89
90 case EOpIndexDirectStruct: return ".";
91 case EOpVectorSwizzle: return ".";
92 case EOpAdd: return "+";
93 case EOpSub: return "-";
94 case EOpMul: return "*";
95 case EOpDiv: return "/";
96 case EOpMod: UNIMPLEMENTED(); break;
97 case EOpEqual: return "==";
98 case EOpNotEqual: return "!=";
99 case EOpLessThan: return "<";
100 case EOpGreaterThan: return ">";
101 case EOpLessThanEqual: return "<=";
102 case EOpGreaterThanEqual: return ">=";
103
104 // Fall-through.
105 case EOpVectorTimesScalar:
106 case EOpVectorTimesMatrix:
107 case EOpMatrixTimesVector:
108 case EOpMatrixTimesScalar:
109 case EOpMatrixTimesMatrix: return "*";
110
111 case EOpLogicalOr: return "||";
112 case EOpLogicalXor: return "^^";
113 case EOpLogicalAnd: return "&&";
114 case EOpIMod: return "%";
115 case EOpBitShiftLeft: return "<<";
116 case EOpBitShiftRight: return ">>";
117 case EOpBitwiseAnd: return "&";
118 case EOpBitwiseXor: return "^";
119 case EOpBitwiseOr: return "|";
120 case EOpNegative: return "-";
121 case EOpVectorLogicalNot: return "not";
122 case EOpLogicalNot: return "!";
123 case EOpBitwiseNot: return "~";
124 case EOpPostIncrement: return "++";
125 case EOpPostDecrement: return "--";
126 case EOpPreIncrement: return "++";
127 case EOpPreDecrement: return "--";
128
129 case EOpRadians: return "radians";
130 case EOpDegrees: return "degrees";
131 case EOpSin: return "sin";
132 case EOpCos: return "cos";
133 case EOpTan: return "tan";
134 case EOpAsin: return "asin";
135 case EOpAcos: return "acos";
136 case EOpAtan: return "atan";
137 case EOpSinh: return "sinh";
138 case EOpCosh: return "cosh";
139 case EOpTanh: return "tanh";
140 case EOpAsinh: return "asinh";
141 case EOpAcosh: return "acosh";
142 case EOpAtanh: return "atanh";
143 case EOpExp: return "exp";
144 case EOpLog: return "log";
145 case EOpExp2: return "exp2";
146 case EOpLog2: return "log2";
147 case EOpSqrt: return "sqrt";
148 case EOpInverseSqrt: return "inversesqrt";
149 case EOpAbs: return "abs";
150 case EOpSign: return "sign";
151 case EOpFloor: return "floor";
152 case EOpTrunc: return "trunc";
153 case EOpRound: return "round";
154 case EOpRoundEven: return "roundEven";
155 case EOpCeil: return "ceil";
156 case EOpFract: return "fract";
157 case EOpLength: return "length";
158 case EOpNormalize: return "normalize";
159 case EOpDFdx: return "dFdx";
160 case EOpDFdy: return "dFdy";
161 case EOpFwidth: return "fwidth";
162 case EOpAny: return "any";
163 case EOpAll: return "all";
164 case EOpIsNan: return "isnan";
165 case EOpIsInf: return "isinf";
166 case EOpOuterProduct: return "outerProduct";
167 case EOpTranspose: return "transpose";
168 case EOpDeterminant: return "determinant";
169 case EOpInverse: return "inverse";
170
171 default: break;
172 }
173 return "";
174 }
175
176 ////////////////////////////////////////////////////////////////////////////
177 //
178 // First set of functions are to help build the intermediate representation.
179 // These functions are not member functions of the nodes.
180 // They are called from parser productions.
181 //
182 /////////////////////////////////////////////////////////////////////////////
183
184 //
185 // Add a terminal node for an identifier in an expression.
186 //
187 // Returns the added node.
188 //
addSymbol(int id,const TString & name,const TType & type,const TSourceLoc & line)189 TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const TSourceLoc &line)
190 {
191 TIntermSymbol* node = new TIntermSymbol(id, name, type);
192 node->setLine(line);
193
194 return node;
195 }
196
197 //
198 // Connect two nodes with a new parent that does a binary operation on the nodes.
199 //
200 // Returns the added node.
201 //
addBinaryMath(TOperator op,TIntermTyped * left,TIntermTyped * right,const TSourceLoc & line)202 TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc &line)
203 {
204 bool isBitShift = false;
205 switch (op) {
206 case EOpEqual:
207 case EOpNotEqual:
208 if (left->isArray())
209 return 0;
210 break;
211 case EOpLessThan:
212 case EOpGreaterThan:
213 case EOpLessThanEqual:
214 case EOpGreaterThanEqual:
215 if (left->isMatrix() || left->isArray() || left->isVector() || left->getBasicType() == EbtStruct) {
216 return 0;
217 }
218 break;
219 case EOpLogicalOr:
220 case EOpLogicalXor:
221 case EOpLogicalAnd:
222 if (left->getBasicType() != EbtBool || left->isMatrix() || left->isArray() || left->isVector()) {
223 return 0;
224 }
225 break;
226 case EOpBitwiseOr:
227 case EOpBitwiseXor:
228 case EOpBitwiseAnd:
229 if (!IsInteger(left->getBasicType()) || left->isMatrix() || left->isArray()) {
230 return 0;
231 }
232 break;
233 case EOpAdd:
234 case EOpSub:
235 case EOpDiv:
236 case EOpMul:
237 if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool) {
238 return 0;
239 }
240 break;
241 case EOpIMod:
242 // Note that this is only for the % operator, not for mod()
243 if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat) {
244 return 0;
245 }
246 break;
247 case EOpBitShiftLeft:
248 case EOpBitShiftRight:
249 case EOpBitShiftLeftAssign:
250 case EOpBitShiftRightAssign:
251 // Unsigned can be bit-shifted by signed and vice versa, but we need to
252 // check that the basic type is an integer type.
253 isBitShift = true;
254 if(!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType()))
255 {
256 return 0;
257 }
258 break;
259 default: break;
260 }
261
262 if(!isBitShift && left->getBasicType() != right->getBasicType())
263 {
264 return 0;
265 }
266
267 //
268 // Need a new node holding things together then. Make
269 // one and promote it to the right type.
270 //
271 TIntermBinary* node = new TIntermBinary(op);
272 node->setLine(line);
273
274 node->setLeft(left);
275 node->setRight(right);
276 if (!node->promote(infoSink))
277 return 0;
278
279 //
280 // See if we can fold constants.
281 //
282 TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
283 TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
284 if (leftTempConstant && rightTempConstant) {
285 TIntermTyped *typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink);
286
287 if (typedReturnNode)
288 return typedReturnNode;
289 }
290
291 return node;
292 }
293
294 //
295 // Connect two nodes through an assignment.
296 //
297 // Returns the added node.
298 //
addAssign(TOperator op,TIntermTyped * left,TIntermTyped * right,const TSourceLoc & line)299 TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc &line)
300 {
301 if (left->getType().getStruct() || right->getType().getStruct())
302 {
303 if (left->getType() != right->getType())
304 {
305 return 0;
306 }
307 }
308
309 TIntermBinary* node = new TIntermBinary(op);
310 node->setLine(line);
311
312 node->setLeft(left);
313 node->setRight(right);
314 if (! node->promote(infoSink))
315 return 0;
316
317 return node;
318 }
319
320 //
321 // Connect two nodes through an index operator, where the left node is the base
322 // of an array or struct, and the right node is a direct or indirect offset.
323 //
324 // Returns the added node.
325 // The caller should set the type of the returned node.
326 //
addIndex(TOperator op,TIntermTyped * base,TIntermTyped * index,const TSourceLoc & line)327 TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc &line)
328 {
329 TIntermBinary* node = new TIntermBinary(op);
330 node->setLine(line);
331 node->setLeft(base);
332 node->setRight(index);
333
334 // caller should set the type
335
336 return node;
337 }
338
339 //
340 // Add one node as the parent of another that it operates on.
341 //
342 // Returns the added node.
343 //
addUnaryMath(TOperator op,TIntermTyped * child,const TSourceLoc & line,const TType * funcReturnType)344 TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, const TSourceLoc &line, const TType *funcReturnType)
345 {
346 if (child == 0) {
347 infoSink.info.message(EPrefixInternalError, "Bad type in AddUnaryMath", line);
348 return 0;
349 }
350
351 switch (op) {
352 case EOpBitwiseNot:
353 if (!IsInteger(child->getType().getBasicType()) || child->getType().isMatrix() || child->getType().isArray()) {
354 return 0;
355 }
356 break;
357
358 case EOpLogicalNot:
359 if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) {
360 return 0;
361 }
362 break;
363
364 case EOpPostIncrement:
365 case EOpPreIncrement:
366 case EOpPostDecrement:
367 case EOpPreDecrement:
368 case EOpNegative:
369 if (child->getType().getBasicType() == EbtStruct || child->getType().isArray())
370 return 0;
371 default: break;
372 }
373
374 TIntermConstantUnion *childTempConstant = 0;
375 if (child->getAsConstantUnion())
376 childTempConstant = child->getAsConstantUnion();
377
378 //
379 // Make a new node for the operator.
380 //
381 TIntermUnary *node = new TIntermUnary(op);
382 node->setLine(line);
383 node->setOperand(child);
384
385 if (! node->promote(infoSink, funcReturnType))
386 return 0;
387
388 if (childTempConstant) {
389 TIntermTyped* newChild = childTempConstant->fold(op, 0, infoSink);
390
391 if (newChild)
392 return newChild;
393 }
394
395 return node;
396 }
397
398 //
399 // This is the safe way to change the operator on an aggregate, as it
400 // does lots of error checking and fixing. Especially for establishing
401 // a function call's operation on it's set of parameters. Sequences
402 // of instructions are also aggregates, but they just direnctly set
403 // their operator to EOpSequence.
404 //
405 // Returns an aggregate node, which could be the one passed in if
406 // it was already an aggregate but no operator was set.
407 //
setAggregateOperator(TIntermNode * node,TOperator op,const TSourceLoc & line)408 TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TSourceLoc &line)
409 {
410 TIntermAggregate* aggNode;
411
412 //
413 // Make sure we have an aggregate. If not turn it into one.
414 //
415 if (node) {
416 aggNode = node->getAsAggregate();
417 if (aggNode == 0 || aggNode->getOp() != EOpNull) {
418 //
419 // Make an aggregate containing this node.
420 //
421 aggNode = new TIntermAggregate();
422 aggNode->getSequence().push_back(node);
423 }
424 } else
425 aggNode = new TIntermAggregate();
426
427 //
428 // Set the operator.
429 //
430 aggNode->setOp(op);
431
432 return aggNode;
433 }
434
435 //
436 // Safe way to combine two nodes into an aggregate. Works with null pointers,
437 // a node that's not a aggregate yet, etc.
438 //
439 // Returns the resulting aggregate, unless 0 was passed in for
440 // both existing nodes.
441 //
growAggregate(TIntermNode * left,TIntermNode * right,const TSourceLoc & line)442 TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc &line)
443 {
444 if (left == 0 && right == 0)
445 return 0;
446
447 TIntermAggregate* aggNode = 0;
448 if (left)
449 aggNode = left->getAsAggregate();
450 if (!aggNode || aggNode->getOp() != EOpNull) {
451 aggNode = new TIntermAggregate;
452 if (left)
453 aggNode->getSequence().push_back(left);
454 }
455
456 if (right)
457 aggNode->getSequence().push_back(right);
458
459 aggNode->setLine(line);
460
461 return aggNode;
462 }
463
464 //
465 // Turn an existing node into an aggregate.
466 //
467 // Returns an aggregate, unless 0 was passed in for the existing node.
468 //
makeAggregate(TIntermNode * node,const TSourceLoc & line)469 TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, const TSourceLoc &line)
470 {
471 if (node == 0)
472 return 0;
473
474 TIntermAggregate* aggNode = new TIntermAggregate;
475 aggNode->getSequence().push_back(node);
476
477 aggNode->setLine(line);
478
479 return aggNode;
480 }
481
482 //
483 // For "if" test nodes. There are three children; a condition,
484 // a true path, and a false path. The two paths are in the
485 // nodePair.
486 //
487 // Returns the selection node created.
488 //
addSelection(TIntermTyped * cond,TIntermNodePair nodePair,const TSourceLoc & line)489 TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, const TSourceLoc &line)
490 {
491 //
492 // For compile time constant selections, prune the code and
493 // test now.
494 //
495
496 if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion()) {
497 if (cond->getAsConstantUnion()->getBConst(0) == true)
498 return nodePair.node1 ? setAggregateOperator(nodePair.node1, EOpSequence, nodePair.node1->getLine()) : nullptr;
499 else
500 return nodePair.node2 ? setAggregateOperator(nodePair.node2, EOpSequence, nodePair.node2->getLine()) : nullptr;
501 }
502
503 TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2);
504 node->setLine(line);
505
506 return node;
507 }
508
509
addComma(TIntermTyped * left,TIntermTyped * right,const TSourceLoc & line)510 TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc &line)
511 {
512 if (left->getType().getQualifier() == EvqConstExpr && right->getType().getQualifier() == EvqConstExpr) {
513 return right;
514 } else {
515 TIntermTyped *commaAggregate = growAggregate(left, right, line);
516 commaAggregate->getAsAggregate()->setOp(EOpComma);
517 commaAggregate->setType(right->getType());
518 commaAggregate->getTypePointer()->setQualifier(EvqTemporary);
519 return commaAggregate;
520 }
521 }
522
523 //
524 // For "?:" test nodes. There are three children; a condition,
525 // a true path, and a false path. The two paths are specified
526 // as separate parameters.
527 //
528 // Returns the selection node created, or 0 if one could not be.
529 //
addSelection(TIntermTyped * cond,TIntermTyped * trueBlock,TIntermTyped * falseBlock,const TSourceLoc & line)530 TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc &line)
531 {
532 if (trueBlock->getType() != falseBlock->getType())
533 {
534 return 0;
535 }
536
537 //
538 // See if all the operands are constant, then fold it otherwise not.
539 //
540
541 if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) {
542 if (cond->getAsConstantUnion()->getBConst(0))
543 return trueBlock;
544 else
545 return falseBlock;
546 }
547
548 //
549 // Make a selection node.
550 //
551 TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
552 node->getTypePointer()->setQualifier(EvqTemporary);
553 node->setLine(line);
554
555 return node;
556 }
557
addSwitch(TIntermTyped * init,TIntermAggregate * statementList,const TSourceLoc & line)558 TIntermSwitch *TIntermediate::addSwitch(TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &line)
559 {
560 TIntermSwitch *node = new TIntermSwitch(init, statementList);
561 node->setLine(line);
562
563 return node;
564 }
565
addCase(TIntermTyped * condition,const TSourceLoc & line)566 TIntermCase *TIntermediate::addCase(TIntermTyped *condition, const TSourceLoc &line)
567 {
568 TIntermCase *node = new TIntermCase(condition);
569 node->setLine(line);
570
571 return node;
572 }
573
574 //
575 // Constant terminal nodes. Has a union that contains bool, float or int constants
576 //
577 // Returns the constant union node created.
578 //
579
addConstantUnion(ConstantUnion * unionArrayPointer,const TType & t,const TSourceLoc & line)580 TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, const TSourceLoc &line)
581 {
582 TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t);
583 node->setLine(line);
584
585 return node;
586 }
587
addSwizzle(TVectorFields & fields,const TSourceLoc & line)588 TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, const TSourceLoc &line)
589 {
590
591 TIntermAggregate* node = new TIntermAggregate(EOpSequence);
592
593 node->setLine(line);
594 TIntermConstantUnion* constIntNode;
595 TIntermSequence &sequenceVector = node->getSequence();
596 ConstantUnion* unionArray;
597
598 for (int i = 0; i < fields.num; i++) {
599 unionArray = new ConstantUnion[1];
600 unionArray->setIConst(fields.offsets[i]);
601 constIntNode = addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConstExpr), line);
602 sequenceVector.push_back(constIntNode);
603 }
604
605 return node;
606 }
607
608 //
609 // Create loop nodes.
610 //
addLoop(TLoopType type,TIntermNode * init,TIntermTyped * cond,TIntermTyped * expr,TIntermNode * body,const TSourceLoc & line)611 TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTyped* cond, TIntermTyped* expr, TIntermNode* body, const TSourceLoc &line)
612 {
613 TIntermNode* node = new TIntermLoop(type, init, cond, expr, body);
614 node->setLine(line);
615
616 return node;
617 }
618
619 //
620 // Add branches.
621 //
addBranch(TOperator branchOp,const TSourceLoc & line)622 TIntermBranch* TIntermediate::addBranch(TOperator branchOp, const TSourceLoc &line)
623 {
624 return addBranch(branchOp, 0, line);
625 }
626
addBranch(TOperator branchOp,TIntermTyped * expression,const TSourceLoc & line)627 TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, const TSourceLoc &line)
628 {
629 TIntermBranch* node = new TIntermBranch(branchOp, expression);
630 node->setLine(line);
631
632 return node;
633 }
634
635 //
636 // This is to be executed once the final root is put on top by the parsing
637 // process.
638 //
postProcess(TIntermNode * root)639 bool TIntermediate::postProcess(TIntermNode* root)
640 {
641 if (root == 0)
642 return true;
643
644 //
645 // First, finish off the top level sequence, if any
646 //
647 TIntermAggregate* aggRoot = root->getAsAggregate();
648 if (aggRoot && aggRoot->getOp() == EOpNull)
649 aggRoot->setOp(EOpSequence);
650
651 return true;
652 }
653
654 ////////////////////////////////////////////////////////////////
655 //
656 // Member functions of the nodes used for building the tree.
657 //
658 ////////////////////////////////////////////////////////////////
659
660 //
661 // Say whether or not an operation node changes the value of a variable.
662 //
663 // Returns true if state is modified.
664 //
modifiesState() const665 bool TIntermOperator::modifiesState() const
666 {
667 switch (op) {
668 case EOpPostIncrement:
669 case EOpPostDecrement:
670 case EOpPreIncrement:
671 case EOpPreDecrement:
672 case EOpAssign:
673 case EOpAddAssign:
674 case EOpSubAssign:
675 case EOpMulAssign:
676 case EOpVectorTimesMatrixAssign:
677 case EOpVectorTimesScalarAssign:
678 case EOpMatrixTimesScalarAssign:
679 case EOpMatrixTimesMatrixAssign:
680 case EOpDivAssign:
681 case EOpIModAssign:
682 case EOpBitShiftLeftAssign:
683 case EOpBitShiftRightAssign:
684 case EOpBitwiseAndAssign:
685 case EOpBitwiseXorAssign:
686 case EOpBitwiseOrAssign:
687 return true;
688 default:
689 return false;
690 }
691 }
692
693 //
694 // returns true if the operator is for one of the constructors
695 //
isConstructor() const696 bool TIntermOperator::isConstructor() const
697 {
698 switch (op) {
699 case EOpConstructVec2:
700 case EOpConstructVec3:
701 case EOpConstructVec4:
702 case EOpConstructMat2:
703 case EOpConstructMat2x3:
704 case EOpConstructMat2x4:
705 case EOpConstructMat3x2:
706 case EOpConstructMat3:
707 case EOpConstructMat3x4:
708 case EOpConstructMat4x2:
709 case EOpConstructMat4x3:
710 case EOpConstructMat4:
711 case EOpConstructFloat:
712 case EOpConstructIVec2:
713 case EOpConstructIVec3:
714 case EOpConstructIVec4:
715 case EOpConstructInt:
716 case EOpConstructUVec2:
717 case EOpConstructUVec3:
718 case EOpConstructUVec4:
719 case EOpConstructUInt:
720 case EOpConstructBVec2:
721 case EOpConstructBVec3:
722 case EOpConstructBVec4:
723 case EOpConstructBool:
724 case EOpConstructStruct:
725 return true;
726 default:
727 return false;
728 }
729 }
730
731 //
732 // Make sure the type of a unary operator is appropriate for its
733 // combination of operation and operand type.
734 //
735 // Returns false in nothing makes sense.
736 //
promote(TInfoSink &,const TType * funcReturnType)737 bool TIntermUnary::promote(TInfoSink&, const TType *funcReturnType)
738 {
739 setType(funcReturnType ? *funcReturnType : operand->getType());
740
741 // Unary operations result in temporary variables unless const.
742 if(type.getQualifier() != EvqConstExpr)
743 {
744 type.setQualifier(EvqTemporary);
745 }
746
747 switch (op) {
748 case EOpLogicalNot:
749 if (operand->getBasicType() != EbtBool)
750 return false;
751 break;
752 case EOpBitwiseNot:
753 if (!IsInteger(operand->getBasicType()))
754 return false;
755 break;
756 case EOpNegative:
757 case EOpPostIncrement:
758 case EOpPostDecrement:
759 case EOpPreIncrement:
760 case EOpPreDecrement:
761 if (operand->getBasicType() == EbtBool)
762 return false;
763 break;
764
765 // operators for built-ins are already type checked against their prototype
766 case EOpAny:
767 case EOpAll:
768 case EOpVectorLogicalNot:
769 case EOpAbs:
770 case EOpSign:
771 case EOpIsNan:
772 case EOpIsInf:
773 case EOpFloatBitsToInt:
774 case EOpFloatBitsToUint:
775 case EOpIntBitsToFloat:
776 case EOpUintBitsToFloat:
777 case EOpPackSnorm2x16:
778 case EOpPackUnorm2x16:
779 case EOpPackHalf2x16:
780 case EOpUnpackSnorm2x16:
781 case EOpUnpackUnorm2x16:
782 case EOpUnpackHalf2x16:
783 return true;
784
785 default:
786 if (operand->getBasicType() != EbtFloat)
787 return false;
788 }
789
790 return true;
791 }
792
793 //
794 // Establishes the type of the resultant operation, as well as
795 // makes the operator the correct one for the operands.
796 //
797 // Returns false if operator can't work on operands.
798 //
promote(TInfoSink & infoSink)799 bool TIntermBinary::promote(TInfoSink& infoSink)
800 {
801 ASSERT(left->isArray() == right->isArray());
802
803 // GLSL ES 2.0 does not support implicit type casting.
804 // So the basic type should always match.
805 // GLSL ES 3.0 supports integer shift operands of different signedness.
806 if(op != EOpBitShiftLeft &&
807 op != EOpBitShiftRight &&
808 op != EOpBitShiftLeftAssign &&
809 op != EOpBitShiftRightAssign &&
810 left->getBasicType() != right->getBasicType())
811 {
812 return false;
813 }
814
815 //
816 // Base assumption: just make the type the same as the left
817 // operand. Then only deviations from this need be coded.
818 //
819 setType(left->getType());
820
821 // The result gets promoted to the highest precision.
822 TPrecision higherPrecision = GetHigherPrecision(left->getPrecision(), right->getPrecision());
823 getTypePointer()->setPrecision(higherPrecision);
824
825 // Binary operations results in temporary variables unless both
826 // operands are const.
827 if (left->getQualifier() != EvqConstExpr || right->getQualifier() != EvqConstExpr) {
828 getTypePointer()->setQualifier(EvqTemporary);
829 }
830
831 int primarySize = std::max(left->getNominalSize(), right->getNominalSize());
832
833 //
834 // All scalars. Code after this test assumes this case is removed!
835 //
836 if (primarySize == 1) {
837 switch (op) {
838 //
839 // Promote to conditional
840 //
841 case EOpEqual:
842 case EOpNotEqual:
843 case EOpLessThan:
844 case EOpGreaterThan:
845 case EOpLessThanEqual:
846 case EOpGreaterThanEqual:
847 setType(TType(EbtBool, EbpUndefined));
848 break;
849
850 //
851 // And and Or operate on conditionals
852 //
853 case EOpLogicalAnd:
854 case EOpLogicalOr:
855 case EOpLogicalXor:
856 // Both operands must be of type bool.
857 if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool)
858 return false;
859 setType(TType(EbtBool, EbpUndefined));
860 break;
861
862 default:
863 break;
864 }
865 return true;
866 }
867
868 // If we reach here, at least one of the operands is vector or matrix.
869 // The other operand could be a scalar, vector, or matrix.
870 // Can these two operands be combined?
871 //
872 TBasicType basicType = left->getBasicType();
873 switch (op) {
874 case EOpMul:
875 if (!left->isMatrix() && right->isMatrix()) {
876 if (left->isVector())
877 {
878 op = EOpVectorTimesMatrix;
879 setType(TType(basicType, higherPrecision, EvqTemporary,
880 static_cast<unsigned char>(right->getNominalSize()), 1));
881 }
882 else {
883 op = EOpMatrixTimesScalar;
884 setType(TType(basicType, higherPrecision, EvqTemporary,
885 static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(right->getSecondarySize())));
886 }
887 } else if (left->isMatrix() && !right->isMatrix()) {
888 if (right->isVector()) {
889 op = EOpMatrixTimesVector;
890 setType(TType(basicType, higherPrecision, EvqTemporary,
891 static_cast<unsigned char>(left->getSecondarySize()), 1));
892 } else {
893 op = EOpMatrixTimesScalar;
894 }
895 } else if (left->isMatrix() && right->isMatrix()) {
896 op = EOpMatrixTimesMatrix;
897 setType(TType(basicType, higherPrecision, EvqTemporary,
898 static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(left->getSecondarySize())));
899 } else if (!left->isMatrix() && !right->isMatrix()) {
900 if (left->isVector() && right->isVector()) {
901 // leave as component product
902 } else if (left->isVector() || right->isVector()) {
903 op = EOpVectorTimesScalar;
904 setType(TType(basicType, higherPrecision, EvqTemporary,
905 static_cast<unsigned char>(primarySize), 1));
906 }
907 } else {
908 infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
909 return false;
910 }
911
912 if(!ValidateMultiplication(op, left->getType(), right->getType()))
913 {
914 return false;
915 }
916 break;
917 case EOpMulAssign:
918 if (!left->isMatrix() && right->isMatrix()) {
919 if (left->isVector())
920 op = EOpVectorTimesMatrixAssign;
921 else {
922 return false;
923 }
924 } else if (left->isMatrix() && !right->isMatrix()) {
925 if (right->isVector()) {
926 return false;
927 } else {
928 op = EOpMatrixTimesScalarAssign;
929 }
930 } else if (left->isMatrix() && right->isMatrix()) {
931 op = EOpMatrixTimesMatrixAssign;
932 setType(TType(basicType, higherPrecision, EvqTemporary,
933 static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(left->getSecondarySize())));
934 } else if (!left->isMatrix() && !right->isMatrix()) {
935 if (left->isVector() && right->isVector()) {
936 // leave as component product
937 } else if (left->isVector() || right->isVector()) {
938 if (! left->isVector())
939 return false;
940 op = EOpVectorTimesScalarAssign;
941 setType(TType(basicType, higherPrecision, EvqTemporary,
942 static_cast<unsigned char>(left->getNominalSize()), 1));
943 }
944 } else {
945 infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
946 return false;
947 }
948
949 if(!ValidateMultiplication(op, left->getType(), right->getType()))
950 {
951 return false;
952 }
953 break;
954
955 case EOpAssign:
956 case EOpInitialize:
957 // No more additional checks are needed.
958 if ((left->getNominalSize() != right->getNominalSize()) ||
959 (left->getSecondarySize() != right->getSecondarySize()))
960 return false;
961 break;
962 case EOpAdd:
963 case EOpSub:
964 case EOpDiv:
965 case EOpIMod:
966 case EOpBitShiftLeft:
967 case EOpBitShiftRight:
968 case EOpBitwiseAnd:
969 case EOpBitwiseXor:
970 case EOpBitwiseOr:
971 case EOpAddAssign:
972 case EOpSubAssign:
973 case EOpDivAssign:
974 case EOpIModAssign:
975 case EOpBitShiftLeftAssign:
976 case EOpBitShiftRightAssign:
977 case EOpBitwiseAndAssign:
978 case EOpBitwiseXorAssign:
979 case EOpBitwiseOrAssign:
980 if ((left->isMatrix() && right->isVector()) ||
981 (left->isVector() && right->isMatrix()))
982 return false;
983
984 // Are the sizes compatible?
985 if(left->getNominalSize() != right->getNominalSize() ||
986 left->getSecondarySize() != right->getSecondarySize())
987 {
988 // If the nominal sizes of operands do not match:
989 // One of them must be a scalar.
990 if(!left->isScalar() && !right->isScalar())
991 return false;
992
993 // In the case of compound assignment other than multiply-assign,
994 // the right side needs to be a scalar. Otherwise a vector/matrix
995 // would be assigned to a scalar. A scalar can't be shifted by a
996 // vector either.
997 if(!right->isScalar() && (modifiesState() || op == EOpBitShiftLeft || op == EOpBitShiftRight))
998 return false;
999 }
1000
1001 {
1002 const int secondarySize = std::max(
1003 left->getSecondarySize(), right->getSecondarySize());
1004 setType(TType(basicType, higherPrecision, EvqTemporary,
1005 static_cast<unsigned char>(primarySize), static_cast<unsigned char>(secondarySize)));
1006 if(left->isArray())
1007 {
1008 ASSERT(left->getArraySize() == right->getArraySize());
1009 type.setArraySize(left->getArraySize());
1010 }
1011 }
1012 break;
1013
1014 case EOpEqual:
1015 case EOpNotEqual:
1016 case EOpLessThan:
1017 case EOpGreaterThan:
1018 case EOpLessThanEqual:
1019 case EOpGreaterThanEqual:
1020 if ((left->getNominalSize() != right->getNominalSize()) ||
1021 (left->getSecondarySize() != right->getSecondarySize()))
1022 return false;
1023 setType(TType(EbtBool, EbpUndefined));
1024 break;
1025
1026 case EOpOuterProduct:
1027 if(!left->isVector() || !right->isVector())
1028 return false;
1029 setType(TType(EbtFloat, right->getNominalSize(), left->getNominalSize()));
1030 break;
1031
1032 case EOpTranspose:
1033 if(!right->isMatrix())
1034 return false;
1035 setType(TType(EbtFloat, right->getSecondarySize(), right->getNominalSize()));
1036 break;
1037
1038 case EOpDeterminant:
1039 if(!right->isMatrix())
1040 return false;
1041 setType(TType(EbtFloat));
1042 break;
1043
1044 case EOpInverse:
1045 if(!right->isMatrix() || right->getNominalSize() != right->getSecondarySize())
1046 return false;
1047 setType(right->getType());
1048 break;
1049
1050 default:
1051 return false;
1052 }
1053
1054 return true;
1055 }
1056
CompareStruct(const TType & leftNodeType,ConstantUnion * rightUnionArray,ConstantUnion * leftUnionArray)1057 bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
1058 {
1059 const TFieldList& fields = leftNodeType.getStruct()->fields();
1060
1061 size_t structSize = fields.size();
1062 int index = 0;
1063
1064 for (size_t j = 0; j < structSize; j++) {
1065 size_t size = fields[j]->type()->getObjectSize();
1066 for(size_t i = 0; i < size; i++) {
1067 if (fields[j]->type()->getBasicType() == EbtStruct) {
1068 if (!CompareStructure(*(fields[j]->type()), &rightUnionArray[index], &leftUnionArray[index]))
1069 return false;
1070 } else {
1071 if (leftUnionArray[index] != rightUnionArray[index])
1072 return false;
1073 index++;
1074 }
1075
1076 }
1077 }
1078 return true;
1079 }
1080
CompareStructure(const TType & leftNodeType,ConstantUnion * rightUnionArray,ConstantUnion * leftUnionArray)1081 bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
1082 {
1083 if (leftNodeType.isArray()) {
1084 TType typeWithoutArrayness = leftNodeType;
1085 typeWithoutArrayness.clearArrayness();
1086
1087 int arraySize = leftNodeType.getArraySize();
1088
1089 for (int i = 0; i < arraySize; ++i) {
1090 size_t offset = typeWithoutArrayness.getObjectSize() * i;
1091 if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset]))
1092 return false;
1093 }
1094 } else
1095 return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray);
1096
1097 return true;
1098 }
1099
determinant2(float m00,float m01,float m10,float m11)1100 float determinant2(float m00, float m01, float m10, float m11)
1101 {
1102 return m00 * m11 - m01 * m10;
1103 }
1104
determinant3(float m00,float m01,float m02,float m10,float m11,float m12,float m20,float m21,float m22)1105 float determinant3(float m00, float m01, float m02,
1106 float m10, float m11, float m12,
1107 float m20, float m21, float m22)
1108 {
1109 return m00 * determinant2(m11, m12, m21, m22) -
1110 m10 * determinant2(m01, m02, m21, m22) +
1111 m20 * determinant2(m01, m02, m11, m12);
1112 }
1113
determinant4(float m00,float m01,float m02,float m03,float m10,float m11,float m12,float m13,float m20,float m21,float m22,float m23,float m30,float m31,float m32,float m33)1114 float determinant4(float m00, float m01, float m02, float m03,
1115 float m10, float m11, float m12, float m13,
1116 float m20, float m21, float m22, float m23,
1117 float m30, float m31, float m32, float m33)
1118 {
1119 return m00 * determinant3(m11, m12, m13, m21, m22, m23, m31, m32, m33) -
1120 m10 * determinant3(m01, m02, m03, m21, m22, m23, m31, m32, m33) +
1121 m20 * determinant3(m01, m02, m03, m11, m12, m13, m31, m32, m33) -
1122 m30 * determinant3(m01, m02, m03, m11, m12, m13, m21, m22, m23);
1123 }
1124
ComputeDeterminant(int size,ConstantUnion * unionArray)1125 float ComputeDeterminant(int size, ConstantUnion* unionArray)
1126 {
1127 switch(size)
1128 {
1129 case 2:
1130 return determinant2(unionArray[0].getFConst(),
1131 unionArray[1].getFConst(),
1132 unionArray[2].getFConst(),
1133 unionArray[3].getFConst());
1134 case 3:
1135 return determinant3(unionArray[0].getFConst(),
1136 unionArray[1].getFConst(),
1137 unionArray[2].getFConst(),
1138 unionArray[3].getFConst(),
1139 unionArray[4].getFConst(),
1140 unionArray[5].getFConst(),
1141 unionArray[6].getFConst(),
1142 unionArray[7].getFConst(),
1143 unionArray[8].getFConst());
1144 case 4:
1145 return determinant4(unionArray[0].getFConst(),
1146 unionArray[1].getFConst(),
1147 unionArray[2].getFConst(),
1148 unionArray[3].getFConst(),
1149 unionArray[4].getFConst(),
1150 unionArray[5].getFConst(),
1151 unionArray[6].getFConst(),
1152 unionArray[7].getFConst(),
1153 unionArray[8].getFConst(),
1154 unionArray[9].getFConst(),
1155 unionArray[10].getFConst(),
1156 unionArray[11].getFConst(),
1157 unionArray[12].getFConst(),
1158 unionArray[13].getFConst(),
1159 unionArray[14].getFConst(),
1160 unionArray[15].getFConst());
1161 default:
1162 UNREACHABLE(size);
1163 return 0.0f;
1164 }
1165 }
1166
CreateInverse(TIntermConstantUnion * node,ConstantUnion * unionArray)1167 ConstantUnion* CreateInverse(TIntermConstantUnion* node, ConstantUnion* unionArray)
1168 {
1169 ConstantUnion* tempConstArray = 0;
1170 int size = node->getNominalSize();
1171 float determinant = ComputeDeterminant(size, unionArray);
1172 if(determinant != 0.0f)
1173 {
1174 float invDet = 1.0f / determinant;
1175 tempConstArray = new ConstantUnion[size*size];
1176 switch(size)
1177 {
1178 case 2:
1179 {
1180 float m00 = unionArray[0].getFConst(); // Matrix is:
1181 float m01 = unionArray[1].getFConst(); // (m00, m01)
1182 float m10 = unionArray[2].getFConst(); // (m10, m11)
1183 float m11 = unionArray[3].getFConst();
1184 tempConstArray[0].setFConst( invDet * m11);
1185 tempConstArray[1].setFConst(-invDet * m01);
1186 tempConstArray[2].setFConst(-invDet * m10);
1187 tempConstArray[3].setFConst( invDet * m00);
1188 }
1189 break;
1190 case 3:
1191 {
1192 float m00 = unionArray[0].getFConst(); // Matrix is:
1193 float m01 = unionArray[1].getFConst(); // (m00, m01, m02)
1194 float m02 = unionArray[2].getFConst(); // (m10, m11, m12)
1195 float m10 = unionArray[3].getFConst(); // (m20, m21, m22)
1196 float m11 = unionArray[4].getFConst();
1197 float m12 = unionArray[5].getFConst();
1198 float m20 = unionArray[6].getFConst();
1199 float m21 = unionArray[7].getFConst();
1200 float m22 = unionArray[8].getFConst();
1201 tempConstArray[0].setFConst(invDet * determinant2(m11, m12, m21, m22)); // m00 = invDet * (m11 * m22 - m12 * m21)
1202 tempConstArray[1].setFConst(invDet * determinant2(m12, m10, m22, m20)); // m01 = -invDet * (m10 * m22 - m12 * m20)
1203 tempConstArray[2].setFConst(invDet * determinant2(m10, m11, m20, m21)); // m02 = invDet * (m10 * m21 - m11 * m20)
1204 tempConstArray[3].setFConst(invDet * determinant2(m21, m22, m01, m02)); // m10 = -invDet * (m01 * m22 - m02 * m21)
1205 tempConstArray[4].setFConst(invDet * determinant2(m00, m02, m20, m22)); // m11 = invDet * (m00 * m22 - m02 * m20)
1206 tempConstArray[5].setFConst(invDet * determinant2(m20, m21, m00, m01)); // m12 = -invDet * (m00 * m21 - m01 * m20)
1207 tempConstArray[6].setFConst(invDet * determinant2(m01, m02, m11, m12)); // m20 = invDet * (m01 * m12 - m02 * m11)
1208 tempConstArray[7].setFConst(invDet * determinant2(m10, m12, m00, m02)); // m21 = -invDet * (m00 * m12 - m02 * m10)
1209 tempConstArray[8].setFConst(invDet * determinant2(m00, m01, m10, m11)); // m22 = invDet * (m00 * m11 - m01 * m10)
1210 }
1211 break;
1212 case 4:
1213 {
1214 float m00 = unionArray[0].getFConst(); // Matrix is:
1215 float m01 = unionArray[1].getFConst(); // (m00, m01, m02, m03)
1216 float m02 = unionArray[2].getFConst(); // (m10, m11, m12, m13)
1217 float m03 = unionArray[3].getFConst(); // (m20, m21, m22, m23)
1218 float m10 = unionArray[4].getFConst(); // (m30, m31, m32, m33)
1219 float m11 = unionArray[5].getFConst();
1220 float m12 = unionArray[6].getFConst();
1221 float m13 = unionArray[7].getFConst();
1222 float m20 = unionArray[8].getFConst();
1223 float m21 = unionArray[9].getFConst();
1224 float m22 = unionArray[10].getFConst();
1225 float m23 = unionArray[11].getFConst();
1226 float m30 = unionArray[12].getFConst();
1227 float m31 = unionArray[13].getFConst();
1228 float m32 = unionArray[14].getFConst();
1229 float m33 = unionArray[15].getFConst();
1230 tempConstArray[ 0].setFConst( invDet * determinant3(m11, m12, m13, m21, m22, m23, m31, m32, m33)); // m00
1231 tempConstArray[ 1].setFConst(-invDet * determinant3(m10, m12, m13, m20, m22, m23, m30, m32, m33)); // m01
1232 tempConstArray[ 2].setFConst( invDet * determinant3(m10, m11, m13, m20, m21, m23, m30, m31, m33)); // m02
1233 tempConstArray[ 3].setFConst(-invDet * determinant3(m10, m11, m12, m20, m21, m22, m30, m31, m32)); // m03
1234 tempConstArray[ 4].setFConst( invDet * determinant3(m01, m02, m03, m21, m22, m23, m31, m32, m33)); // m10
1235 tempConstArray[ 5].setFConst(-invDet * determinant3(m00, m02, m03, m20, m22, m23, m30, m32, m33)); // m11
1236 tempConstArray[ 6].setFConst( invDet * determinant3(m00, m01, m03, m20, m21, m23, m30, m31, m33)); // m12
1237 tempConstArray[ 7].setFConst(-invDet * determinant3(m00, m01, m02, m20, m21, m22, m30, m31, m32)); // m13
1238 tempConstArray[ 8].setFConst( invDet * determinant3(m01, m02, m03, m11, m12, m13, m31, m32, m33)); // m20
1239 tempConstArray[ 9].setFConst(-invDet * determinant3(m00, m02, m03, m10, m12, m13, m30, m32, m33)); // m21
1240 tempConstArray[10].setFConst( invDet * determinant3(m00, m01, m03, m10, m11, m13, m30, m31, m33)); // m22
1241 tempConstArray[11].setFConst(-invDet * determinant3(m00, m01, m02, m10, m11, m12, m30, m31, m32)); // m23
1242 tempConstArray[12].setFConst( invDet * determinant3(m01, m02, m03, m11, m12, m13, m21, m22, m23)); // m30
1243 tempConstArray[13].setFConst(-invDet * determinant3(m00, m02, m03, m10, m12, m13, m20, m22, m23)); // m31
1244 tempConstArray[14].setFConst( invDet * determinant3(m00, m01, m03, m10, m11, m13, m20, m21, m23)); // m32
1245 tempConstArray[15].setFConst(-invDet * determinant3(m00, m01, m02, m10, m11, m12, m20, m21, m22)); // m33
1246 }
1247 break;
1248 default:
1249 UNREACHABLE(size);
1250 }
1251 }
1252 return tempConstArray;
1253 }
1254
1255 //
1256 // The fold functions see if an operation on a constant can be done in place,
1257 // without generating run-time code.
1258 //
1259 // Returns the node to keep using, which may or may not be the node passed in.
1260 //
1261
fold(TOperator op,TIntermTyped * constantNode,TInfoSink & infoSink)1262 TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink)
1263 {
1264 ConstantUnion *unionArray = getUnionArrayPointer();
1265 size_t objectSize = getType().getObjectSize();
1266
1267 if (constantNode) { // binary operations
1268 TIntermConstantUnion *node = constantNode->getAsConstantUnion();
1269 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
1270 TType returnType = getType();
1271
1272 // for a case like float f = 1.2 + vec4(2,3,4,5);
1273 if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) {
1274 rightUnionArray = new ConstantUnion[objectSize];
1275 for (size_t i = 0; i < objectSize; ++i)
1276 rightUnionArray[i] = *node->getUnionArrayPointer();
1277 returnType = getType();
1278 } else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) {
1279 // for a case like float f = vec4(2,3,4,5) + 1.2;
1280 unionArray = new ConstantUnion[constantNode->getType().getObjectSize()];
1281 for (size_t i = 0; i < constantNode->getType().getObjectSize(); ++i)
1282 unionArray[i] = *getUnionArrayPointer();
1283 returnType = node->getType();
1284 objectSize = constantNode->getType().getObjectSize();
1285 }
1286
1287 ConstantUnion* tempConstArray = 0;
1288 TIntermConstantUnion *tempNode;
1289
1290 switch(op) {
1291 case EOpAdd:
1292 tempConstArray = new ConstantUnion[objectSize];
1293 {// support MSVC++6.0
1294 for (size_t i = 0; i < objectSize; i++)
1295 tempConstArray[i] = unionArray[i] + rightUnionArray[i];
1296 }
1297 break;
1298 case EOpSub:
1299 tempConstArray = new ConstantUnion[objectSize];
1300 {// support MSVC++6.0
1301 for (size_t i = 0; i < objectSize; i++)
1302 tempConstArray[i] = unionArray[i] - rightUnionArray[i];
1303 }
1304 break;
1305
1306 case EOpMul:
1307 case EOpVectorTimesScalar:
1308 case EOpMatrixTimesScalar:
1309 tempConstArray = new ConstantUnion[objectSize];
1310 {// support MSVC++6.0
1311 for (size_t i = 0; i < objectSize; i++)
1312 tempConstArray[i] = unionArray[i] * rightUnionArray[i];
1313 }
1314 break;
1315 case EOpMatrixTimesMatrix:
1316 if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat) {
1317 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
1318 return 0;
1319 }
1320 {// support MSVC++6.0
1321 int leftNumCols = getNominalSize();
1322 int leftNumRows = getSecondarySize();
1323 int rightNumCols = node->getNominalSize();
1324 int rightNumRows = node->getSecondarySize();
1325 if(leftNumCols != rightNumRows) {
1326 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
1327 return 0;
1328 }
1329 int tempNumCols = rightNumCols;
1330 int tempNumRows = leftNumRows;
1331 int tempNumAdds = leftNumCols;
1332 tempConstArray = new ConstantUnion[tempNumCols*tempNumRows];
1333 for (int row = 0; row < tempNumRows; row++) {
1334 for (int column = 0; column < tempNumCols; column++) {
1335 tempConstArray[tempNumRows * column + row].setFConst(0.0f);
1336 for (int i = 0; i < tempNumAdds; i++) {
1337 tempConstArray[tempNumRows * column + row].setFConst(tempConstArray[tempNumRows * column + row].getFConst() + unionArray[i * leftNumRows + row].getFConst() * (rightUnionArray[column * rightNumRows + i].getFConst()));
1338 }
1339 }
1340 }
1341 // update return type for matrix product
1342 returnType.setNominalSize(static_cast<unsigned char>(tempNumCols));
1343 returnType.setSecondarySize(static_cast<unsigned char>(tempNumRows));
1344 }
1345 break;
1346
1347 case EOpOuterProduct:
1348 {
1349 int leftSize = getNominalSize();
1350 int rightSize = node->getNominalSize();
1351 tempConstArray = new ConstantUnion[leftSize*rightSize];
1352 for(int row = 0; row < leftSize; row++) {
1353 for(int column = 0; column < rightSize; column++) {
1354 tempConstArray[leftSize * column + row].setFConst(unionArray[row].getFConst() * rightUnionArray[column].getFConst());
1355 }
1356 }
1357 // update return type for outer product
1358 returnType.setNominalSize(static_cast<unsigned char>(rightSize));
1359 returnType.setSecondarySize(static_cast<unsigned char>(leftSize));
1360 }
1361 break;
1362
1363 case EOpTranspose:
1364 {
1365 int rightCol = node->getNominalSize();
1366 int rightRow = node->getSecondarySize();
1367 tempConstArray = new ConstantUnion[rightCol*rightRow];
1368 for(int row = 0; row < rightRow; row++) {
1369 for(int column = 0; column < rightCol; column++) {
1370 tempConstArray[rightRow * column + row].setFConst(rightUnionArray[rightCol * row + column].getFConst());
1371 }
1372 }
1373 // update return type for transpose
1374 returnType.setNominalSize(static_cast<unsigned char>(rightRow));
1375 returnType.setSecondarySize(static_cast<unsigned char>(rightCol));
1376 }
1377 break;
1378
1379 case EOpDeterminant:
1380 {
1381 ASSERT(node->getNominalSize() == node->getSecondarySize());
1382
1383 tempConstArray = new ConstantUnion[1];
1384 tempConstArray[0].setFConst(ComputeDeterminant(node->getNominalSize(), rightUnionArray));
1385 // update return type for determinant
1386 returnType.setNominalSize(1);
1387 returnType.setSecondarySize(1);
1388 }
1389 break;
1390
1391 case EOpInverse:
1392 {
1393 ASSERT(node->getNominalSize() == node->getSecondarySize());
1394
1395 tempConstArray = CreateInverse(node, rightUnionArray);
1396 if(!tempConstArray)
1397 {
1398 // Singular matrix, just copy
1399 tempConstArray = new ConstantUnion[objectSize];
1400 for(size_t i = 0; i < objectSize; i++)
1401 tempConstArray[i] = rightUnionArray[i];
1402 }
1403 }
1404 break;
1405
1406 case EOpDiv:
1407 case EOpIMod:
1408 tempConstArray = new ConstantUnion[objectSize];
1409 {// support MSVC++6.0
1410 for (size_t i = 0; i < objectSize; i++) {
1411 switch (getType().getBasicType()) {
1412 case EbtFloat:
1413 if (rightUnionArray[i] == 0.0f) {
1414 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1415 tempConstArray[i].setFConst(FLT_MAX);
1416 } else {
1417 ASSERT(op == EOpDiv);
1418 tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst());
1419 }
1420 break;
1421
1422 case EbtInt:
1423 if (rightUnionArray[i] == 0) {
1424 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1425 tempConstArray[i].setIConst(INT_MAX);
1426 } else {
1427 if(op == EOpDiv) {
1428 tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst());
1429 } else {
1430 ASSERT(op == EOpIMod);
1431 tempConstArray[i].setIConst(unionArray[i].getIConst() % rightUnionArray[i].getIConst());
1432 }
1433 }
1434 break;
1435 case EbtUInt:
1436 if (rightUnionArray[i] == 0) {
1437 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1438 tempConstArray[i].setUConst(UINT_MAX);
1439 } else {
1440 if(op == EOpDiv) {
1441 tempConstArray[i].setUConst(unionArray[i].getUConst() / rightUnionArray[i].getUConst());
1442 } else {
1443 ASSERT(op == EOpIMod);
1444 tempConstArray[i].setUConst(unionArray[i].getUConst() % rightUnionArray[i].getUConst());
1445 }
1446 }
1447 break;
1448 default:
1449 infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"/\"", getLine());
1450 return 0;
1451 }
1452 }
1453 }
1454 break;
1455
1456 case EOpMatrixTimesVector:
1457 if (node->getBasicType() != EbtFloat) {
1458 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix times vector", getLine());
1459 return 0;
1460 }
1461 tempConstArray = new ConstantUnion[getNominalSize()];
1462
1463 {// support MSVC++6.0
1464 for (int size = getNominalSize(), i = 0; i < size; i++) {
1465 tempConstArray[i].setFConst(0.0f);
1466 for (int j = 0; j < size; j++) {
1467 tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j*size + i].getFConst()) * rightUnionArray[j].getFConst()));
1468 }
1469 }
1470 }
1471
1472 tempNode = new TIntermConstantUnion(tempConstArray, node->getType());
1473 tempNode->setLine(getLine());
1474
1475 return tempNode;
1476
1477 case EOpVectorTimesMatrix:
1478 if (getType().getBasicType() != EbtFloat) {
1479 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for vector times matrix", getLine());
1480 return 0;
1481 }
1482
1483 tempConstArray = new ConstantUnion[getNominalSize()];
1484 {// support MSVC++6.0
1485 for (int size = getNominalSize(), i = 0; i < size; i++) {
1486 tempConstArray[i].setFConst(0.0f);
1487 for (int j = 0; j < size; j++) {
1488 tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j].getFConst()) * rightUnionArray[i*size + j].getFConst()));
1489 }
1490 }
1491 }
1492 break;
1493
1494 case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
1495 tempConstArray = new ConstantUnion[objectSize];
1496 {// support MSVC++6.0
1497 for (size_t i = 0; i < objectSize; i++)
1498 tempConstArray[i] = unionArray[i] && rightUnionArray[i];
1499 }
1500 break;
1501
1502 case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
1503 tempConstArray = new ConstantUnion[objectSize];
1504 {// support MSVC++6.0
1505 for (size_t i = 0; i < objectSize; i++)
1506 tempConstArray[i] = unionArray[i] || rightUnionArray[i];
1507 }
1508 break;
1509
1510 case EOpLogicalXor:
1511 tempConstArray = new ConstantUnion[objectSize];
1512 {// support MSVC++6.0
1513 for (size_t i = 0; i < objectSize; i++)
1514 switch (getType().getBasicType()) {
1515 case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break;
1516 default: assert(false && "Default missing");
1517 }
1518 }
1519 break;
1520
1521 case EOpBitwiseAnd:
1522 tempConstArray = new ConstantUnion[objectSize];
1523 for(size_t i = 0; i < objectSize; i++)
1524 tempConstArray[i] = unionArray[i] & rightUnionArray[i];
1525 break;
1526 case EOpBitwiseXor:
1527 tempConstArray = new ConstantUnion[objectSize];
1528 for(size_t i = 0; i < objectSize; i++)
1529 tempConstArray[i] = unionArray[i] ^ rightUnionArray[i];
1530 break;
1531 case EOpBitwiseOr:
1532 tempConstArray = new ConstantUnion[objectSize];
1533 for(size_t i = 0; i < objectSize; i++)
1534 tempConstArray[i] = unionArray[i] | rightUnionArray[i];
1535 break;
1536 case EOpBitShiftLeft:
1537 tempConstArray = new ConstantUnion[objectSize];
1538 for(size_t i = 0; i < objectSize; i++)
1539 tempConstArray[i] = unionArray[i] << rightUnionArray[i];
1540 break;
1541 case EOpBitShiftRight:
1542 tempConstArray = new ConstantUnion[objectSize];
1543 for(size_t i = 0; i < objectSize; i++)
1544 tempConstArray[i] = unionArray[i] >> rightUnionArray[i];
1545 break;
1546
1547 case EOpLessThan:
1548 tempConstArray = new ConstantUnion[objectSize];
1549 for(size_t i = 0; i < objectSize; i++)
1550 tempConstArray[i].setBConst(unionArray[i] < rightUnionArray[i]);
1551 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr, objectSize);
1552 break;
1553 case EOpGreaterThan:
1554 tempConstArray = new ConstantUnion[objectSize];
1555 for(size_t i = 0; i < objectSize; i++)
1556 tempConstArray[i].setBConst(unionArray[i] > rightUnionArray[i]);
1557 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr, objectSize);
1558 break;
1559 case EOpLessThanEqual:
1560 tempConstArray = new ConstantUnion[objectSize];
1561 for(size_t i = 0; i < objectSize; i++)
1562 tempConstArray[i].setBConst(unionArray[i] <= rightUnionArray[i]);
1563 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr, objectSize);
1564 break;
1565 case EOpGreaterThanEqual:
1566 tempConstArray = new ConstantUnion[objectSize];
1567 for(size_t i = 0; i < objectSize; i++)
1568 tempConstArray[i].setBConst(unionArray[i] >= rightUnionArray[i]);
1569 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr, objectSize);
1570 break;
1571 case EOpEqual:
1572 tempConstArray = new ConstantUnion[1];
1573
1574 if(getType().getBasicType() == EbtStruct) {
1575 tempConstArray->setBConst(CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray));
1576 } else {
1577 bool boolNodeFlag = true;
1578 for (size_t i = 0; i < objectSize; i++) {
1579 if (unionArray[i] != rightUnionArray[i]) {
1580 boolNodeFlag = false;
1581 break; // break out of for loop
1582 }
1583 }
1584 tempConstArray->setBConst(boolNodeFlag);
1585 }
1586
1587 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConstExpr));
1588 tempNode->setLine(getLine());
1589
1590 return tempNode;
1591
1592 case EOpNotEqual:
1593 tempConstArray = new ConstantUnion[1];
1594
1595 if(getType().getBasicType() == EbtStruct) {
1596 tempConstArray->setBConst(!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray));
1597 } else {
1598 bool boolNodeFlag = false;
1599 for (size_t i = 0; i < objectSize; i++) {
1600 if (unionArray[i] != rightUnionArray[i]) {
1601 boolNodeFlag = true;
1602 break; // break out of for loop
1603 }
1604 }
1605 tempConstArray->setBConst(boolNodeFlag);
1606 }
1607
1608 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConstExpr));
1609 tempNode->setLine(getLine());
1610
1611 return tempNode;
1612 case EOpMax:
1613 tempConstArray = new ConstantUnion[objectSize];
1614 {// support MSVC++6.0
1615 for (size_t i = 0; i < objectSize; i++)
1616 tempConstArray[i] = unionArray[i] > rightUnionArray[i] ? unionArray[i] : rightUnionArray[i];
1617 }
1618 break;
1619 case EOpMin:
1620 tempConstArray = new ConstantUnion[objectSize];
1621 {// support MSVC++6.0
1622 for (size_t i = 0; i < objectSize; i++)
1623 tempConstArray[i] = unionArray[i] < rightUnionArray[i] ? unionArray[i] : rightUnionArray[i];
1624 }
1625 break;
1626 default:
1627 return 0;
1628 }
1629 tempNode = new TIntermConstantUnion(tempConstArray, returnType);
1630 tempNode->setLine(getLine());
1631
1632 return tempNode;
1633 } else {
1634 //
1635 // Do unary operations
1636 //
1637 TIntermConstantUnion *newNode = 0;
1638 ConstantUnion* tempConstArray = new ConstantUnion[objectSize];
1639 for (size_t i = 0; i < objectSize; i++) {
1640 switch(op) {
1641 case EOpNegative:
1642 switch (getType().getBasicType()) {
1643 case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break;
1644 case EbtInt: tempConstArray[i].setIConst(-unionArray[i].getIConst()); break;
1645 default:
1646 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1647 return 0;
1648 }
1649 break;
1650 case EOpLogicalNot: // this code is written for possible future use, will not get executed currently
1651 switch (getType().getBasicType()) {
1652 case EbtBool: tempConstArray[i].setBConst(!unionArray[i].getBConst()); break;
1653 default:
1654 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1655 return 0;
1656 }
1657 break;
1658 case EOpBitwiseNot:
1659 switch(getType().getBasicType()) {
1660 case EbtInt: tempConstArray[i].setIConst(~unionArray[i].getIConst()); break;
1661 case EbtUInt: tempConstArray[i].setUConst(~unionArray[i].getUConst()); break;
1662 default:
1663 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1664 return 0;
1665 }
1666 break;
1667 case EOpRadians:
1668 switch(getType().getBasicType()) {
1669 case EbtFloat: tempConstArray[i].setFConst(unionArray[i].getFConst() * 1.74532925e-2f); break;
1670 default:
1671 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1672 return 0;
1673 }
1674 break;
1675 case EOpDegrees:
1676 switch(getType().getBasicType()) {
1677 case EbtFloat: tempConstArray[i].setFConst(unionArray[i].getFConst() * 5.72957795e+1f); break;
1678 default:
1679 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1680 return 0;
1681 }
1682 break;
1683 case EOpSin:
1684 switch(getType().getBasicType()) {
1685 case EbtFloat: tempConstArray[i].setFConst(sinf(unionArray[i].getFConst())); break;
1686 default:
1687 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1688 return 0;
1689 }
1690 break;
1691 case EOpCos:
1692 switch(getType().getBasicType()) {
1693 case EbtFloat: tempConstArray[i].setFConst(cosf(unionArray[i].getFConst())); break;
1694 default:
1695 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1696 return 0;
1697 }
1698 break;
1699 case EOpTan:
1700 switch(getType().getBasicType()) {
1701 case EbtFloat: tempConstArray[i].setFConst(tanf(unionArray[i].getFConst())); break;
1702 default:
1703 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1704 return 0;
1705 }
1706 break;
1707 case EOpAsin:
1708 switch(getType().getBasicType()) {
1709 case EbtFloat: tempConstArray[i].setFConst(asinf(unionArray[i].getFConst())); break;
1710 default:
1711 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1712 return 0;
1713 }
1714 break;
1715 case EOpAcos:
1716 switch(getType().getBasicType()) {
1717 case EbtFloat: tempConstArray[i].setFConst(acosf(unionArray[i].getFConst())); break;
1718 default:
1719 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1720 return 0;
1721 }
1722 break;
1723 case EOpAtan:
1724 switch(getType().getBasicType()) {
1725 case EbtFloat: tempConstArray[i].setFConst(atanf(unionArray[i].getFConst())); break;
1726 default:
1727 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1728 return 0;
1729 }
1730 break;
1731 case EOpSinh:
1732 switch(getType().getBasicType()) {
1733 case EbtFloat: tempConstArray[i].setFConst(sinhf(unionArray[i].getFConst())); break;
1734 default:
1735 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1736 return 0;
1737 }
1738 break;
1739 case EOpCosh:
1740 switch(getType().getBasicType()) {
1741 case EbtFloat: tempConstArray[i].setFConst(coshf(unionArray[i].getFConst())); break;
1742 default:
1743 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1744 return 0;
1745 }
1746 break;
1747 case EOpTanh:
1748 switch(getType().getBasicType()) {
1749 case EbtFloat: tempConstArray[i].setFConst(tanhf(unionArray[i].getFConst())); break;
1750 default:
1751 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1752 return 0;
1753 }
1754 break;
1755 case EOpAsinh:
1756 switch(getType().getBasicType()) {
1757 case EbtFloat: tempConstArray[i].setFConst(asinhf(unionArray[i].getFConst())); break;
1758 default:
1759 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1760 return 0;
1761 }
1762 break;
1763 case EOpAcosh:
1764 switch(getType().getBasicType()) {
1765 case EbtFloat: tempConstArray[i].setFConst(acoshf(unionArray[i].getFConst())); break;
1766 default:
1767 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1768 return 0;
1769 }
1770 break;
1771 case EOpAtanh:
1772 switch(getType().getBasicType()) {
1773 case EbtFloat: tempConstArray[i].setFConst(atanhf(unionArray[i].getFConst())); break;
1774 default:
1775 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1776 return 0;
1777 }
1778 break;
1779 case EOpLog:
1780 switch(getType().getBasicType()) {
1781 case EbtFloat: tempConstArray[i].setFConst(logf(unionArray[i].getFConst())); break;
1782 default:
1783 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1784 return 0;
1785 }
1786 break;
1787 case EOpLog2:
1788 switch(getType().getBasicType()) {
1789 case EbtFloat: tempConstArray[i].setFConst(sw::log2(unionArray[i].getFConst())); break;
1790 default:
1791 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1792 return 0;
1793 }
1794 break;
1795 case EOpExp:
1796 switch(getType().getBasicType()) {
1797 case EbtFloat: tempConstArray[i].setFConst(expf(unionArray[i].getFConst())); break;
1798 default:
1799 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1800 return 0;
1801 }
1802 break;
1803 case EOpExp2:
1804 switch(getType().getBasicType()) {
1805 case EbtFloat: tempConstArray[i].setFConst(exp2f(unionArray[i].getFConst())); break;
1806 default:
1807 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1808 return 0;
1809 }
1810 break;
1811 case EOpSqrt:
1812 switch(getType().getBasicType()) {
1813 case EbtFloat: tempConstArray[i].setFConst(sqrtf(unionArray[i].getFConst())); break;
1814 default:
1815 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1816 return 0;
1817 }
1818 break;
1819 case EOpInverseSqrt:
1820 switch(getType().getBasicType()) {
1821 case EbtFloat: tempConstArray[i].setFConst(1.0f / sqrtf(unionArray[i].getFConst())); break;
1822 default:
1823 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1824 return 0;
1825 }
1826 break;
1827 default:
1828 return 0;
1829 }
1830 }
1831 newNode = new TIntermConstantUnion(tempConstArray, getType());
1832 newNode->setLine(getLine());
1833 return newNode;
1834 }
1835 }
1836
promoteConstantUnion(TBasicType promoteTo,TIntermConstantUnion * node)1837 TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node)
1838 {
1839 size_t size = node->getType().getObjectSize();
1840
1841 ConstantUnion *leftUnionArray = new ConstantUnion[size];
1842
1843 for(size_t i = 0; i < size; i++) {
1844 switch (promoteTo) {
1845 case EbtFloat:
1846 switch (node->getType().getBasicType()) {
1847 case EbtInt:
1848 leftUnionArray[i].setFConst(static_cast<float>(node->getIConst(i)));
1849 break;
1850 case EbtUInt:
1851 leftUnionArray[i].setFConst(static_cast<float>(node->getUConst(i)));
1852 break;
1853 case EbtBool:
1854 leftUnionArray[i].setFConst(static_cast<float>(node->getBConst(i)));
1855 break;
1856 case EbtFloat:
1857 leftUnionArray[i].setFConst(static_cast<float>(node->getFConst(i)));
1858 break;
1859 default:
1860 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1861 return 0;
1862 }
1863 break;
1864 case EbtInt:
1865 switch (node->getType().getBasicType()) {
1866 case EbtInt:
1867 leftUnionArray[i].setIConst(static_cast<int>(node->getIConst(i)));
1868 break;
1869 case EbtUInt:
1870 leftUnionArray[i].setIConst(static_cast<int>(node->getUConst(i)));
1871 break;
1872 case EbtBool:
1873 leftUnionArray[i].setIConst(static_cast<int>(node->getBConst(i)));
1874 break;
1875 case EbtFloat:
1876 leftUnionArray[i].setIConst(static_cast<int>(node->getFConst(i)));
1877 break;
1878 default:
1879 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1880 return 0;
1881 }
1882 break;
1883 case EbtUInt:
1884 switch (node->getType().getBasicType()) {
1885 case EbtInt:
1886 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getIConst(i)));
1887 break;
1888 case EbtUInt:
1889 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getUConst(i)));
1890 break;
1891 case EbtBool:
1892 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getBConst(i)));
1893 break;
1894 case EbtFloat:
1895 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getFConst(i)));
1896 break;
1897 default:
1898 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1899 return 0;
1900 }
1901 break;
1902 case EbtBool:
1903 switch (node->getType().getBasicType()) {
1904 case EbtInt:
1905 leftUnionArray[i].setBConst(node->getIConst(i) != 0);
1906 break;
1907 case EbtUInt:
1908 leftUnionArray[i].setBConst(node->getUConst(i) != 0);
1909 break;
1910 case EbtBool:
1911 leftUnionArray[i].setBConst(node->getBConst(i));
1912 break;
1913 case EbtFloat:
1914 leftUnionArray[i].setBConst(node->getFConst(i) != 0.0f);
1915 break;
1916 default:
1917 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1918 return 0;
1919 }
1920
1921 break;
1922 default:
1923 infoSink.info.message(EPrefixInternalError, "Incorrect data type found", node->getLine());
1924 return 0;
1925 }
1926
1927 }
1928
1929 const TType& t = node->getType();
1930
1931 return addConstantUnion(leftUnionArray, TType(promoteTo, t.getPrecision(), t.getQualifier(), t.getNominalSize(), t.getSecondarySize(), t.isArray()), node->getLine());
1932 }
1933
1934