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