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