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