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