• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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