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