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