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 {
406 delete node;
407 return 0;
408 }
409
410 //
411 // See if we can fold constants.
412 //
413 TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
414 TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
415 if (leftTempConstant && rightTempConstant) {
416 TIntermTyped *typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink);
417
418 if (typedReturnNode)
419 return typedReturnNode;
420 }
421
422 return node;
423 }
424
425 //
426 // Connect two nodes through an assignment.
427 //
428 // Returns the added node.
429 //
addAssign(TOperator op,TIntermTyped * left,TIntermTyped * right,const TSourceLoc & line)430 TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc &line)
431 {
432 if (left->getType().getStruct() || right->getType().getStruct())
433 {
434 if (left->getType() != right->getType())
435 {
436 return 0;
437 }
438 }
439
440 TIntermBinary* node = new TIntermBinary(op);
441 node->setLine(line);
442
443 node->setLeft(left);
444 node->setRight(right);
445 if (! node->promote(infoSink))
446 return 0;
447
448 return node;
449 }
450
451 //
452 // Connect two nodes through an index operator, where the left node is the base
453 // of an array or struct, and the right node is a direct or indirect offset.
454 //
455 // Returns the added node.
456 // The caller should set the type of the returned node.
457 //
addIndex(TOperator op,TIntermTyped * base,TIntermTyped * index,const TSourceLoc & line)458 TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc &line)
459 {
460 TIntermBinary* node = new TIntermBinary(op);
461 node->setLine(line);
462 node->setLeft(base);
463 node->setRight(index);
464
465 // caller should set the type
466
467 return node;
468 }
469
470 //
471 // Add one node as the parent of another that it operates on.
472 //
473 // Returns the added node.
474 //
addUnaryMath(TOperator op,TIntermTyped * child,const TSourceLoc & line,const TType * funcReturnType)475 TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, const TSourceLoc &line, const TType *funcReturnType)
476 {
477 if (child == 0) {
478 infoSink.info.message(EPrefixInternalError, "Bad type in AddUnaryMath", line);
479 return 0;
480 }
481
482 switch (op) {
483 case EOpBitwiseNot:
484 if (!IsInteger(child->getType().getBasicType()) || child->getType().isMatrix() || child->getType().isArray()) {
485 return 0;
486 }
487 break;
488
489 case EOpLogicalNot:
490 if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) {
491 return 0;
492 }
493 break;
494
495 case EOpPostIncrement:
496 case EOpPreIncrement:
497 case EOpPostDecrement:
498 case EOpPreDecrement:
499 case EOpNegative:
500 if (child->getType().getBasicType() == EbtStruct || child->getType().isArray())
501 return 0;
502 default: break;
503 }
504
505 TIntermConstantUnion *childTempConstant = 0;
506 if (child->getAsConstantUnion())
507 childTempConstant = child->getAsConstantUnion();
508
509 //
510 // Make a new node for the operator.
511 //
512 TIntermUnary *node = new TIntermUnary(op);
513 node->setLine(line);
514 node->setOperand(child);
515
516 if (! node->promote(infoSink, funcReturnType))
517 return 0;
518
519 if (childTempConstant) {
520 TIntermTyped* newChild = childTempConstant->fold(op, 0, infoSink);
521
522 if (newChild)
523 return newChild;
524 }
525
526 return node;
527 }
528
529 //
530 // This is the safe way to change the operator on an aggregate, as it
531 // does lots of error checking and fixing. Especially for establishing
532 // a function call's operation on its set of parameters. Sequences
533 // of instructions are also aggregates, but they just directly set
534 // their operator to EOpSequence.
535 //
536 // Returns an aggregate node, which could be the one passed in if
537 // it was already an aggregate but no operator was set.
538 //
setAggregateOperator(TIntermNode * node,TOperator op,const TSourceLoc & line)539 TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TSourceLoc &line)
540 {
541 TIntermAggregate* aggNode;
542
543 //
544 // Make sure we have an aggregate. If not turn it into one.
545 //
546 if (node) {
547 aggNode = node->getAsAggregate();
548 if (aggNode == 0 || aggNode->getOp() != EOpNull) {
549 //
550 // Make an aggregate containing this node.
551 //
552 aggNode = new TIntermAggregate();
553 aggNode->getSequence().push_back(node);
554 }
555 } else
556 aggNode = new TIntermAggregate();
557
558 //
559 // Set the operator.
560 //
561 aggNode->setOp(op);
562
563 return aggNode;
564 }
565
566 //
567 // Safe way to combine two nodes into an aggregate. Works with null pointers,
568 // a node that's not a aggregate yet, etc.
569 //
570 // Returns the resulting aggregate, unless 0 was passed in for
571 // both existing nodes.
572 //
growAggregate(TIntermNode * left,TIntermNode * right,const TSourceLoc & line)573 TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc &line)
574 {
575 if (left == 0 && right == 0)
576 return 0;
577
578 TIntermAggregate* aggNode = 0;
579 if (left)
580 aggNode = left->getAsAggregate();
581 if (!aggNode || aggNode->getOp() != EOpNull) {
582 aggNode = new TIntermAggregate;
583 if (left)
584 aggNode->getSequence().push_back(left);
585 }
586
587 if (right)
588 aggNode->getSequence().push_back(right);
589
590 aggNode->setLine(line);
591
592 return aggNode;
593 }
594
595 //
596 // Turn an existing node into an aggregate.
597 //
598 // Returns an aggregate, unless 0 was passed in for the existing node.
599 //
makeAggregate(TIntermNode * node,const TSourceLoc & line)600 TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, const TSourceLoc &line)
601 {
602 if (node == 0)
603 return 0;
604
605 TIntermAggregate* aggNode = new TIntermAggregate;
606 aggNode->getSequence().push_back(node);
607
608 aggNode->setLine(line);
609
610 return aggNode;
611 }
612
613 //
614 // For "if" test nodes. There are three children; a condition,
615 // a true path, and a false path. The two paths are in the
616 // nodePair.
617 //
618 // Returns the selection node created.
619 //
addSelection(TIntermTyped * cond,TIntermNodePair nodePair,const TSourceLoc & line)620 TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, const TSourceLoc &line)
621 {
622 //
623 // For compile time constant selections, prune the code and
624 // test now.
625 //
626
627 if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion()) {
628 if (cond->getAsConstantUnion()->getBConst(0) == true)
629 return nodePair.node1 ? setAggregateOperator(nodePair.node1, EOpSequence, nodePair.node1->getLine()) : nullptr;
630 else
631 return nodePair.node2 ? setAggregateOperator(nodePair.node2, EOpSequence, nodePair.node2->getLine()) : nullptr;
632 }
633
634 TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2);
635 node->setLine(line);
636
637 return node;
638 }
639
640
addComma(TIntermTyped * left,TIntermTyped * right,const TSourceLoc & line)641 TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc &line)
642 {
643 if (left->getType().getQualifier() == EvqConstExpr && right->getType().getQualifier() == EvqConstExpr) {
644 return right;
645 } else {
646 TIntermTyped *commaAggregate = growAggregate(left, right, line);
647 commaAggregate->getAsAggregate()->setOp(EOpComma);
648 commaAggregate->setType(right->getType());
649 commaAggregate->getTypePointer()->setQualifier(EvqTemporary);
650 return commaAggregate;
651 }
652 }
653
654 //
655 // For "?:" test nodes. There are three children; a condition,
656 // a true path, and a false path. The two paths are specified
657 // as separate parameters.
658 //
659 // Returns the selection node created, or 0 if one could not be.
660 //
addSelection(TIntermTyped * cond,TIntermTyped * trueBlock,TIntermTyped * falseBlock,const TSourceLoc & line)661 TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc &line)
662 {
663 if (trueBlock->getType() != falseBlock->getType())
664 {
665 return 0;
666 }
667
668 //
669 // See if all the operands are constant, then fold it otherwise not.
670 //
671
672 if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) {
673 if (cond->getAsConstantUnion()->getBConst(0))
674 return trueBlock;
675 else
676 return falseBlock;
677 }
678
679 //
680 // Make a selection node.
681 //
682 TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
683 node->getTypePointer()->setQualifier(EvqTemporary);
684 node->setLine(line);
685
686 return node;
687 }
688
addSwitch(TIntermTyped * init,TIntermAggregate * statementList,const TSourceLoc & line)689 TIntermSwitch *TIntermediate::addSwitch(TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &line)
690 {
691 TIntermSwitch *node = new TIntermSwitch(init, statementList);
692 node->setLine(line);
693
694 return node;
695 }
696
addCase(TIntermTyped * condition,const TSourceLoc & line)697 TIntermCase *TIntermediate::addCase(TIntermTyped *condition, const TSourceLoc &line)
698 {
699 TIntermCase *node = new TIntermCase(condition);
700 node->setLine(line);
701
702 return node;
703 }
704
705 //
706 // Constant terminal nodes. Has a union that contains bool, float or int constants
707 //
708 // Returns the constant union node created.
709 //
710
addConstantUnion(ConstantUnion * unionArrayPointer,const TType & t,const TSourceLoc & line)711 TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, const TSourceLoc &line)
712 {
713 TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t);
714 node->setLine(line);
715
716 return node;
717 }
718
addSwizzle(TVectorFields & fields,const TSourceLoc & line)719 TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, const TSourceLoc &line)
720 {
721
722 TIntermAggregate* node = new TIntermAggregate(EOpSequence);
723
724 node->setLine(line);
725 TIntermConstantUnion* constIntNode;
726 TIntermSequence &sequenceVector = node->getSequence();
727 ConstantUnion* unionArray;
728
729 for (int i = 0; i < fields.num; i++) {
730 unionArray = new ConstantUnion[1];
731 unionArray->setIConst(fields.offsets[i]);
732 constIntNode = addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConstExpr), line);
733 sequenceVector.push_back(constIntNode);
734 }
735
736 return node;
737 }
738
739 //
740 // Create loop nodes.
741 //
addLoop(TLoopType type,TIntermNode * init,TIntermTyped * cond,TIntermTyped * expr,TIntermNode * body,const TSourceLoc & line)742 TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTyped* cond, TIntermTyped* expr, TIntermNode* body, const TSourceLoc &line)
743 {
744 TIntermNode* node = new TIntermLoop(type, init, cond, expr, body);
745 node->setLine(line);
746
747 return node;
748 }
749
750 //
751 // Add branches.
752 //
addBranch(TOperator branchOp,const TSourceLoc & line)753 TIntermBranch* TIntermediate::addBranch(TOperator branchOp, const TSourceLoc &line)
754 {
755 return addBranch(branchOp, 0, line);
756 }
757
addBranch(TOperator branchOp,TIntermTyped * expression,const TSourceLoc & line)758 TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, const TSourceLoc &line)
759 {
760 TIntermBranch* node = new TIntermBranch(branchOp, expression);
761 node->setLine(line);
762
763 return node;
764 }
765
766 //
767 // This is to be executed once the final root is put on top by the parsing
768 // process.
769 //
postProcess(TIntermNode * root)770 bool TIntermediate::postProcess(TIntermNode* root)
771 {
772 if (root == 0)
773 return true;
774
775 //
776 // First, finish off the top level sequence, if any
777 //
778 TIntermAggregate* aggRoot = root->getAsAggregate();
779 if (aggRoot && aggRoot->getOp() == EOpNull)
780 aggRoot->setOp(EOpSequence);
781
782 return true;
783 }
784
785 ////////////////////////////////////////////////////////////////
786 //
787 // Member functions of the nodes used for building the tree.
788 //
789 ////////////////////////////////////////////////////////////////
790
791 // static
CreateIndexNode(int index)792 TIntermTyped *TIntermTyped::CreateIndexNode(int index)
793 {
794 ConstantUnion *u = new ConstantUnion[1];
795 u[0].setIConst(index);
796
797 TType type(EbtInt, EbpUndefined, EvqConstExpr, 1);
798 TIntermConstantUnion *node = new TIntermConstantUnion(u, type);
799 return node;
800 }
801
802 //
803 // Say whether or not an operation node changes the value of a variable.
804 //
805 // Returns true if state is modified.
806 //
modifiesState() const807 bool TIntermOperator::modifiesState() const
808 {
809 switch (op) {
810 case EOpPostIncrement:
811 case EOpPostDecrement:
812 case EOpPreIncrement:
813 case EOpPreDecrement:
814 case EOpAssign:
815 case EOpAddAssign:
816 case EOpSubAssign:
817 case EOpMulAssign:
818 case EOpVectorTimesMatrixAssign:
819 case EOpVectorTimesScalarAssign:
820 case EOpMatrixTimesScalarAssign:
821 case EOpMatrixTimesMatrixAssign:
822 case EOpDivAssign:
823 case EOpIModAssign:
824 case EOpBitShiftLeftAssign:
825 case EOpBitShiftRightAssign:
826 case EOpBitwiseAndAssign:
827 case EOpBitwiseXorAssign:
828 case EOpBitwiseOrAssign:
829 return true;
830 default:
831 return false;
832 }
833 }
834
835 //
836 // returns true if the operator is for one of the constructors
837 //
isConstructor() const838 bool TIntermOperator::isConstructor() const
839 {
840 switch (op) {
841 case EOpConstructVec2:
842 case EOpConstructVec3:
843 case EOpConstructVec4:
844 case EOpConstructMat2:
845 case EOpConstructMat2x3:
846 case EOpConstructMat2x4:
847 case EOpConstructMat3x2:
848 case EOpConstructMat3:
849 case EOpConstructMat3x4:
850 case EOpConstructMat4x2:
851 case EOpConstructMat4x3:
852 case EOpConstructMat4:
853 case EOpConstructFloat:
854 case EOpConstructIVec2:
855 case EOpConstructIVec3:
856 case EOpConstructIVec4:
857 case EOpConstructInt:
858 case EOpConstructUVec2:
859 case EOpConstructUVec3:
860 case EOpConstructUVec4:
861 case EOpConstructUInt:
862 case EOpConstructBVec2:
863 case EOpConstructBVec3:
864 case EOpConstructBVec4:
865 case EOpConstructBool:
866 case EOpConstructStruct:
867 return true;
868 default:
869 return false;
870 }
871 }
872
873 //
874 // Make sure the type of a unary operator is appropriate for its
875 // combination of operation and operand type.
876 //
877 // Returns false in nothing makes sense.
878 //
promote(TInfoSink &,const TType * funcReturnType)879 bool TIntermUnary::promote(TInfoSink&, const TType *funcReturnType)
880 {
881 setType(funcReturnType ? *funcReturnType : operand->getType());
882
883 // Unary operations result in temporary variables unless const.
884 if(type.getQualifier() != EvqConstExpr)
885 {
886 type.setQualifier(EvqTemporary);
887 }
888
889 switch (op) {
890 case EOpLogicalNot:
891 if (operand->getBasicType() != EbtBool)
892 return false;
893 break;
894 case EOpBitwiseNot:
895 if (!IsInteger(operand->getBasicType()))
896 return false;
897 break;
898 case EOpNegative:
899 case EOpPostIncrement:
900 case EOpPostDecrement:
901 case EOpPreIncrement:
902 case EOpPreDecrement:
903 if (operand->getBasicType() == EbtBool)
904 return false;
905 break;
906
907 // operators for built-ins are already type checked against their prototype
908 case EOpAny:
909 case EOpAll:
910 case EOpVectorLogicalNot:
911 case EOpAbs:
912 case EOpSign:
913 case EOpIsNan:
914 case EOpIsInf:
915 case EOpFloatBitsToInt:
916 case EOpFloatBitsToUint:
917 case EOpIntBitsToFloat:
918 case EOpUintBitsToFloat:
919 case EOpPackSnorm2x16:
920 case EOpPackUnorm2x16:
921 case EOpPackHalf2x16:
922 case EOpUnpackSnorm2x16:
923 case EOpUnpackUnorm2x16:
924 case EOpUnpackHalf2x16:
925 return true;
926
927 default:
928 if (operand->getBasicType() != EbtFloat)
929 return false;
930 }
931
932 return true;
933 }
934
935 //
936 // Establishes the type of the resultant operation, as well as
937 // makes the operator the correct one for the operands.
938 //
939 // Returns false if operator can't work on operands.
940 //
promote(TInfoSink & infoSink)941 bool TIntermBinary::promote(TInfoSink& infoSink)
942 {
943 ASSERT(left->isArray() == right->isArray());
944
945 // GLSL ES 2.0 does not support implicit type casting.
946 // So the basic type should always match.
947 // GLSL ES 3.0 supports integer shift operands of different signedness.
948 if(op != EOpBitShiftLeft &&
949 op != EOpBitShiftRight &&
950 op != EOpBitShiftLeftAssign &&
951 op != EOpBitShiftRightAssign &&
952 left->getBasicType() != right->getBasicType())
953 {
954 return false;
955 }
956
957 //
958 // Base assumption: just make the type the same as the left
959 // operand. Then only deviations from this need be coded.
960 //
961 setType(left->getType());
962
963 // The result gets promoted to the highest precision.
964 TPrecision higherPrecision = GetHigherPrecision(left->getPrecision(), right->getPrecision());
965 getTypePointer()->setPrecision(higherPrecision);
966
967 // Binary operations results in temporary variables unless both
968 // operands are const.
969 if (left->getQualifier() != EvqConstExpr || right->getQualifier() != EvqConstExpr) {
970 getTypePointer()->setQualifier(EvqTemporary);
971 }
972
973 int primarySize = std::max(left->getNominalSize(), right->getNominalSize());
974
975 //
976 // All scalars. Code after this test assumes this case is removed!
977 //
978 if (primarySize == 1) {
979 switch (op) {
980 //
981 // Promote to conditional
982 //
983 case EOpEqual:
984 case EOpNotEqual:
985 case EOpLessThan:
986 case EOpGreaterThan:
987 case EOpLessThanEqual:
988 case EOpGreaterThanEqual:
989 setType(TType(EbtBool, EbpUndefined));
990 break;
991
992 //
993 // And and Or operate on conditionals
994 //
995 case EOpLogicalAnd:
996 case EOpLogicalOr:
997 case EOpLogicalXor:
998 // Both operands must be of type bool.
999 if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool)
1000 return false;
1001 setType(TType(EbtBool, EbpUndefined));
1002 break;
1003
1004 default:
1005 break;
1006 }
1007 return true;
1008 }
1009
1010 // If we reach here, at least one of the operands is vector or matrix.
1011 // The other operand could be a scalar, vector, or matrix.
1012 // Can these two operands be combined?
1013 //
1014 TBasicType basicType = left->getBasicType();
1015 switch (op) {
1016 case EOpMul:
1017 if (!left->isMatrix() && right->isMatrix()) {
1018 if (left->isVector())
1019 {
1020 op = EOpVectorTimesMatrix;
1021 setType(TType(basicType, higherPrecision, EvqTemporary,
1022 static_cast<unsigned char>(right->getNominalSize()), 1));
1023 }
1024 else {
1025 op = EOpMatrixTimesScalar;
1026 setType(TType(basicType, higherPrecision, EvqTemporary,
1027 static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(right->getSecondarySize())));
1028 }
1029 } else if (left->isMatrix() && !right->isMatrix()) {
1030 if (right->isVector()) {
1031 op = EOpMatrixTimesVector;
1032 setType(TType(basicType, higherPrecision, EvqTemporary,
1033 static_cast<unsigned char>(left->getSecondarySize()), 1));
1034 } else {
1035 op = EOpMatrixTimesScalar;
1036 }
1037 } else if (left->isMatrix() && right->isMatrix()) {
1038 op = EOpMatrixTimesMatrix;
1039 setType(TType(basicType, higherPrecision, EvqTemporary,
1040 static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(left->getSecondarySize())));
1041 } else if (!left->isMatrix() && !right->isMatrix()) {
1042 if (left->isVector() && right->isVector()) {
1043 // leave as component product
1044 } else if (left->isVector() || right->isVector()) {
1045 op = EOpVectorTimesScalar;
1046 setType(TType(basicType, higherPrecision, EvqTemporary,
1047 static_cast<unsigned char>(primarySize), 1));
1048 }
1049 } else {
1050 infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
1051 return false;
1052 }
1053
1054 if(!ValidateMultiplication(op, left->getType(), right->getType()))
1055 {
1056 return false;
1057 }
1058 break;
1059 case EOpMulAssign:
1060 if (!left->isMatrix() && right->isMatrix()) {
1061 if (left->isVector())
1062 op = EOpVectorTimesMatrixAssign;
1063 else {
1064 return false;
1065 }
1066 } else if (left->isMatrix() && !right->isMatrix()) {
1067 if (right->isVector()) {
1068 return false;
1069 } else {
1070 op = EOpMatrixTimesScalarAssign;
1071 }
1072 } else if (left->isMatrix() && right->isMatrix()) {
1073 op = EOpMatrixTimesMatrixAssign;
1074 setType(TType(basicType, higherPrecision, EvqTemporary,
1075 static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(left->getSecondarySize())));
1076 } else if (!left->isMatrix() && !right->isMatrix()) {
1077 if (left->isVector() && right->isVector()) {
1078 // leave as component product
1079 } else if (left->isVector() || right->isVector()) {
1080 if (! left->isVector())
1081 return false;
1082 op = EOpVectorTimesScalarAssign;
1083 setType(TType(basicType, higherPrecision, EvqTemporary,
1084 static_cast<unsigned char>(left->getNominalSize()), 1));
1085 }
1086 } else {
1087 infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
1088 return false;
1089 }
1090
1091 if(!ValidateMultiplication(op, left->getType(), right->getType()))
1092 {
1093 return false;
1094 }
1095 break;
1096
1097 case EOpAssign:
1098 case EOpInitialize:
1099 // No more additional checks are needed.
1100 if ((left->getNominalSize() != right->getNominalSize()) ||
1101 (left->getSecondarySize() != right->getSecondarySize()))
1102 return false;
1103 break;
1104 case EOpAdd:
1105 case EOpSub:
1106 case EOpDiv:
1107 case EOpIMod:
1108 case EOpBitShiftLeft:
1109 case EOpBitShiftRight:
1110 case EOpBitwiseAnd:
1111 case EOpBitwiseXor:
1112 case EOpBitwiseOr:
1113 case EOpAddAssign:
1114 case EOpSubAssign:
1115 case EOpDivAssign:
1116 case EOpIModAssign:
1117 case EOpBitShiftLeftAssign:
1118 case EOpBitShiftRightAssign:
1119 case EOpBitwiseAndAssign:
1120 case EOpBitwiseXorAssign:
1121 case EOpBitwiseOrAssign:
1122 if ((left->isMatrix() && right->isVector()) ||
1123 (left->isVector() && right->isMatrix()))
1124 return false;
1125
1126 // Are the sizes compatible?
1127 if(left->getNominalSize() != right->getNominalSize() ||
1128 left->getSecondarySize() != right->getSecondarySize())
1129 {
1130 // If the nominal sizes of operands do not match:
1131 // One of them must be a scalar.
1132 if(!left->isScalar() && !right->isScalar())
1133 return false;
1134
1135 // In the case of compound assignment other than multiply-assign,
1136 // the right side needs to be a scalar. Otherwise a vector/matrix
1137 // would be assigned to a scalar. A scalar can't be shifted by a
1138 // vector either.
1139 if(!right->isScalar() && (modifiesState() || op == EOpBitShiftLeft || op == EOpBitShiftRight))
1140 return false;
1141 }
1142
1143 {
1144 const int secondarySize = std::max(
1145 left->getSecondarySize(), right->getSecondarySize());
1146 setType(TType(basicType, higherPrecision, EvqTemporary,
1147 static_cast<unsigned char>(primarySize), static_cast<unsigned char>(secondarySize)));
1148 if(left->isArray())
1149 {
1150 ASSERT(left->getArraySize() == right->getArraySize());
1151 type.setArraySize(left->getArraySize());
1152 }
1153 }
1154 break;
1155
1156 case EOpEqual:
1157 case EOpNotEqual:
1158 case EOpLessThan:
1159 case EOpGreaterThan:
1160 case EOpLessThanEqual:
1161 case EOpGreaterThanEqual:
1162 if ((left->getNominalSize() != right->getNominalSize()) ||
1163 (left->getSecondarySize() != right->getSecondarySize()))
1164 return false;
1165 setType(TType(EbtBool, EbpUndefined));
1166 break;
1167
1168 case EOpOuterProduct:
1169 if(!left->isVector() || !right->isVector())
1170 return false;
1171 setType(TType(EbtFloat, right->getNominalSize(), left->getNominalSize()));
1172 break;
1173
1174 case EOpTranspose:
1175 if(!right->isMatrix())
1176 return false;
1177 setType(TType(EbtFloat, right->getSecondarySize(), right->getNominalSize()));
1178 break;
1179
1180 case EOpDeterminant:
1181 if(!right->isMatrix())
1182 return false;
1183 setType(TType(EbtFloat));
1184 break;
1185
1186 case EOpInverse:
1187 if(!right->isMatrix() || right->getNominalSize() != right->getSecondarySize())
1188 return false;
1189 setType(right->getType());
1190 break;
1191
1192 default:
1193 return false;
1194 }
1195
1196 return true;
1197 }
1198
CompareStruct(const TType & leftNodeType,ConstantUnion * rightUnionArray,ConstantUnion * leftUnionArray)1199 bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
1200 {
1201 const TFieldList& fields = leftNodeType.getStruct()->fields();
1202
1203 size_t structSize = fields.size();
1204 int index = 0;
1205
1206 for (size_t j = 0; j < structSize; j++) {
1207 size_t size = fields[j]->type()->getObjectSize();
1208 for(size_t i = 0; i < size; i++) {
1209 if (fields[j]->type()->getBasicType() == EbtStruct) {
1210 if (!CompareStructure(*(fields[j]->type()), &rightUnionArray[index], &leftUnionArray[index]))
1211 return false;
1212 } else {
1213 if (leftUnionArray[index] != rightUnionArray[index])
1214 return false;
1215 index++;
1216 }
1217
1218 }
1219 }
1220 return true;
1221 }
1222
CompareStructure(const TType & leftNodeType,ConstantUnion * rightUnionArray,ConstantUnion * leftUnionArray)1223 bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
1224 {
1225 if (leftNodeType.isArray()) {
1226 TType typeWithoutArrayness = leftNodeType;
1227 typeWithoutArrayness.clearArrayness();
1228
1229 int arraySize = leftNodeType.getArraySize();
1230
1231 for (int i = 0; i < arraySize; ++i) {
1232 size_t offset = typeWithoutArrayness.getObjectSize() * i;
1233 if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset]))
1234 return false;
1235 }
1236 } else
1237 return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray);
1238
1239 return true;
1240 }
1241
determinant2(float m00,float m01,float m10,float m11)1242 float determinant2(float m00, float m01, float m10, float m11)
1243 {
1244 return m00 * m11 - m01 * m10;
1245 }
1246
determinant3(float m00,float m01,float m02,float m10,float m11,float m12,float m20,float m21,float m22)1247 float determinant3(float m00, float m01, float m02,
1248 float m10, float m11, float m12,
1249 float m20, float m21, float m22)
1250 {
1251 return m00 * determinant2(m11, m12, m21, m22) -
1252 m10 * determinant2(m01, m02, m21, m22) +
1253 m20 * determinant2(m01, m02, m11, m12);
1254 }
1255
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)1256 float determinant4(float m00, float m01, float m02, float m03,
1257 float m10, float m11, float m12, float m13,
1258 float m20, float m21, float m22, float m23,
1259 float m30, float m31, float m32, float m33)
1260 {
1261 return m00 * determinant3(m11, m12, m13, m21, m22, m23, m31, m32, m33) -
1262 m10 * determinant3(m01, m02, m03, m21, m22, m23, m31, m32, m33) +
1263 m20 * determinant3(m01, m02, m03, m11, m12, m13, m31, m32, m33) -
1264 m30 * determinant3(m01, m02, m03, m11, m12, m13, m21, m22, m23);
1265 }
1266
ComputeDeterminant(int size,ConstantUnion * unionArray)1267 float ComputeDeterminant(int size, ConstantUnion* unionArray)
1268 {
1269 switch(size)
1270 {
1271 case 2:
1272 return determinant2(unionArray[0].getFConst(),
1273 unionArray[1].getFConst(),
1274 unionArray[2].getFConst(),
1275 unionArray[3].getFConst());
1276 case 3:
1277 return determinant3(unionArray[0].getFConst(),
1278 unionArray[1].getFConst(),
1279 unionArray[2].getFConst(),
1280 unionArray[3].getFConst(),
1281 unionArray[4].getFConst(),
1282 unionArray[5].getFConst(),
1283 unionArray[6].getFConst(),
1284 unionArray[7].getFConst(),
1285 unionArray[8].getFConst());
1286 case 4:
1287 return determinant4(unionArray[0].getFConst(),
1288 unionArray[1].getFConst(),
1289 unionArray[2].getFConst(),
1290 unionArray[3].getFConst(),
1291 unionArray[4].getFConst(),
1292 unionArray[5].getFConst(),
1293 unionArray[6].getFConst(),
1294 unionArray[7].getFConst(),
1295 unionArray[8].getFConst(),
1296 unionArray[9].getFConst(),
1297 unionArray[10].getFConst(),
1298 unionArray[11].getFConst(),
1299 unionArray[12].getFConst(),
1300 unionArray[13].getFConst(),
1301 unionArray[14].getFConst(),
1302 unionArray[15].getFConst());
1303 default:
1304 UNREACHABLE(size);
1305 return 0.0f;
1306 }
1307 }
1308
CreateInverse(TIntermConstantUnion * node,ConstantUnion * unionArray)1309 ConstantUnion* CreateInverse(TIntermConstantUnion* node, ConstantUnion* unionArray)
1310 {
1311 ConstantUnion* tempConstArray = 0;
1312 int size = node->getNominalSize();
1313 float determinant = ComputeDeterminant(size, unionArray);
1314 if(determinant != 0.0f)
1315 {
1316 float invDet = 1.0f / determinant;
1317 tempConstArray = new ConstantUnion[size*size];
1318 switch(size)
1319 {
1320 case 2:
1321 {
1322 float m00 = unionArray[0].getFConst(); // Matrix is:
1323 float m01 = unionArray[1].getFConst(); // (m00, m01)
1324 float m10 = unionArray[2].getFConst(); // (m10, m11)
1325 float m11 = unionArray[3].getFConst();
1326 tempConstArray[0].setFConst( invDet * m11);
1327 tempConstArray[1].setFConst(-invDet * m01);
1328 tempConstArray[2].setFConst(-invDet * m10);
1329 tempConstArray[3].setFConst( invDet * m00);
1330 }
1331 break;
1332 case 3:
1333 {
1334 float m00 = unionArray[0].getFConst(); // Matrix is:
1335 float m01 = unionArray[1].getFConst(); // (m00, m01, m02)
1336 float m02 = unionArray[2].getFConst(); // (m10, m11, m12)
1337 float m10 = unionArray[3].getFConst(); // (m20, m21, m22)
1338 float m11 = unionArray[4].getFConst();
1339 float m12 = unionArray[5].getFConst();
1340 float m20 = unionArray[6].getFConst();
1341 float m21 = unionArray[7].getFConst();
1342 float m22 = unionArray[8].getFConst();
1343 tempConstArray[0].setFConst(invDet * determinant2(m11, m12, m21, m22)); // m00 = invDet * (m11 * m22 - m12 * m21)
1344 tempConstArray[1].setFConst(invDet * determinant2(m12, m10, m22, m20)); // m01 = -invDet * (m10 * m22 - m12 * m20)
1345 tempConstArray[2].setFConst(invDet * determinant2(m10, m11, m20, m21)); // m02 = invDet * (m10 * m21 - m11 * m20)
1346 tempConstArray[3].setFConst(invDet * determinant2(m21, m22, m01, m02)); // m10 = -invDet * (m01 * m22 - m02 * m21)
1347 tempConstArray[4].setFConst(invDet * determinant2(m00, m02, m20, m22)); // m11 = invDet * (m00 * m22 - m02 * m20)
1348 tempConstArray[5].setFConst(invDet * determinant2(m20, m21, m00, m01)); // m12 = -invDet * (m00 * m21 - m01 * m20)
1349 tempConstArray[6].setFConst(invDet * determinant2(m01, m02, m11, m12)); // m20 = invDet * (m01 * m12 - m02 * m11)
1350 tempConstArray[7].setFConst(invDet * determinant2(m10, m12, m00, m02)); // m21 = -invDet * (m00 * m12 - m02 * m10)
1351 tempConstArray[8].setFConst(invDet * determinant2(m00, m01, m10, m11)); // m22 = invDet * (m00 * m11 - m01 * m10)
1352 }
1353 break;
1354 case 4:
1355 {
1356 float m00 = unionArray[0].getFConst(); // Matrix is:
1357 float m01 = unionArray[1].getFConst(); // (m00, m01, m02, m03)
1358 float m02 = unionArray[2].getFConst(); // (m10, m11, m12, m13)
1359 float m03 = unionArray[3].getFConst(); // (m20, m21, m22, m23)
1360 float m10 = unionArray[4].getFConst(); // (m30, m31, m32, m33)
1361 float m11 = unionArray[5].getFConst();
1362 float m12 = unionArray[6].getFConst();
1363 float m13 = unionArray[7].getFConst();
1364 float m20 = unionArray[8].getFConst();
1365 float m21 = unionArray[9].getFConst();
1366 float m22 = unionArray[10].getFConst();
1367 float m23 = unionArray[11].getFConst();
1368 float m30 = unionArray[12].getFConst();
1369 float m31 = unionArray[13].getFConst();
1370 float m32 = unionArray[14].getFConst();
1371 float m33 = unionArray[15].getFConst();
1372 tempConstArray[ 0].setFConst( invDet * determinant3(m11, m12, m13, m21, m22, m23, m31, m32, m33)); // m00
1373 tempConstArray[ 1].setFConst(-invDet * determinant3(m10, m12, m13, m20, m22, m23, m30, m32, m33)); // m01
1374 tempConstArray[ 2].setFConst( invDet * determinant3(m10, m11, m13, m20, m21, m23, m30, m31, m33)); // m02
1375 tempConstArray[ 3].setFConst(-invDet * determinant3(m10, m11, m12, m20, m21, m22, m30, m31, m32)); // m03
1376 tempConstArray[ 4].setFConst( invDet * determinant3(m01, m02, m03, m21, m22, m23, m31, m32, m33)); // m10
1377 tempConstArray[ 5].setFConst(-invDet * determinant3(m00, m02, m03, m20, m22, m23, m30, m32, m33)); // m11
1378 tempConstArray[ 6].setFConst( invDet * determinant3(m00, m01, m03, m20, m21, m23, m30, m31, m33)); // m12
1379 tempConstArray[ 7].setFConst(-invDet * determinant3(m00, m01, m02, m20, m21, m22, m30, m31, m32)); // m13
1380 tempConstArray[ 8].setFConst( invDet * determinant3(m01, m02, m03, m11, m12, m13, m31, m32, m33)); // m20
1381 tempConstArray[ 9].setFConst(-invDet * determinant3(m00, m02, m03, m10, m12, m13, m30, m32, m33)); // m21
1382 tempConstArray[10].setFConst( invDet * determinant3(m00, m01, m03, m10, m11, m13, m30, m31, m33)); // m22
1383 tempConstArray[11].setFConst(-invDet * determinant3(m00, m01, m02, m10, m11, m12, m30, m31, m32)); // m23
1384 tempConstArray[12].setFConst( invDet * determinant3(m01, m02, m03, m11, m12, m13, m21, m22, m23)); // m30
1385 tempConstArray[13].setFConst(-invDet * determinant3(m00, m02, m03, m10, m12, m13, m20, m22, m23)); // m31
1386 tempConstArray[14].setFConst( invDet * determinant3(m00, m01, m03, m10, m11, m13, m20, m21, m23)); // m32
1387 tempConstArray[15].setFConst(-invDet * determinant3(m00, m01, m02, m10, m11, m12, m20, m21, m22)); // m33
1388 }
1389 break;
1390 default:
1391 UNREACHABLE(size);
1392 }
1393 }
1394 return tempConstArray;
1395 }
1396
1397 //
1398 // The fold functions see if an operation on a constant can be done in place,
1399 // without generating run-time code.
1400 //
1401 // Returns the node to keep using, which may or may not be the node passed in.
1402 //
1403
fold(TOperator op,TIntermTyped * constantNode,TInfoSink & infoSink)1404 TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink)
1405 {
1406 ConstantUnion *unionArray = getUnionArrayPointer();
1407 size_t objectSize = getType().getObjectSize();
1408
1409 if (constantNode) { // binary operations
1410 TIntermConstantUnion *node = constantNode->getAsConstantUnion();
1411 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
1412 TType returnType = getType();
1413
1414 // for a case like float f = 1.2 + vec4(2,3,4,5);
1415 if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) {
1416 rightUnionArray = new ConstantUnion[objectSize];
1417 for (size_t i = 0; i < objectSize; ++i)
1418 rightUnionArray[i] = *node->getUnionArrayPointer();
1419 returnType = getType();
1420 } else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) {
1421 // for a case like float f = vec4(2,3,4,5) + 1.2;
1422 unionArray = new ConstantUnion[constantNode->getType().getObjectSize()];
1423 for (size_t i = 0; i < constantNode->getType().getObjectSize(); ++i)
1424 unionArray[i] = *getUnionArrayPointer();
1425 returnType = node->getType();
1426 objectSize = constantNode->getType().getObjectSize();
1427 }
1428
1429 ConstantUnion* tempConstArray = 0;
1430 TIntermConstantUnion *tempNode;
1431
1432 switch(op) {
1433 case EOpAdd:
1434 tempConstArray = new ConstantUnion[objectSize];
1435 {// support MSVC++6.0
1436 for (size_t i = 0; i < objectSize; i++)
1437 tempConstArray[i] = unionArray[i] + rightUnionArray[i];
1438 }
1439 break;
1440 case EOpSub:
1441 tempConstArray = new ConstantUnion[objectSize];
1442 {// support MSVC++6.0
1443 for (size_t i = 0; i < objectSize; i++)
1444 tempConstArray[i] = unionArray[i] - rightUnionArray[i];
1445 }
1446 break;
1447
1448 case EOpMul:
1449 case EOpVectorTimesScalar:
1450 case EOpMatrixTimesScalar:
1451 tempConstArray = new ConstantUnion[objectSize];
1452 {// support MSVC++6.0
1453 for (size_t i = 0; i < objectSize; i++)
1454 tempConstArray[i] = unionArray[i] * rightUnionArray[i];
1455 }
1456 break;
1457 case EOpMatrixTimesMatrix:
1458 if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat) {
1459 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
1460 return 0;
1461 }
1462 {// support MSVC++6.0
1463 int leftNumCols = getNominalSize();
1464 int leftNumRows = getSecondarySize();
1465 int rightNumCols = node->getNominalSize();
1466 int rightNumRows = node->getSecondarySize();
1467 if(leftNumCols != rightNumRows) {
1468 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
1469 return 0;
1470 }
1471 int tempNumCols = rightNumCols;
1472 int tempNumRows = leftNumRows;
1473 int tempNumAdds = leftNumCols;
1474 tempConstArray = new ConstantUnion[tempNumCols*tempNumRows];
1475 for (int row = 0; row < tempNumRows; row++) {
1476 for (int column = 0; column < tempNumCols; column++) {
1477 tempConstArray[tempNumRows * column + row].setFConst(0.0f);
1478 for (int i = 0; i < tempNumAdds; i++) {
1479 tempConstArray[tempNumRows * column + row].setFConst(tempConstArray[tempNumRows * column + row].getFConst() + unionArray[i * leftNumRows + row].getFConst() * (rightUnionArray[column * rightNumRows + i].getFConst()));
1480 }
1481 }
1482 }
1483 // update return type for matrix product
1484 returnType.setNominalSize(static_cast<unsigned char>(tempNumCols));
1485 returnType.setSecondarySize(static_cast<unsigned char>(tempNumRows));
1486 }
1487 break;
1488
1489 case EOpOuterProduct:
1490 {
1491 int leftSize = getNominalSize();
1492 int rightSize = node->getNominalSize();
1493 tempConstArray = new ConstantUnion[leftSize*rightSize];
1494 for(int row = 0; row < leftSize; row++) {
1495 for(int column = 0; column < rightSize; column++) {
1496 tempConstArray[leftSize * column + row].setFConst(unionArray[row].getFConst() * rightUnionArray[column].getFConst());
1497 }
1498 }
1499 // update return type for outer product
1500 returnType.setNominalSize(static_cast<unsigned char>(rightSize));
1501 returnType.setSecondarySize(static_cast<unsigned char>(leftSize));
1502 }
1503 break;
1504
1505 case EOpTranspose:
1506 {
1507 int rightCol = node->getNominalSize();
1508 int rightRow = node->getSecondarySize();
1509 tempConstArray = new ConstantUnion[rightCol*rightRow];
1510 for(int row = 0; row < rightRow; row++) {
1511 for(int column = 0; column < rightCol; column++) {
1512 tempConstArray[rightRow * column + row].setFConst(rightUnionArray[rightCol * row + column].getFConst());
1513 }
1514 }
1515 // update return type for transpose
1516 returnType.setNominalSize(static_cast<unsigned char>(rightRow));
1517 returnType.setSecondarySize(static_cast<unsigned char>(rightCol));
1518 }
1519 break;
1520
1521 case EOpDeterminant:
1522 {
1523 ASSERT(node->getNominalSize() == node->getSecondarySize());
1524
1525 tempConstArray = new ConstantUnion[1];
1526 tempConstArray[0].setFConst(ComputeDeterminant(node->getNominalSize(), rightUnionArray));
1527 // update return type for determinant
1528 returnType.setNominalSize(1);
1529 returnType.setSecondarySize(1);
1530 }
1531 break;
1532
1533 case EOpInverse:
1534 {
1535 ASSERT(node->getNominalSize() == node->getSecondarySize());
1536
1537 tempConstArray = CreateInverse(node, rightUnionArray);
1538 if(!tempConstArray)
1539 {
1540 // Singular matrix, just copy
1541 tempConstArray = new ConstantUnion[objectSize];
1542 for(size_t i = 0; i < objectSize; i++)
1543 tempConstArray[i] = rightUnionArray[i];
1544 }
1545 }
1546 break;
1547
1548 case EOpDiv:
1549 case EOpIMod:
1550 tempConstArray = new ConstantUnion[objectSize];
1551 {// support MSVC++6.0
1552 for (size_t i = 0; i < objectSize; i++) {
1553 switch (getType().getBasicType()) {
1554 case EbtFloat:
1555 if (rightUnionArray[i] == 0.0f) {
1556 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1557 tempConstArray[i].setFConst(FLT_MAX);
1558 } else {
1559 ASSERT(op == EOpDiv);
1560 tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst());
1561 }
1562 break;
1563
1564 case EbtInt:
1565 if (rightUnionArray[i] == 0) {
1566 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1567 tempConstArray[i].setIConst(INT_MAX);
1568 } else {
1569 if(op == EOpDiv) {
1570 tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst());
1571 } else {
1572 ASSERT(op == EOpIMod);
1573 tempConstArray[i].setIConst(unionArray[i].getIConst() % rightUnionArray[i].getIConst());
1574 }
1575 }
1576 break;
1577 case EbtUInt:
1578 if (rightUnionArray[i] == 0) {
1579 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1580 tempConstArray[i].setUConst(UINT_MAX);
1581 } else {
1582 if(op == EOpDiv) {
1583 tempConstArray[i].setUConst(unionArray[i].getUConst() / rightUnionArray[i].getUConst());
1584 } else {
1585 ASSERT(op == EOpIMod);
1586 tempConstArray[i].setUConst(unionArray[i].getUConst() % rightUnionArray[i].getUConst());
1587 }
1588 }
1589 break;
1590 default:
1591 infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"/\"", getLine());
1592 return 0;
1593 }
1594 }
1595 }
1596 break;
1597
1598 case EOpMatrixTimesVector:
1599 if (node->getBasicType() != EbtFloat) {
1600 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix times vector", getLine());
1601 return 0;
1602 }
1603 tempConstArray = new ConstantUnion[getSecondarySize()];
1604
1605 {// support MSVC++6.0
1606 for (int rows = getSecondarySize(), i = 0; i < rows; i++) {
1607 tempConstArray[i].setFConst(0.0f);
1608 for (int cols = getNominalSize(), j = 0; j < cols; j++) {
1609 tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j*rows + i].getFConst()) * rightUnionArray[j].getFConst()));
1610 }
1611 }
1612 }
1613
1614 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtFloat, EbpUndefined, EvqConstExpr, getSecondarySize()));
1615 tempNode->setLine(getLine());
1616
1617 return tempNode;
1618
1619 case EOpVectorTimesMatrix:
1620 if (getType().getBasicType() != EbtFloat) {
1621 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for vector times matrix", getLine());
1622 return 0;
1623 }
1624
1625 tempConstArray = new ConstantUnion[node->getNominalSize()];
1626 {// support MSVC++6.0
1627 for (int cols = node->getNominalSize(), i = 0; i < cols; i++) {
1628 tempConstArray[i].setFConst(0.0f);
1629 for (int rows = node->getSecondarySize(), j = 0; j < rows; j++) {
1630 tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j].getFConst()) * rightUnionArray[i*rows + j].getFConst()));
1631 }
1632 }
1633 }
1634
1635 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtFloat, EbpUndefined, EvqConstExpr, node->getNominalSize()));
1636 tempNode->setLine(getLine());
1637 return tempNode;
1638
1639 case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
1640 tempConstArray = new ConstantUnion[objectSize];
1641 {// support MSVC++6.0
1642 for (size_t i = 0; i < objectSize; i++)
1643 tempConstArray[i] = unionArray[i] && rightUnionArray[i];
1644 }
1645 break;
1646
1647 case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
1648 tempConstArray = new ConstantUnion[objectSize];
1649 {// support MSVC++6.0
1650 for (size_t i = 0; i < objectSize; i++)
1651 tempConstArray[i] = unionArray[i] || rightUnionArray[i];
1652 }
1653 break;
1654
1655 case EOpLogicalXor:
1656 tempConstArray = new ConstantUnion[objectSize];
1657 {// support MSVC++6.0
1658 for (size_t i = 0; i < objectSize; i++)
1659 switch (getType().getBasicType()) {
1660 case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break;
1661 default: assert(false && "Default missing");
1662 }
1663 }
1664 break;
1665
1666 case EOpBitwiseAnd:
1667 tempConstArray = new ConstantUnion[objectSize];
1668 for(size_t i = 0; i < objectSize; i++)
1669 tempConstArray[i] = unionArray[i] & rightUnionArray[i];
1670 break;
1671 case EOpBitwiseXor:
1672 tempConstArray = new ConstantUnion[objectSize];
1673 for(size_t i = 0; i < objectSize; i++)
1674 tempConstArray[i] = unionArray[i] ^ rightUnionArray[i];
1675 break;
1676 case EOpBitwiseOr:
1677 tempConstArray = new ConstantUnion[objectSize];
1678 for(size_t i = 0; i < objectSize; i++)
1679 tempConstArray[i] = unionArray[i] | rightUnionArray[i];
1680 break;
1681 case EOpBitShiftLeft:
1682 tempConstArray = new ConstantUnion[objectSize];
1683 for(size_t i = 0; i < objectSize; i++)
1684 tempConstArray[i] = unionArray[i] << rightUnionArray[i];
1685 break;
1686 case EOpBitShiftRight:
1687 tempConstArray = new ConstantUnion[objectSize];
1688 for(size_t i = 0; i < objectSize; i++)
1689 tempConstArray[i] = unionArray[i] >> rightUnionArray[i];
1690 break;
1691
1692 case EOpLessThan:
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 EOpGreaterThan:
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 EOpLessThanEqual:
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 EOpGreaterThanEqual:
1711 tempConstArray = new ConstantUnion[objectSize];
1712 for(size_t i = 0; i < objectSize; i++)
1713 tempConstArray[i].setBConst(unionArray[i] >= rightUnionArray[i]);
1714 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr, objectSize);
1715 break;
1716 case EOpEqual:
1717 tempConstArray = new ConstantUnion[1];
1718
1719 if(getType().getBasicType() == EbtStruct) {
1720 tempConstArray->setBConst(CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray));
1721 } else {
1722 bool boolNodeFlag = true;
1723 for (size_t i = 0; i < objectSize; i++) {
1724 if (unionArray[i] != rightUnionArray[i]) {
1725 boolNodeFlag = false;
1726 break; // break out of for loop
1727 }
1728 }
1729 tempConstArray->setBConst(boolNodeFlag);
1730 }
1731
1732 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConstExpr));
1733 tempNode->setLine(getLine());
1734
1735 return tempNode;
1736
1737 case EOpNotEqual:
1738 tempConstArray = new ConstantUnion[1];
1739
1740 if(getType().getBasicType() == EbtStruct) {
1741 tempConstArray->setBConst(!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray));
1742 } else {
1743 bool boolNodeFlag = false;
1744 for (size_t i = 0; i < objectSize; i++) {
1745 if (unionArray[i] != rightUnionArray[i]) {
1746 boolNodeFlag = true;
1747 break; // break out of for loop
1748 }
1749 }
1750 tempConstArray->setBConst(boolNodeFlag);
1751 }
1752
1753 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConstExpr));
1754 tempNode->setLine(getLine());
1755
1756 return tempNode;
1757 case EOpMax:
1758 tempConstArray = new ConstantUnion[objectSize];
1759 {// support MSVC++6.0
1760 for (size_t i = 0; i < objectSize; i++)
1761 tempConstArray[i] = unionArray[i] > rightUnionArray[i] ? unionArray[i] : rightUnionArray[i];
1762 }
1763 break;
1764 case EOpMin:
1765 tempConstArray = new ConstantUnion[objectSize];
1766 {// support MSVC++6.0
1767 for (size_t i = 0; i < objectSize; i++)
1768 tempConstArray[i] = unionArray[i] < rightUnionArray[i] ? unionArray[i] : rightUnionArray[i];
1769 }
1770 break;
1771 default:
1772 return 0;
1773 }
1774 tempNode = new TIntermConstantUnion(tempConstArray, returnType);
1775 tempNode->setLine(getLine());
1776
1777 return tempNode;
1778 } else {
1779 //
1780 // Do unary operations
1781 //
1782 TIntermConstantUnion *newNode = 0;
1783 ConstantUnion* tempConstArray = new ConstantUnion[objectSize];
1784 TType type = getType();
1785 TBasicType basicType = type.getBasicType();
1786 for (size_t i = 0; i < objectSize; i++) {
1787 switch(op) {
1788 case EOpNegative:
1789 switch (basicType) {
1790 case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break;
1791 case EbtInt: tempConstArray[i].setIConst(-unionArray[i].getIConst()); break;
1792 default:
1793 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1794 return 0;
1795 }
1796 break;
1797 case EOpLogicalNot: // this code is written for possible future use, will not get executed currently
1798 switch (basicType) {
1799 case EbtBool: tempConstArray[i].setBConst(!unionArray[i].getBConst()); break;
1800 default:
1801 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1802 return 0;
1803 }
1804 break;
1805 case EOpBitwiseNot:
1806 switch(basicType) {
1807 case EbtInt: tempConstArray[i].setIConst(~unionArray[i].getIConst()); break;
1808 case EbtUInt: tempConstArray[i].setUConst(~unionArray[i].getUConst()); break;
1809 default:
1810 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1811 return 0;
1812 }
1813 break;
1814 case EOpRadians:
1815 switch(basicType) {
1816 case EbtFloat: tempConstArray[i].setFConst(unionArray[i].getFConst() * 1.74532925e-2f); break;
1817 default:
1818 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1819 return 0;
1820 }
1821 break;
1822 case EOpDegrees:
1823 switch(basicType) {
1824 case EbtFloat: tempConstArray[i].setFConst(unionArray[i].getFConst() * 5.72957795e+1f); break;
1825 default:
1826 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1827 return 0;
1828 }
1829 break;
1830 case EOpSin:
1831 switch(basicType) {
1832 case EbtFloat: tempConstArray[i].setFConst(sinf(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 EOpCos:
1839 switch(basicType) {
1840 case EbtFloat: tempConstArray[i].setFConst(cosf(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 EOpTan:
1847 switch(basicType) {
1848 case EbtFloat: tempConstArray[i].setFConst(tanf(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 EOpAsin:
1855 switch(basicType) {
1856 case EbtFloat: tempConstArray[i].setFConst(asinf(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 EOpAcos:
1863 switch(basicType) {
1864 case EbtFloat: tempConstArray[i].setFConst(acosf(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 EOpAtan:
1871 switch(basicType) {
1872 case EbtFloat: tempConstArray[i].setFConst(atanf(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 EOpSinh:
1879 switch(basicType) {
1880 case EbtFloat: tempConstArray[i].setFConst(sinhf(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 EOpCosh:
1887 switch(basicType) {
1888 case EbtFloat: tempConstArray[i].setFConst(coshf(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 EOpTanh:
1895 switch(basicType) {
1896 case EbtFloat: tempConstArray[i].setFConst(tanhf(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 EOpAsinh:
1903 switch(basicType) {
1904 case EbtFloat: tempConstArray[i].setFConst(asinhf(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 EOpAcosh:
1911 switch(basicType) {
1912 case EbtFloat: tempConstArray[i].setFConst(acoshf(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 EOpAtanh:
1919 switch(basicType) {
1920 case EbtFloat: tempConstArray[i].setFConst(atanhf(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 EOpLog:
1927 switch(basicType) {
1928 case EbtFloat: tempConstArray[i].setFConst(logf(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 EOpLog2:
1935 switch(basicType) {
1936 case EbtFloat: tempConstArray[i].setFConst(sw::log2(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 EOpExp:
1943 switch(basicType) {
1944 case EbtFloat: tempConstArray[i].setFConst(expf(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 EOpExp2:
1951 switch(basicType) {
1952 case EbtFloat: tempConstArray[i].setFConst(exp2f(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 EOpSqrt:
1959 switch(basicType) {
1960 case EbtFloat: tempConstArray[i].setFConst(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 case EOpInverseSqrt:
1967 switch(basicType) {
1968 case EbtFloat: tempConstArray[i].setFConst(1.0f / sqrtf(unionArray[i].getFConst())); break;
1969 default:
1970 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1971 return 0;
1972 }
1973 break;
1974 case EOpFloatBitsToInt:
1975 switch(basicType) {
1976 case EbtFloat:
1977 tempConstArray[i].setIConst(sw::bit_cast<int>(unionArray[i].getFConst()));
1978 type.setBasicType(EbtInt);
1979 break;
1980 default:
1981 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1982 return 0;
1983 }
1984 break;
1985 break;
1986 case EOpFloatBitsToUint:
1987 switch(basicType) {
1988 case EbtFloat:
1989 tempConstArray[i].setUConst(sw::bit_cast<unsigned int>(unionArray[i].getFConst()));
1990 type.setBasicType(EbtUInt);
1991 break;
1992 default:
1993 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1994 return 0;
1995 }
1996 break;
1997 case EOpIntBitsToFloat:
1998 switch(basicType) {
1999 case EbtInt:
2000 tempConstArray[i].setFConst(sw::bit_cast<float>(unionArray[i].getIConst()));
2001 type.setBasicType(EbtFloat);
2002 break;
2003 default:
2004 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
2005 return 0;
2006 }
2007 break;
2008 case EOpUintBitsToFloat:
2009 switch(basicType) {
2010 case EbtUInt:
2011 tempConstArray[i].setFConst(sw::bit_cast<float>(unionArray[i].getUConst()));
2012 type.setBasicType(EbtFloat);
2013 break;
2014 default:
2015 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
2016 return 0;
2017 }
2018 break;
2019 default:
2020 return 0;
2021 }
2022 }
2023 newNode = new TIntermConstantUnion(tempConstArray, type);
2024 newNode->setLine(getLine());
2025 return newNode;
2026 }
2027 }
2028
promoteConstantUnion(TBasicType promoteTo,TIntermConstantUnion * node)2029 TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node)
2030 {
2031 size_t size = node->getType().getObjectSize();
2032
2033 ConstantUnion *leftUnionArray = new ConstantUnion[size];
2034
2035 for(size_t i = 0; i < size; i++) {
2036 switch (promoteTo) {
2037 case EbtFloat:
2038 switch (node->getType().getBasicType()) {
2039 case EbtInt:
2040 leftUnionArray[i].setFConst(static_cast<float>(node->getIConst(i)));
2041 break;
2042 case EbtUInt:
2043 leftUnionArray[i].setFConst(static_cast<float>(node->getUConst(i)));
2044 break;
2045 case EbtBool:
2046 leftUnionArray[i].setFConst(static_cast<float>(node->getBConst(i)));
2047 break;
2048 case EbtFloat:
2049 leftUnionArray[i].setFConst(static_cast<float>(node->getFConst(i)));
2050 break;
2051 default:
2052 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
2053 return 0;
2054 }
2055 break;
2056 case EbtInt:
2057 switch (node->getType().getBasicType()) {
2058 case EbtInt:
2059 leftUnionArray[i].setIConst(static_cast<int>(node->getIConst(i)));
2060 break;
2061 case EbtUInt:
2062 leftUnionArray[i].setIConst(static_cast<int>(node->getUConst(i)));
2063 break;
2064 case EbtBool:
2065 leftUnionArray[i].setIConst(static_cast<int>(node->getBConst(i)));
2066 break;
2067 case EbtFloat:
2068 leftUnionArray[i].setIConst(static_cast<int>(node->getFConst(i)));
2069 break;
2070 default:
2071 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
2072 return 0;
2073 }
2074 break;
2075 case EbtUInt:
2076 switch (node->getType().getBasicType()) {
2077 case EbtInt:
2078 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getIConst(i)));
2079 break;
2080 case EbtUInt:
2081 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getUConst(i)));
2082 break;
2083 case EbtBool:
2084 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getBConst(i)));
2085 break;
2086 case EbtFloat:
2087 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getFConst(i)));
2088 break;
2089 default:
2090 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
2091 return 0;
2092 }
2093 break;
2094 case EbtBool:
2095 switch (node->getType().getBasicType()) {
2096 case EbtInt:
2097 leftUnionArray[i].setBConst(node->getIConst(i) != 0);
2098 break;
2099 case EbtUInt:
2100 leftUnionArray[i].setBConst(node->getUConst(i) != 0);
2101 break;
2102 case EbtBool:
2103 leftUnionArray[i].setBConst(node->getBConst(i));
2104 break;
2105 case EbtFloat:
2106 leftUnionArray[i].setBConst(node->getFConst(i) != 0.0f);
2107 break;
2108 default:
2109 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
2110 return 0;
2111 }
2112
2113 break;
2114 default:
2115 infoSink.info.message(EPrefixInternalError, "Incorrect data type found", node->getLine());
2116 return 0;
2117 }
2118
2119 }
2120
2121 const TType& t = node->getType();
2122
2123 return addConstantUnion(leftUnionArray, TType(promoteTo, t.getPrecision(), t.getQualifier(), t.getNominalSize(), t.getSecondarySize(), t.isArray()), node->getLine());
2124 }
2125
2126