1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/angle/src/compiler/Intermediate.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1442 @@ 1.4 +// 1.5 +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. 1.6 +// Use of this source code is governed by a BSD-style license that can be 1.7 +// found in the LICENSE file. 1.8 +// 1.9 + 1.10 +// 1.11 +// Build the intermediate representation. 1.12 +// 1.13 + 1.14 +#include <float.h> 1.15 +#include <limits.h> 1.16 +#include <algorithm> 1.17 + 1.18 +#include "compiler/HashNames.h" 1.19 +#include "compiler/localintermediate.h" 1.20 +#include "compiler/QualifierAlive.h" 1.21 +#include "compiler/RemoveTree.h" 1.22 + 1.23 +bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray); 1.24 + 1.25 +static TPrecision GetHigherPrecision( TPrecision left, TPrecision right ){ 1.26 + return left > right ? left : right; 1.27 +} 1.28 + 1.29 +const char* getOperatorString(TOperator op) { 1.30 + switch (op) { 1.31 + case EOpInitialize: return "="; 1.32 + case EOpAssign: return "="; 1.33 + case EOpAddAssign: return "+="; 1.34 + case EOpSubAssign: return "-="; 1.35 + case EOpDivAssign: return "/="; 1.36 + 1.37 + // Fall-through. 1.38 + case EOpMulAssign: 1.39 + case EOpVectorTimesMatrixAssign: 1.40 + case EOpVectorTimesScalarAssign: 1.41 + case EOpMatrixTimesScalarAssign: 1.42 + case EOpMatrixTimesMatrixAssign: return "*="; 1.43 + 1.44 + // Fall-through. 1.45 + case EOpIndexDirect: 1.46 + case EOpIndexIndirect: return "[]"; 1.47 + 1.48 + case EOpIndexDirectStruct: return "."; 1.49 + case EOpVectorSwizzle: return "."; 1.50 + case EOpAdd: return "+"; 1.51 + case EOpSub: return "-"; 1.52 + case EOpMul: return "*"; 1.53 + case EOpDiv: return "/"; 1.54 + case EOpMod: UNIMPLEMENTED(); break; 1.55 + case EOpEqual: return "=="; 1.56 + case EOpNotEqual: return "!="; 1.57 + case EOpLessThan: return "<"; 1.58 + case EOpGreaterThan: return ">"; 1.59 + case EOpLessThanEqual: return "<="; 1.60 + case EOpGreaterThanEqual: return ">="; 1.61 + 1.62 + // Fall-through. 1.63 + case EOpVectorTimesScalar: 1.64 + case EOpVectorTimesMatrix: 1.65 + case EOpMatrixTimesVector: 1.66 + case EOpMatrixTimesScalar: 1.67 + case EOpMatrixTimesMatrix: return "*"; 1.68 + 1.69 + case EOpLogicalOr: return "||"; 1.70 + case EOpLogicalXor: return "^^"; 1.71 + case EOpLogicalAnd: return "&&"; 1.72 + case EOpNegative: return "-"; 1.73 + case EOpVectorLogicalNot: return "not"; 1.74 + case EOpLogicalNot: return "!"; 1.75 + case EOpPostIncrement: return "++"; 1.76 + case EOpPostDecrement: return "--"; 1.77 + case EOpPreIncrement: return "++"; 1.78 + case EOpPreDecrement: return "--"; 1.79 + 1.80 + // Fall-through. 1.81 + case EOpConvIntToBool: 1.82 + case EOpConvFloatToBool: return "bool"; 1.83 + 1.84 + // Fall-through. 1.85 + case EOpConvBoolToFloat: 1.86 + case EOpConvIntToFloat: return "float"; 1.87 + 1.88 + // Fall-through. 1.89 + case EOpConvFloatToInt: 1.90 + case EOpConvBoolToInt: return "int"; 1.91 + 1.92 + case EOpRadians: return "radians"; 1.93 + case EOpDegrees: return "degrees"; 1.94 + case EOpSin: return "sin"; 1.95 + case EOpCos: return "cos"; 1.96 + case EOpTan: return "tan"; 1.97 + case EOpAsin: return "asin"; 1.98 + case EOpAcos: return "acos"; 1.99 + case EOpAtan: return "atan"; 1.100 + case EOpExp: return "exp"; 1.101 + case EOpLog: return "log"; 1.102 + case EOpExp2: return "exp2"; 1.103 + case EOpLog2: return "log2"; 1.104 + case EOpSqrt: return "sqrt"; 1.105 + case EOpInverseSqrt: return "inversesqrt"; 1.106 + case EOpAbs: return "abs"; 1.107 + case EOpSign: return "sign"; 1.108 + case EOpFloor: return "floor"; 1.109 + case EOpCeil: return "ceil"; 1.110 + case EOpFract: return "fract"; 1.111 + case EOpLength: return "length"; 1.112 + case EOpNormalize: return "normalize"; 1.113 + case EOpDFdx: return "dFdx"; 1.114 + case EOpDFdy: return "dFdy"; 1.115 + case EOpFwidth: return "fwidth"; 1.116 + case EOpAny: return "any"; 1.117 + case EOpAll: return "all"; 1.118 + 1.119 + default: break; 1.120 + } 1.121 + return ""; 1.122 +} 1.123 + 1.124 +//////////////////////////////////////////////////////////////////////////// 1.125 +// 1.126 +// First set of functions are to help build the intermediate representation. 1.127 +// These functions are not member functions of the nodes. 1.128 +// They are called from parser productions. 1.129 +// 1.130 +///////////////////////////////////////////////////////////////////////////// 1.131 + 1.132 +// 1.133 +// Add a terminal node for an identifier in an expression. 1.134 +// 1.135 +// Returns the added node. 1.136 +// 1.137 +TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const TSourceLoc& line) 1.138 +{ 1.139 + TIntermSymbol* node = new TIntermSymbol(id, name, type); 1.140 + node->setLine(line); 1.141 + 1.142 + return node; 1.143 +} 1.144 + 1.145 +// 1.146 +// Connect two nodes with a new parent that does a binary operation on the nodes. 1.147 +// 1.148 +// Returns the added node. 1.149 +// 1.150 +TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line, TSymbolTable& symbolTable) 1.151 +{ 1.152 + switch (op) { 1.153 + case EOpEqual: 1.154 + case EOpNotEqual: 1.155 + if (left->isArray()) 1.156 + return 0; 1.157 + break; 1.158 + case EOpLessThan: 1.159 + case EOpGreaterThan: 1.160 + case EOpLessThanEqual: 1.161 + case EOpGreaterThanEqual: 1.162 + if (left->isMatrix() || left->isArray() || left->isVector() || left->getBasicType() == EbtStruct) { 1.163 + return 0; 1.164 + } 1.165 + break; 1.166 + case EOpLogicalOr: 1.167 + case EOpLogicalXor: 1.168 + case EOpLogicalAnd: 1.169 + if (left->getBasicType() != EbtBool || left->isMatrix() || left->isArray() || left->isVector()) { 1.170 + return 0; 1.171 + } 1.172 + break; 1.173 + case EOpAdd: 1.174 + case EOpSub: 1.175 + case EOpDiv: 1.176 + case EOpMul: 1.177 + if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool) 1.178 + return 0; 1.179 + default: break; 1.180 + } 1.181 + 1.182 + // 1.183 + // First try converting the children to compatible types. 1.184 + // 1.185 + if (left->getType().getStruct() && right->getType().getStruct()) { 1.186 + if (left->getType() != right->getType()) 1.187 + return 0; 1.188 + } else { 1.189 + TIntermTyped* child = addConversion(op, left->getType(), right); 1.190 + if (child) 1.191 + right = child; 1.192 + else { 1.193 + child = addConversion(op, right->getType(), left); 1.194 + if (child) 1.195 + left = child; 1.196 + else 1.197 + return 0; 1.198 + } 1.199 + } 1.200 + 1.201 + // 1.202 + // Need a new node holding things together then. Make 1.203 + // one and promote it to the right type. 1.204 + // 1.205 + TIntermBinary* node = new TIntermBinary(op); 1.206 + node->setLine(line); 1.207 + 1.208 + node->setLeft(left); 1.209 + node->setRight(right); 1.210 + if (!node->promote(infoSink)) 1.211 + return 0; 1.212 + 1.213 + // 1.214 + // See if we can fold constants. 1.215 + // 1.216 + TIntermTyped* typedReturnNode = 0; 1.217 + TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion(); 1.218 + TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion(); 1.219 + if (leftTempConstant && rightTempConstant) { 1.220 + typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink); 1.221 + 1.222 + if (typedReturnNode) 1.223 + return typedReturnNode; 1.224 + } 1.225 + 1.226 + return node; 1.227 +} 1.228 + 1.229 +// 1.230 +// Connect two nodes through an assignment. 1.231 +// 1.232 +// Returns the added node. 1.233 +// 1.234 +TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line) 1.235 +{ 1.236 + // 1.237 + // Like adding binary math, except the conversion can only go 1.238 + // from right to left. 1.239 + // 1.240 + TIntermBinary* node = new TIntermBinary(op); 1.241 + node->setLine(line); 1.242 + 1.243 + TIntermTyped* child = addConversion(op, left->getType(), right); 1.244 + if (child == 0) 1.245 + return 0; 1.246 + 1.247 + node->setLeft(left); 1.248 + node->setRight(child); 1.249 + if (! node->promote(infoSink)) 1.250 + return 0; 1.251 + 1.252 + return node; 1.253 +} 1.254 + 1.255 +// 1.256 +// Connect two nodes through an index operator, where the left node is the base 1.257 +// of an array or struct, and the right node is a direct or indirect offset. 1.258 +// 1.259 +// Returns the added node. 1.260 +// The caller should set the type of the returned node. 1.261 +// 1.262 +TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc& line) 1.263 +{ 1.264 + TIntermBinary* node = new TIntermBinary(op); 1.265 + node->setLine(line); 1.266 + node->setLeft(base); 1.267 + node->setRight(index); 1.268 + 1.269 + // caller should set the type 1.270 + 1.271 + return node; 1.272 +} 1.273 + 1.274 +// 1.275 +// Add one node as the parent of another that it operates on. 1.276 +// 1.277 +// Returns the added node. 1.278 +// 1.279 +TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, const TSourceLoc& line, TSymbolTable& symbolTable) 1.280 +{ 1.281 + TIntermUnary* node; 1.282 + TIntermTyped* child = childNode->getAsTyped(); 1.283 + 1.284 + if (child == 0) { 1.285 + infoSink.info.message(EPrefixInternalError, line, "Bad type in AddUnaryMath"); 1.286 + return 0; 1.287 + } 1.288 + 1.289 + switch (op) { 1.290 + case EOpLogicalNot: 1.291 + if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) { 1.292 + return 0; 1.293 + } 1.294 + break; 1.295 + 1.296 + case EOpPostIncrement: 1.297 + case EOpPreIncrement: 1.298 + case EOpPostDecrement: 1.299 + case EOpPreDecrement: 1.300 + case EOpNegative: 1.301 + if (child->getType().getBasicType() == EbtStruct || child->getType().isArray()) 1.302 + return 0; 1.303 + default: break; 1.304 + } 1.305 + 1.306 + // 1.307 + // Do we need to promote the operand? 1.308 + // 1.309 + // Note: Implicit promotions were removed from the language. 1.310 + // 1.311 + TBasicType newType = EbtVoid; 1.312 + switch (op) { 1.313 + case EOpConstructInt: newType = EbtInt; break; 1.314 + case EOpConstructBool: newType = EbtBool; break; 1.315 + case EOpConstructFloat: newType = EbtFloat; break; 1.316 + default: break; 1.317 + } 1.318 + 1.319 + if (newType != EbtVoid) { 1.320 + child = addConversion(op, TType(newType, child->getPrecision(), EvqTemporary, 1.321 + child->getNominalSize(), 1.322 + child->isMatrix(), 1.323 + child->isArray()), 1.324 + child); 1.325 + if (child == 0) 1.326 + return 0; 1.327 + } 1.328 + 1.329 + // 1.330 + // For constructors, we are now done, it's all in the conversion. 1.331 + // 1.332 + switch (op) { 1.333 + case EOpConstructInt: 1.334 + case EOpConstructBool: 1.335 + case EOpConstructFloat: 1.336 + return child; 1.337 + default: break; 1.338 + } 1.339 + 1.340 + TIntermConstantUnion *childTempConstant = 0; 1.341 + if (child->getAsConstantUnion()) 1.342 + childTempConstant = child->getAsConstantUnion(); 1.343 + 1.344 + // 1.345 + // Make a new node for the operator. 1.346 + // 1.347 + node = new TIntermUnary(op); 1.348 + node->setLine(line); 1.349 + node->setOperand(child); 1.350 + 1.351 + if (! node->promote(infoSink)) 1.352 + return 0; 1.353 + 1.354 + if (childTempConstant) { 1.355 + TIntermTyped* newChild = childTempConstant->fold(op, 0, infoSink); 1.356 + 1.357 + if (newChild) 1.358 + return newChild; 1.359 + } 1.360 + 1.361 + return node; 1.362 +} 1.363 + 1.364 +// 1.365 +// This is the safe way to change the operator on an aggregate, as it 1.366 +// does lots of error checking and fixing. Especially for establishing 1.367 +// a function call's operation on it's set of parameters. Sequences 1.368 +// of instructions are also aggregates, but they just direnctly set 1.369 +// their operator to EOpSequence. 1.370 +// 1.371 +// Returns an aggregate node, which could be the one passed in if 1.372 +// it was already an aggregate but no operator was set. 1.373 +// 1.374 +TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TSourceLoc& line) 1.375 +{ 1.376 + TIntermAggregate* aggNode; 1.377 + 1.378 + // 1.379 + // Make sure we have an aggregate. If not turn it into one. 1.380 + // 1.381 + if (node) { 1.382 + aggNode = node->getAsAggregate(); 1.383 + if (aggNode == 0 || aggNode->getOp() != EOpNull) { 1.384 + // 1.385 + // Make an aggregate containing this node. 1.386 + // 1.387 + aggNode = new TIntermAggregate(); 1.388 + aggNode->getSequence().push_back(node); 1.389 + } 1.390 + } else 1.391 + aggNode = new TIntermAggregate(); 1.392 + 1.393 + // 1.394 + // Set the operator. 1.395 + // 1.396 + aggNode->setOp(op); 1.397 + aggNode->setLine(line); 1.398 + 1.399 + return aggNode; 1.400 +} 1.401 + 1.402 +// 1.403 +// Convert one type to another. 1.404 +// 1.405 +// Returns the node representing the conversion, which could be the same 1.406 +// node passed in if no conversion was needed. 1.407 +// 1.408 +// Return 0 if a conversion can't be done. 1.409 +// 1.410 +TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TIntermTyped* node) 1.411 +{ 1.412 + // 1.413 + // Does the base type allow operation? 1.414 + // 1.415 + switch (node->getBasicType()) { 1.416 + case EbtVoid: 1.417 + case EbtSampler2D: 1.418 + case EbtSamplerCube: 1.419 + return 0; 1.420 + default: break; 1.421 + } 1.422 + 1.423 + // 1.424 + // Otherwise, if types are identical, no problem 1.425 + // 1.426 + if (type == node->getType()) 1.427 + return node; 1.428 + 1.429 + // 1.430 + // If one's a structure, then no conversions. 1.431 + // 1.432 + if (type.getStruct() || node->getType().getStruct()) 1.433 + return 0; 1.434 + 1.435 + // 1.436 + // If one's an array, then no conversions. 1.437 + // 1.438 + if (type.isArray() || node->getType().isArray()) 1.439 + return 0; 1.440 + 1.441 + TBasicType promoteTo; 1.442 + 1.443 + switch (op) { 1.444 + // 1.445 + // Explicit conversions 1.446 + // 1.447 + case EOpConstructBool: 1.448 + promoteTo = EbtBool; 1.449 + break; 1.450 + case EOpConstructFloat: 1.451 + promoteTo = EbtFloat; 1.452 + break; 1.453 + case EOpConstructInt: 1.454 + promoteTo = EbtInt; 1.455 + break; 1.456 + default: 1.457 + // 1.458 + // implicit conversions were removed from the language. 1.459 + // 1.460 + if (type.getBasicType() != node->getType().getBasicType()) 1.461 + return 0; 1.462 + // 1.463 + // Size and structure could still differ, but that's 1.464 + // handled by operator promotion. 1.465 + // 1.466 + return node; 1.467 + } 1.468 + 1.469 + if (node->getAsConstantUnion()) { 1.470 + 1.471 + return (promoteConstantUnion(promoteTo, node->getAsConstantUnion())); 1.472 + } else { 1.473 + 1.474 + // 1.475 + // Add a new newNode for the conversion. 1.476 + // 1.477 + TIntermUnary* newNode = 0; 1.478 + 1.479 + TOperator newOp = EOpNull; 1.480 + switch (promoteTo) { 1.481 + case EbtFloat: 1.482 + switch (node->getBasicType()) { 1.483 + case EbtInt: newOp = EOpConvIntToFloat; break; 1.484 + case EbtBool: newOp = EOpConvBoolToFloat; break; 1.485 + default: 1.486 + infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node"); 1.487 + return 0; 1.488 + } 1.489 + break; 1.490 + case EbtBool: 1.491 + switch (node->getBasicType()) { 1.492 + case EbtInt: newOp = EOpConvIntToBool; break; 1.493 + case EbtFloat: newOp = EOpConvFloatToBool; break; 1.494 + default: 1.495 + infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node"); 1.496 + return 0; 1.497 + } 1.498 + break; 1.499 + case EbtInt: 1.500 + switch (node->getBasicType()) { 1.501 + case EbtBool: newOp = EOpConvBoolToInt; break; 1.502 + case EbtFloat: newOp = EOpConvFloatToInt; break; 1.503 + default: 1.504 + infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node"); 1.505 + return 0; 1.506 + } 1.507 + break; 1.508 + default: 1.509 + infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion type"); 1.510 + return 0; 1.511 + } 1.512 + 1.513 + TType type(promoteTo, node->getPrecision(), EvqTemporary, node->getNominalSize(), node->isMatrix(), node->isArray()); 1.514 + newNode = new TIntermUnary(newOp, type); 1.515 + newNode->setLine(node->getLine()); 1.516 + newNode->setOperand(node); 1.517 + 1.518 + return newNode; 1.519 + } 1.520 +} 1.521 + 1.522 +// 1.523 +// Safe way to combine two nodes into an aggregate. Works with null pointers, 1.524 +// a node that's not a aggregate yet, etc. 1.525 +// 1.526 +// Returns the resulting aggregate, unless 0 was passed in for 1.527 +// both existing nodes. 1.528 +// 1.529 +TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc& line) 1.530 +{ 1.531 + if (left == 0 && right == 0) 1.532 + return 0; 1.533 + 1.534 + TIntermAggregate* aggNode = 0; 1.535 + if (left) 1.536 + aggNode = left->getAsAggregate(); 1.537 + if (!aggNode || aggNode->getOp() != EOpNull) { 1.538 + aggNode = new TIntermAggregate; 1.539 + if (left) 1.540 + aggNode->getSequence().push_back(left); 1.541 + } 1.542 + 1.543 + if (right) 1.544 + aggNode->getSequence().push_back(right); 1.545 + 1.546 + aggNode->setLine(line); 1.547 + 1.548 + return aggNode; 1.549 +} 1.550 + 1.551 +// 1.552 +// Turn an existing node into an aggregate. 1.553 +// 1.554 +// Returns an aggregate, unless 0 was passed in for the existing node. 1.555 +// 1.556 +TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, const TSourceLoc& line) 1.557 +{ 1.558 + if (node == 0) 1.559 + return 0; 1.560 + 1.561 + TIntermAggregate* aggNode = new TIntermAggregate; 1.562 + aggNode->getSequence().push_back(node); 1.563 + aggNode->setLine(line); 1.564 + 1.565 + return aggNode; 1.566 +} 1.567 + 1.568 +// 1.569 +// For "if" test nodes. There are three children; a condition, 1.570 +// a true path, and a false path. The two paths are in the 1.571 +// nodePair. 1.572 +// 1.573 +// Returns the selection node created. 1.574 +// 1.575 +TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, const TSourceLoc& line) 1.576 +{ 1.577 + // 1.578 + // For compile time constant selections, prune the code and 1.579 + // test now. 1.580 + // 1.581 + 1.582 + if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion()) { 1.583 + if (cond->getAsConstantUnion()->getBConst(0) == true) 1.584 + return nodePair.node1 ? setAggregateOperator(nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL; 1.585 + else 1.586 + return nodePair.node2 ? setAggregateOperator(nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL; 1.587 + } 1.588 + 1.589 + TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2); 1.590 + node->setLine(line); 1.591 + 1.592 + return node; 1.593 +} 1.594 + 1.595 + 1.596 +TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line) 1.597 +{ 1.598 + if (left->getType().getQualifier() == EvqConst && right->getType().getQualifier() == EvqConst) { 1.599 + return right; 1.600 + } else { 1.601 + TIntermTyped *commaAggregate = growAggregate(left, right, line); 1.602 + commaAggregate->getAsAggregate()->setOp(EOpComma); 1.603 + commaAggregate->setType(right->getType()); 1.604 + commaAggregate->getTypePointer()->setQualifier(EvqTemporary); 1.605 + return commaAggregate; 1.606 + } 1.607 +} 1.608 + 1.609 +// 1.610 +// For "?:" test nodes. There are three children; a condition, 1.611 +// a true path, and a false path. The two paths are specified 1.612 +// as separate parameters. 1.613 +// 1.614 +// Returns the selection node created, or 0 if one could not be. 1.615 +// 1.616 +TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc& line) 1.617 +{ 1.618 + // 1.619 + // Get compatible types. 1.620 + // 1.621 + TIntermTyped* child = addConversion(EOpSequence, trueBlock->getType(), falseBlock); 1.622 + if (child) 1.623 + falseBlock = child; 1.624 + else { 1.625 + child = addConversion(EOpSequence, falseBlock->getType(), trueBlock); 1.626 + if (child) 1.627 + trueBlock = child; 1.628 + else 1.629 + return 0; 1.630 + } 1.631 + 1.632 + // 1.633 + // See if all the operands are constant, then fold it otherwise not. 1.634 + // 1.635 + 1.636 + if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) { 1.637 + if (cond->getAsConstantUnion()->getBConst(0)) 1.638 + return trueBlock; 1.639 + else 1.640 + return falseBlock; 1.641 + } 1.642 + 1.643 + // 1.644 + // Make a selection node. 1.645 + // 1.646 + TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType()); 1.647 + node->getTypePointer()->setQualifier(EvqTemporary); 1.648 + node->setLine(line); 1.649 + 1.650 + return node; 1.651 +} 1.652 + 1.653 +// 1.654 +// Constant terminal nodes. Has a union that contains bool, float or int constants 1.655 +// 1.656 +// Returns the constant union node created. 1.657 +// 1.658 + 1.659 +TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, const TSourceLoc& line) 1.660 +{ 1.661 + TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t); 1.662 + node->setLine(line); 1.663 + 1.664 + return node; 1.665 +} 1.666 + 1.667 +TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, const TSourceLoc& line) 1.668 +{ 1.669 + 1.670 + TIntermAggregate* node = new TIntermAggregate(EOpSequence); 1.671 + 1.672 + node->setLine(line); 1.673 + TIntermConstantUnion* constIntNode; 1.674 + TIntermSequence &sequenceVector = node->getSequence(); 1.675 + ConstantUnion* unionArray; 1.676 + 1.677 + for (int i = 0; i < fields.num; i++) { 1.678 + unionArray = new ConstantUnion[1]; 1.679 + unionArray->setIConst(fields.offsets[i]); 1.680 + constIntNode = addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), line); 1.681 + sequenceVector.push_back(constIntNode); 1.682 + } 1.683 + 1.684 + return node; 1.685 +} 1.686 + 1.687 +// 1.688 +// Create loop nodes. 1.689 +// 1.690 +TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTyped* cond, TIntermTyped* expr, TIntermNode* body, const TSourceLoc& line) 1.691 +{ 1.692 + TIntermNode* node = new TIntermLoop(type, init, cond, expr, body); 1.693 + node->setLine(line); 1.694 + 1.695 + return node; 1.696 +} 1.697 + 1.698 +// 1.699 +// Add branches. 1.700 +// 1.701 +TIntermBranch* TIntermediate::addBranch(TOperator branchOp, const TSourceLoc& line) 1.702 +{ 1.703 + return addBranch(branchOp, 0, line); 1.704 +} 1.705 + 1.706 +TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, const TSourceLoc& line) 1.707 +{ 1.708 + TIntermBranch* node = new TIntermBranch(branchOp, expression); 1.709 + node->setLine(line); 1.710 + 1.711 + return node; 1.712 +} 1.713 + 1.714 +// 1.715 +// This is to be executed once the final root is put on top by the parsing 1.716 +// process. 1.717 +// 1.718 +bool TIntermediate::postProcess(TIntermNode* root) 1.719 +{ 1.720 + if (root == 0) 1.721 + return true; 1.722 + 1.723 + // 1.724 + // First, finish off the top level sequence, if any 1.725 + // 1.726 + TIntermAggregate* aggRoot = root->getAsAggregate(); 1.727 + if (aggRoot && aggRoot->getOp() == EOpNull) 1.728 + aggRoot->setOp(EOpSequence); 1.729 + 1.730 + return true; 1.731 +} 1.732 + 1.733 +// 1.734 +// This deletes the tree. 1.735 +// 1.736 +void TIntermediate::remove(TIntermNode* root) 1.737 +{ 1.738 + if (root) 1.739 + RemoveAllTreeNodes(root); 1.740 +} 1.741 + 1.742 +//////////////////////////////////////////////////////////////// 1.743 +// 1.744 +// Member functions of the nodes used for building the tree. 1.745 +// 1.746 +//////////////////////////////////////////////////////////////// 1.747 + 1.748 +// 1.749 +// Say whether or not an operation node changes the value of a variable. 1.750 +// 1.751 +// Returns true if state is modified. 1.752 +// 1.753 +bool TIntermOperator::modifiesState() const 1.754 +{ 1.755 + switch (op) { 1.756 + case EOpPostIncrement: 1.757 + case EOpPostDecrement: 1.758 + case EOpPreIncrement: 1.759 + case EOpPreDecrement: 1.760 + case EOpAssign: 1.761 + case EOpAddAssign: 1.762 + case EOpSubAssign: 1.763 + case EOpMulAssign: 1.764 + case EOpVectorTimesMatrixAssign: 1.765 + case EOpVectorTimesScalarAssign: 1.766 + case EOpMatrixTimesScalarAssign: 1.767 + case EOpMatrixTimesMatrixAssign: 1.768 + case EOpDivAssign: 1.769 + return true; 1.770 + default: 1.771 + return false; 1.772 + } 1.773 +} 1.774 + 1.775 +// 1.776 +// returns true if the operator is for one of the constructors 1.777 +// 1.778 +bool TIntermOperator::isConstructor() const 1.779 +{ 1.780 + switch (op) { 1.781 + case EOpConstructVec2: 1.782 + case EOpConstructVec3: 1.783 + case EOpConstructVec4: 1.784 + case EOpConstructMat2: 1.785 + case EOpConstructMat3: 1.786 + case EOpConstructMat4: 1.787 + case EOpConstructFloat: 1.788 + case EOpConstructIVec2: 1.789 + case EOpConstructIVec3: 1.790 + case EOpConstructIVec4: 1.791 + case EOpConstructInt: 1.792 + case EOpConstructBVec2: 1.793 + case EOpConstructBVec3: 1.794 + case EOpConstructBVec4: 1.795 + case EOpConstructBool: 1.796 + case EOpConstructStruct: 1.797 + return true; 1.798 + default: 1.799 + return false; 1.800 + } 1.801 +} 1.802 +// 1.803 +// Make sure the type of a unary operator is appropriate for its 1.804 +// combination of operation and operand type. 1.805 +// 1.806 +// Returns false in nothing makes sense. 1.807 +// 1.808 +bool TIntermUnary::promote(TInfoSink&) 1.809 +{ 1.810 + switch (op) { 1.811 + case EOpLogicalNot: 1.812 + if (operand->getBasicType() != EbtBool) 1.813 + return false; 1.814 + break; 1.815 + case EOpNegative: 1.816 + case EOpPostIncrement: 1.817 + case EOpPostDecrement: 1.818 + case EOpPreIncrement: 1.819 + case EOpPreDecrement: 1.820 + if (operand->getBasicType() == EbtBool) 1.821 + return false; 1.822 + break; 1.823 + 1.824 + // operators for built-ins are already type checked against their prototype 1.825 + case EOpAny: 1.826 + case EOpAll: 1.827 + case EOpVectorLogicalNot: 1.828 + return true; 1.829 + 1.830 + default: 1.831 + if (operand->getBasicType() != EbtFloat) 1.832 + return false; 1.833 + } 1.834 + 1.835 + setType(operand->getType()); 1.836 + type.setQualifier(EvqTemporary); 1.837 + 1.838 + return true; 1.839 +} 1.840 + 1.841 +// 1.842 +// Establishes the type of the resultant operation, as well as 1.843 +// makes the operator the correct one for the operands. 1.844 +// 1.845 +// Returns false if operator can't work on operands. 1.846 +// 1.847 +bool TIntermBinary::promote(TInfoSink& infoSink) 1.848 +{ 1.849 + // This function only handles scalars, vectors, and matrices. 1.850 + if (left->isArray() || right->isArray()) { 1.851 + infoSink.info.message(EPrefixInternalError, getLine(), "Invalid operation for arrays"); 1.852 + return false; 1.853 + } 1.854 + 1.855 + // GLSL ES 2.0 does not support implicit type casting. 1.856 + // So the basic type should always match. 1.857 + if (left->getBasicType() != right->getBasicType()) 1.858 + return false; 1.859 + 1.860 + // 1.861 + // Base assumption: just make the type the same as the left 1.862 + // operand. Then only deviations from this need be coded. 1.863 + // 1.864 + setType(left->getType()); 1.865 + 1.866 + // The result gets promoted to the highest precision. 1.867 + TPrecision higherPrecision = GetHigherPrecision(left->getPrecision(), right->getPrecision()); 1.868 + getTypePointer()->setPrecision(higherPrecision); 1.869 + 1.870 + // Binary operations results in temporary variables unless both 1.871 + // operands are const. 1.872 + if (left->getQualifier() != EvqConst || right->getQualifier() != EvqConst) { 1.873 + getTypePointer()->setQualifier(EvqTemporary); 1.874 + } 1.875 + 1.876 + int size = std::max(left->getNominalSize(), right->getNominalSize()); 1.877 + 1.878 + // 1.879 + // All scalars. Code after this test assumes this case is removed! 1.880 + // 1.881 + if (size == 1) { 1.882 + switch (op) { 1.883 + // 1.884 + // Promote to conditional 1.885 + // 1.886 + case EOpEqual: 1.887 + case EOpNotEqual: 1.888 + case EOpLessThan: 1.889 + case EOpGreaterThan: 1.890 + case EOpLessThanEqual: 1.891 + case EOpGreaterThanEqual: 1.892 + setType(TType(EbtBool, EbpUndefined)); 1.893 + break; 1.894 + 1.895 + // 1.896 + // And and Or operate on conditionals 1.897 + // 1.898 + case EOpLogicalAnd: 1.899 + case EOpLogicalOr: 1.900 + // Both operands must be of type bool. 1.901 + if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool) 1.902 + return false; 1.903 + setType(TType(EbtBool, EbpUndefined)); 1.904 + break; 1.905 + 1.906 + default: 1.907 + break; 1.908 + } 1.909 + return true; 1.910 + } 1.911 + 1.912 + // If we reach here, at least one of the operands is vector or matrix. 1.913 + // The other operand could be a scalar, vector, or matrix. 1.914 + // Are the sizes compatible? 1.915 + // 1.916 + if (left->getNominalSize() != right->getNominalSize()) { 1.917 + // If the nominal size of operands do not match: 1.918 + // One of them must be scalar. 1.919 + if (left->getNominalSize() != 1 && right->getNominalSize() != 1) 1.920 + return false; 1.921 + // Operator cannot be of type pure assignment. 1.922 + if (op == EOpAssign || op == EOpInitialize) 1.923 + return false; 1.924 + } 1.925 + 1.926 + // 1.927 + // Can these two operands be combined? 1.928 + // 1.929 + TBasicType basicType = left->getBasicType(); 1.930 + switch (op) { 1.931 + case EOpMul: 1.932 + if (!left->isMatrix() && right->isMatrix()) { 1.933 + if (left->isVector()) 1.934 + op = EOpVectorTimesMatrix; 1.935 + else { 1.936 + op = EOpMatrixTimesScalar; 1.937 + setType(TType(basicType, higherPrecision, EvqTemporary, size, true)); 1.938 + } 1.939 + } else if (left->isMatrix() && !right->isMatrix()) { 1.940 + if (right->isVector()) { 1.941 + op = EOpMatrixTimesVector; 1.942 + setType(TType(basicType, higherPrecision, EvqTemporary, size, false)); 1.943 + } else { 1.944 + op = EOpMatrixTimesScalar; 1.945 + } 1.946 + } else if (left->isMatrix() && right->isMatrix()) { 1.947 + op = EOpMatrixTimesMatrix; 1.948 + } else if (!left->isMatrix() && !right->isMatrix()) { 1.949 + if (left->isVector() && right->isVector()) { 1.950 + // leave as component product 1.951 + } else if (left->isVector() || right->isVector()) { 1.952 + op = EOpVectorTimesScalar; 1.953 + setType(TType(basicType, higherPrecision, EvqTemporary, size, false)); 1.954 + } 1.955 + } else { 1.956 + infoSink.info.message(EPrefixInternalError, getLine(), "Missing elses"); 1.957 + return false; 1.958 + } 1.959 + break; 1.960 + case EOpMulAssign: 1.961 + if (!left->isMatrix() && right->isMatrix()) { 1.962 + if (left->isVector()) 1.963 + op = EOpVectorTimesMatrixAssign; 1.964 + else { 1.965 + return false; 1.966 + } 1.967 + } else if (left->isMatrix() && !right->isMatrix()) { 1.968 + if (right->isVector()) { 1.969 + return false; 1.970 + } else { 1.971 + op = EOpMatrixTimesScalarAssign; 1.972 + } 1.973 + } else if (left->isMatrix() && right->isMatrix()) { 1.974 + op = EOpMatrixTimesMatrixAssign; 1.975 + } else if (!left->isMatrix() && !right->isMatrix()) { 1.976 + if (left->isVector() && right->isVector()) { 1.977 + // leave as component product 1.978 + } else if (left->isVector() || right->isVector()) { 1.979 + if (! left->isVector()) 1.980 + return false; 1.981 + op = EOpVectorTimesScalarAssign; 1.982 + setType(TType(basicType, higherPrecision, EvqTemporary, size, false)); 1.983 + } 1.984 + } else { 1.985 + infoSink.info.message(EPrefixInternalError, getLine(), "Missing elses"); 1.986 + return false; 1.987 + } 1.988 + break; 1.989 + 1.990 + case EOpAssign: 1.991 + case EOpInitialize: 1.992 + case EOpAdd: 1.993 + case EOpSub: 1.994 + case EOpDiv: 1.995 + case EOpAddAssign: 1.996 + case EOpSubAssign: 1.997 + case EOpDivAssign: 1.998 + if ((left->isMatrix() && right->isVector()) || 1.999 + (left->isVector() && right->isMatrix())) 1.1000 + return false; 1.1001 + setType(TType(basicType, higherPrecision, EvqTemporary, size, left->isMatrix() || right->isMatrix())); 1.1002 + break; 1.1003 + 1.1004 + case EOpEqual: 1.1005 + case EOpNotEqual: 1.1006 + case EOpLessThan: 1.1007 + case EOpGreaterThan: 1.1008 + case EOpLessThanEqual: 1.1009 + case EOpGreaterThanEqual: 1.1010 + if ((left->isMatrix() && right->isVector()) || 1.1011 + (left->isVector() && right->isMatrix())) 1.1012 + return false; 1.1013 + setType(TType(EbtBool, EbpUndefined)); 1.1014 + break; 1.1015 + 1.1016 + default: 1.1017 + return false; 1.1018 + } 1.1019 + 1.1020 + return true; 1.1021 +} 1.1022 + 1.1023 +bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray) 1.1024 +{ 1.1025 + const TFieldList& fields = leftNodeType.getStruct()->fields(); 1.1026 + 1.1027 + size_t structSize = fields.size(); 1.1028 + size_t index = 0; 1.1029 + 1.1030 + for (size_t j = 0; j < structSize; j++) { 1.1031 + size_t size = fields[j]->type()->getObjectSize(); 1.1032 + for (size_t i = 0; i < size; i++) { 1.1033 + if (fields[j]->type()->getBasicType() == EbtStruct) { 1.1034 + if (!CompareStructure(*(fields[j]->type()), &rightUnionArray[index], &leftUnionArray[index])) 1.1035 + return false; 1.1036 + } else { 1.1037 + if (leftUnionArray[index] != rightUnionArray[index]) 1.1038 + return false; 1.1039 + index++; 1.1040 + } 1.1041 + } 1.1042 + } 1.1043 + return true; 1.1044 +} 1.1045 + 1.1046 +bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray) 1.1047 +{ 1.1048 + if (leftNodeType.isArray()) { 1.1049 + TType typeWithoutArrayness = leftNodeType; 1.1050 + typeWithoutArrayness.clearArrayness(); 1.1051 + 1.1052 + size_t arraySize = leftNodeType.getArraySize(); 1.1053 + 1.1054 + for (size_t i = 0; i < arraySize; ++i) { 1.1055 + size_t offset = typeWithoutArrayness.getObjectSize() * i; 1.1056 + if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset])) 1.1057 + return false; 1.1058 + } 1.1059 + } else 1.1060 + return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray); 1.1061 + 1.1062 + return true; 1.1063 +} 1.1064 + 1.1065 +// 1.1066 +// The fold functions see if an operation on a constant can be done in place, 1.1067 +// without generating run-time code. 1.1068 +// 1.1069 +// Returns the node to keep using, which may or may not be the node passed in. 1.1070 +// 1.1071 + 1.1072 +TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink) 1.1073 +{ 1.1074 + ConstantUnion *unionArray = getUnionArrayPointer(); 1.1075 + size_t objectSize = getType().getObjectSize(); 1.1076 + 1.1077 + if (constantNode) { // binary operations 1.1078 + TIntermConstantUnion *node = constantNode->getAsConstantUnion(); 1.1079 + ConstantUnion *rightUnionArray = node->getUnionArrayPointer(); 1.1080 + TType returnType = getType(); 1.1081 + 1.1082 + // for a case like float f = 1.2 + vec4(2,3,4,5); 1.1083 + if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) { 1.1084 + rightUnionArray = new ConstantUnion[objectSize]; 1.1085 + for (size_t i = 0; i < objectSize; ++i) 1.1086 + rightUnionArray[i] = *node->getUnionArrayPointer(); 1.1087 + returnType = getType(); 1.1088 + } else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) { 1.1089 + // for a case like float f = vec4(2,3,4,5) + 1.2; 1.1090 + unionArray = new ConstantUnion[constantNode->getType().getObjectSize()]; 1.1091 + for (size_t i = 0; i < constantNode->getType().getObjectSize(); ++i) 1.1092 + unionArray[i] = *getUnionArrayPointer(); 1.1093 + returnType = node->getType(); 1.1094 + objectSize = constantNode->getType().getObjectSize(); 1.1095 + } 1.1096 + 1.1097 + ConstantUnion* tempConstArray = 0; 1.1098 + TIntermConstantUnion *tempNode; 1.1099 + 1.1100 + bool boolNodeFlag = false; 1.1101 + switch(op) { 1.1102 + case EOpAdd: 1.1103 + tempConstArray = new ConstantUnion[objectSize]; 1.1104 + {// support MSVC++6.0 1.1105 + for (size_t i = 0; i < objectSize; i++) 1.1106 + tempConstArray[i] = unionArray[i] + rightUnionArray[i]; 1.1107 + } 1.1108 + break; 1.1109 + case EOpSub: 1.1110 + tempConstArray = new ConstantUnion[objectSize]; 1.1111 + {// support MSVC++6.0 1.1112 + for (size_t i = 0; i < objectSize; i++) 1.1113 + tempConstArray[i] = unionArray[i] - rightUnionArray[i]; 1.1114 + } 1.1115 + break; 1.1116 + 1.1117 + case EOpMul: 1.1118 + case EOpVectorTimesScalar: 1.1119 + case EOpMatrixTimesScalar: 1.1120 + tempConstArray = new ConstantUnion[objectSize]; 1.1121 + {// support MSVC++6.0 1.1122 + for (size_t i = 0; i < objectSize; i++) 1.1123 + tempConstArray[i] = unionArray[i] * rightUnionArray[i]; 1.1124 + } 1.1125 + break; 1.1126 + case EOpMatrixTimesMatrix: 1.1127 + if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat) { 1.1128 + infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for matrix multiply"); 1.1129 + return 0; 1.1130 + } 1.1131 + {// support MSVC++6.0 1.1132 + int size = getNominalSize(); 1.1133 + tempConstArray = new ConstantUnion[size*size]; 1.1134 + for (int row = 0; row < size; row++) { 1.1135 + for (int column = 0; column < size; column++) { 1.1136 + tempConstArray[size * column + row].setFConst(0.0f); 1.1137 + for (int i = 0; i < size; i++) { 1.1138 + tempConstArray[size * column + row].setFConst(tempConstArray[size * column + row].getFConst() + unionArray[i * size + row].getFConst() * (rightUnionArray[column * size + i].getFConst())); 1.1139 + } 1.1140 + } 1.1141 + } 1.1142 + } 1.1143 + break; 1.1144 + case EOpDiv: 1.1145 + tempConstArray = new ConstantUnion[objectSize]; 1.1146 + {// support MSVC++6.0 1.1147 + for (size_t i = 0; i < objectSize; i++) { 1.1148 + switch (getType().getBasicType()) { 1.1149 + case EbtFloat: 1.1150 + if (rightUnionArray[i] == 0.0f) { 1.1151 + infoSink.info.message(EPrefixWarning, getLine(), "Divide by zero error during constant folding"); 1.1152 + tempConstArray[i].setFConst(unionArray[i].getFConst() < 0 ? -FLT_MAX : FLT_MAX); 1.1153 + } else 1.1154 + tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst()); 1.1155 + break; 1.1156 + 1.1157 + case EbtInt: 1.1158 + if (rightUnionArray[i] == 0) { 1.1159 + infoSink.info.message(EPrefixWarning, getLine(), "Divide by zero error during constant folding"); 1.1160 + tempConstArray[i].setIConst(INT_MAX); 1.1161 + } else 1.1162 + tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst()); 1.1163 + break; 1.1164 + default: 1.1165 + infoSink.info.message(EPrefixInternalError, getLine(), "Constant folding cannot be done for \"/\""); 1.1166 + return 0; 1.1167 + } 1.1168 + } 1.1169 + } 1.1170 + break; 1.1171 + 1.1172 + case EOpMatrixTimesVector: 1.1173 + if (node->getBasicType() != EbtFloat) { 1.1174 + infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for matrix times vector"); 1.1175 + return 0; 1.1176 + } 1.1177 + tempConstArray = new ConstantUnion[getNominalSize()]; 1.1178 + 1.1179 + {// support MSVC++6.0 1.1180 + for (int size = getNominalSize(), i = 0; i < size; i++) { 1.1181 + tempConstArray[i].setFConst(0.0f); 1.1182 + for (int j = 0; j < size; j++) { 1.1183 + tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j*size + i].getFConst()) * rightUnionArray[j].getFConst())); 1.1184 + } 1.1185 + } 1.1186 + } 1.1187 + 1.1188 + tempNode = new TIntermConstantUnion(tempConstArray, node->getType()); 1.1189 + tempNode->setLine(getLine()); 1.1190 + 1.1191 + return tempNode; 1.1192 + 1.1193 + case EOpVectorTimesMatrix: 1.1194 + if (getType().getBasicType() != EbtFloat) { 1.1195 + infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for vector times matrix"); 1.1196 + return 0; 1.1197 + } 1.1198 + 1.1199 + tempConstArray = new ConstantUnion[getNominalSize()]; 1.1200 + {// support MSVC++6.0 1.1201 + for (int size = getNominalSize(), i = 0; i < size; i++) { 1.1202 + tempConstArray[i].setFConst(0.0f); 1.1203 + for (int j = 0; j < size; j++) { 1.1204 + tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j].getFConst()) * rightUnionArray[i*size + j].getFConst())); 1.1205 + } 1.1206 + } 1.1207 + } 1.1208 + break; 1.1209 + 1.1210 + case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently 1.1211 + tempConstArray = new ConstantUnion[objectSize]; 1.1212 + {// support MSVC++6.0 1.1213 + for (size_t i = 0; i < objectSize; i++) 1.1214 + tempConstArray[i] = unionArray[i] && rightUnionArray[i]; 1.1215 + } 1.1216 + break; 1.1217 + 1.1218 + case EOpLogicalOr: // this code is written for possible future use, will not get executed currently 1.1219 + tempConstArray = new ConstantUnion[objectSize]; 1.1220 + {// support MSVC++6.0 1.1221 + for (size_t i = 0; i < objectSize; i++) 1.1222 + tempConstArray[i] = unionArray[i] || rightUnionArray[i]; 1.1223 + } 1.1224 + break; 1.1225 + 1.1226 + case EOpLogicalXor: 1.1227 + tempConstArray = new ConstantUnion[objectSize]; 1.1228 + {// support MSVC++6.0 1.1229 + for (size_t i = 0; i < objectSize; i++) 1.1230 + switch (getType().getBasicType()) { 1.1231 + case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break; 1.1232 + default: assert(false && "Default missing"); 1.1233 + } 1.1234 + } 1.1235 + break; 1.1236 + 1.1237 + case EOpLessThan: 1.1238 + assert(objectSize == 1); 1.1239 + tempConstArray = new ConstantUnion[1]; 1.1240 + tempConstArray->setBConst(*unionArray < *rightUnionArray); 1.1241 + returnType = TType(EbtBool, EbpUndefined, EvqConst); 1.1242 + break; 1.1243 + case EOpGreaterThan: 1.1244 + assert(objectSize == 1); 1.1245 + tempConstArray = new ConstantUnion[1]; 1.1246 + tempConstArray->setBConst(*unionArray > *rightUnionArray); 1.1247 + returnType = TType(EbtBool, EbpUndefined, EvqConst); 1.1248 + break; 1.1249 + case EOpLessThanEqual: 1.1250 + { 1.1251 + assert(objectSize == 1); 1.1252 + ConstantUnion constant; 1.1253 + constant.setBConst(*unionArray > *rightUnionArray); 1.1254 + tempConstArray = new ConstantUnion[1]; 1.1255 + tempConstArray->setBConst(!constant.getBConst()); 1.1256 + returnType = TType(EbtBool, EbpUndefined, EvqConst); 1.1257 + break; 1.1258 + } 1.1259 + case EOpGreaterThanEqual: 1.1260 + { 1.1261 + assert(objectSize == 1); 1.1262 + ConstantUnion constant; 1.1263 + constant.setBConst(*unionArray < *rightUnionArray); 1.1264 + tempConstArray = new ConstantUnion[1]; 1.1265 + tempConstArray->setBConst(!constant.getBConst()); 1.1266 + returnType = TType(EbtBool, EbpUndefined, EvqConst); 1.1267 + break; 1.1268 + } 1.1269 + 1.1270 + case EOpEqual: 1.1271 + if (getType().getBasicType() == EbtStruct) { 1.1272 + if (!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray)) 1.1273 + boolNodeFlag = true; 1.1274 + } else { 1.1275 + for (size_t i = 0; i < objectSize; i++) { 1.1276 + if (unionArray[i] != rightUnionArray[i]) { 1.1277 + boolNodeFlag = true; 1.1278 + break; // break out of for loop 1.1279 + } 1.1280 + } 1.1281 + } 1.1282 + 1.1283 + tempConstArray = new ConstantUnion[1]; 1.1284 + if (!boolNodeFlag) { 1.1285 + tempConstArray->setBConst(true); 1.1286 + } 1.1287 + else { 1.1288 + tempConstArray->setBConst(false); 1.1289 + } 1.1290 + 1.1291 + tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst)); 1.1292 + tempNode->setLine(getLine()); 1.1293 + 1.1294 + return tempNode; 1.1295 + 1.1296 + case EOpNotEqual: 1.1297 + if (getType().getBasicType() == EbtStruct) { 1.1298 + if (CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray)) 1.1299 + boolNodeFlag = true; 1.1300 + } else { 1.1301 + for (size_t i = 0; i < objectSize; i++) { 1.1302 + if (unionArray[i] == rightUnionArray[i]) { 1.1303 + boolNodeFlag = true; 1.1304 + break; // break out of for loop 1.1305 + } 1.1306 + } 1.1307 + } 1.1308 + 1.1309 + tempConstArray = new ConstantUnion[1]; 1.1310 + if (!boolNodeFlag) { 1.1311 + tempConstArray->setBConst(true); 1.1312 + } 1.1313 + else { 1.1314 + tempConstArray->setBConst(false); 1.1315 + } 1.1316 + 1.1317 + tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst)); 1.1318 + tempNode->setLine(getLine()); 1.1319 + 1.1320 + return tempNode; 1.1321 + 1.1322 + default: 1.1323 + infoSink.info.message(EPrefixInternalError, getLine(), "Invalid operator for constant folding"); 1.1324 + return 0; 1.1325 + } 1.1326 + tempNode = new TIntermConstantUnion(tempConstArray, returnType); 1.1327 + tempNode->setLine(getLine()); 1.1328 + 1.1329 + return tempNode; 1.1330 + } else { 1.1331 + // 1.1332 + // Do unary operations 1.1333 + // 1.1334 + TIntermConstantUnion *newNode = 0; 1.1335 + ConstantUnion* tempConstArray = new ConstantUnion[objectSize]; 1.1336 + for (size_t i = 0; i < objectSize; i++) { 1.1337 + switch(op) { 1.1338 + case EOpNegative: 1.1339 + switch (getType().getBasicType()) { 1.1340 + case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break; 1.1341 + case EbtInt: tempConstArray[i].setIConst(-unionArray[i].getIConst()); break; 1.1342 + default: 1.1343 + infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); 1.1344 + return 0; 1.1345 + } 1.1346 + break; 1.1347 + case EOpLogicalNot: // this code is written for possible future use, will not get executed currently 1.1348 + switch (getType().getBasicType()) { 1.1349 + case EbtBool: tempConstArray[i].setBConst(!unionArray[i].getBConst()); break; 1.1350 + default: 1.1351 + infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); 1.1352 + return 0; 1.1353 + } 1.1354 + break; 1.1355 + default: 1.1356 + return 0; 1.1357 + } 1.1358 + } 1.1359 + newNode = new TIntermConstantUnion(tempConstArray, getType()); 1.1360 + newNode->setLine(getLine()); 1.1361 + return newNode; 1.1362 + } 1.1363 +} 1.1364 + 1.1365 +TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node) 1.1366 +{ 1.1367 + size_t size = node->getType().getObjectSize(); 1.1368 + 1.1369 + ConstantUnion *leftUnionArray = new ConstantUnion[size]; 1.1370 + 1.1371 + for (size_t i = 0; i < size; i++) { 1.1372 + 1.1373 + switch (promoteTo) { 1.1374 + case EbtFloat: 1.1375 + switch (node->getType().getBasicType()) { 1.1376 + case EbtInt: 1.1377 + leftUnionArray[i].setFConst(static_cast<float>(node->getIConst(i))); 1.1378 + break; 1.1379 + case EbtBool: 1.1380 + leftUnionArray[i].setFConst(static_cast<float>(node->getBConst(i))); 1.1381 + break; 1.1382 + case EbtFloat: 1.1383 + leftUnionArray[i].setFConst(static_cast<float>(node->getFConst(i))); 1.1384 + break; 1.1385 + default: 1.1386 + infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote"); 1.1387 + return 0; 1.1388 + } 1.1389 + break; 1.1390 + case EbtInt: 1.1391 + switch (node->getType().getBasicType()) { 1.1392 + case EbtInt: 1.1393 + leftUnionArray[i].setIConst(static_cast<int>(node->getIConst(i))); 1.1394 + break; 1.1395 + case EbtBool: 1.1396 + leftUnionArray[i].setIConst(static_cast<int>(node->getBConst(i))); 1.1397 + break; 1.1398 + case EbtFloat: 1.1399 + leftUnionArray[i].setIConst(static_cast<int>(node->getFConst(i))); 1.1400 + break; 1.1401 + default: 1.1402 + infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote"); 1.1403 + return 0; 1.1404 + } 1.1405 + break; 1.1406 + case EbtBool: 1.1407 + switch (node->getType().getBasicType()) { 1.1408 + case EbtInt: 1.1409 + leftUnionArray[i].setBConst(node->getIConst(i) != 0); 1.1410 + break; 1.1411 + case EbtBool: 1.1412 + leftUnionArray[i].setBConst(node->getBConst(i)); 1.1413 + break; 1.1414 + case EbtFloat: 1.1415 + leftUnionArray[i].setBConst(node->getFConst(i) != 0.0f); 1.1416 + break; 1.1417 + default: 1.1418 + infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote"); 1.1419 + return 0; 1.1420 + } 1.1421 + 1.1422 + break; 1.1423 + default: 1.1424 + infoSink.info.message(EPrefixInternalError, node->getLine(), "Incorrect data type found"); 1.1425 + return 0; 1.1426 + } 1.1427 + 1.1428 + } 1.1429 + 1.1430 + const TType& t = node->getType(); 1.1431 + 1.1432 + return addConstantUnion(leftUnionArray, TType(promoteTo, t.getPrecision(), t.getQualifier(), t.getNominalSize(), t.isMatrix(), t.isArray()), node->getLine()); 1.1433 +} 1.1434 + 1.1435 +// static 1.1436 +TString TIntermTraverser::hash(const TString& name, ShHashFunction64 hashFunction) 1.1437 +{ 1.1438 + if (hashFunction == NULL || name.empty()) 1.1439 + return name; 1.1440 + khronos_uint64_t number = (*hashFunction)(name.c_str(), name.length()); 1.1441 + TStringStream stream; 1.1442 + stream << HASHED_NAME_PREFIX << std::hex << number; 1.1443 + TString hashedName = stream.str(); 1.1444 + return hashedName; 1.1445 +}