1 // 2 // Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 // 8 // Build the intermediate representation. 9 // 10 11 #include <float.h> 12 #include <limits.h> 13 #include <algorithm> 14 15 #include "compiler/translator/Intermediate.h" 16 #include "compiler/translator/RemoveTree.h" 17 #include "compiler/translator/SymbolTable.h" 18 19 //////////////////////////////////////////////////////////////////////////// 20 // 21 // First set of functions are to help build the intermediate representation. 22 // These functions are not member functions of the nodes. 23 // They are called from parser productions. 24 // 25 ///////////////////////////////////////////////////////////////////////////// 26 27 // 28 // Add a terminal node for an identifier in an expression. 29 // 30 // Returns the added node. 31 // 32 TIntermSymbol *TIntermediate::addSymbol( 33 int id, const TString &name, const TType &type, const TSourceLoc &line) 34 { 35 TIntermSymbol *node = new TIntermSymbol(id, name, type); 36 node->setLine(line); 37 38 return node; 39 } 40 41 // 42 // Connect two nodes with a new parent that does a binary operation on the nodes. 43 // 44 // Returns the added node. 45 // 46 TIntermTyped *TIntermediate::addBinaryMath( 47 TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line) 48 { 49 switch (op) 50 { 51 case EOpEqual: 52 case EOpNotEqual: 53 if (left->isArray()) 54 return NULL; 55 break; 56 case EOpLessThan: 57 case EOpGreaterThan: 58 case EOpLessThanEqual: 59 case EOpGreaterThanEqual: 60 if (left->isMatrix() || left->isArray() || left->isVector() || 61 left->getBasicType() == EbtStruct) 62 { 63 return NULL; 64 } 65 break; 66 case EOpLogicalOr: 67 case EOpLogicalXor: 68 case EOpLogicalAnd: 69 if (left->getBasicType() != EbtBool || 70 left->isMatrix() || left->isArray() || left->isVector()) 71 { 72 return NULL; 73 } 74 break; 75 case EOpAdd: 76 case EOpSub: 77 case EOpDiv: 78 case EOpMul: 79 if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool) 80 return NULL; 81 default: 82 break; 83 } 84 85 if (left->getBasicType() != right->getBasicType()) 86 { 87 return NULL; 88 } 89 90 // 91 // Need a new node holding things together then. Make 92 // one and promote it to the right type. 93 // 94 TIntermBinary *node = new TIntermBinary(op); 95 node->setLine(line); 96 97 node->setLeft(left); 98 node->setRight(right); 99 if (!node->promote(mInfoSink)) 100 return NULL; 101 102 // 103 // See if we can fold constants. 104 // 105 TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion(); 106 TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion(); 107 if (leftTempConstant && rightTempConstant) 108 { 109 TIntermTyped *typedReturnNode = 110 leftTempConstant->fold(node->getOp(), rightTempConstant, mInfoSink); 111 112 if (typedReturnNode) 113 return typedReturnNode; 114 } 115 116 return node; 117 } 118 119 // 120 // Connect two nodes through an assignment. 121 // 122 // Returns the added node. 123 // 124 TIntermTyped *TIntermediate::addAssign( 125 TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line) 126 { 127 if (left->getType().getStruct() || right->getType().getStruct()) 128 { 129 if (left->getType() != right->getType()) 130 { 131 return NULL; 132 } 133 } 134 135 TIntermBinary *node = new TIntermBinary(op); 136 node->setLine(line); 137 138 node->setLeft(left); 139 node->setRight(right); 140 if (!node->promote(mInfoSink)) 141 return NULL; 142 143 return node; 144 } 145 146 // 147 // Connect two nodes through an index operator, where the left node is the base 148 // of an array or struct, and the right node is a direct or indirect offset. 149 // 150 // Returns the added node. 151 // The caller should set the type of the returned node. 152 // 153 TIntermTyped *TIntermediate::addIndex( 154 TOperator op, TIntermTyped *base, TIntermTyped *index, const TSourceLoc &line) 155 { 156 TIntermBinary *node = new TIntermBinary(op); 157 node->setLine(line); 158 node->setLeft(base); 159 node->setRight(index); 160 161 // caller should set the type 162 163 return node; 164 } 165 166 // 167 // Add one node as the parent of another that it operates on. 168 // 169 // Returns the added node. 170 // 171 TIntermTyped *TIntermediate::addUnaryMath( 172 TOperator op, TIntermNode *childNode, const TSourceLoc &line) 173 { 174 TIntermUnary *node; 175 TIntermTyped *child = childNode->getAsTyped(); 176 177 if (child == NULL) 178 { 179 mInfoSink.info.message(EPrefixInternalError, line, 180 "Bad type in AddUnaryMath"); 181 return NULL; 182 } 183 184 switch (op) 185 { 186 case EOpLogicalNot: 187 if (child->getType().getBasicType() != EbtBool || 188 child->getType().isMatrix() || 189 child->getType().isArray() || 190 child->getType().isVector()) 191 { 192 return NULL; 193 } 194 break; 195 196 case EOpPostIncrement: 197 case EOpPreIncrement: 198 case EOpPostDecrement: 199 case EOpPreDecrement: 200 case EOpNegative: 201 if (child->getType().getBasicType() == EbtStruct || 202 child->getType().isArray()) 203 { 204 return NULL; 205 } 206 default: 207 break; 208 } 209 210 TIntermConstantUnion *childTempConstant = 0; 211 if (child->getAsConstantUnion()) 212 childTempConstant = child->getAsConstantUnion(); 213 214 // 215 // Make a new node for the operator. 216 // 217 node = new TIntermUnary(op); 218 node->setLine(line); 219 node->setOperand(child); 220 221 if (!node->promote(mInfoSink)) 222 return 0; 223 224 if (childTempConstant) 225 { 226 TIntermTyped *newChild = childTempConstant->fold(op, 0, mInfoSink); 227 228 if (newChild) 229 return newChild; 230 } 231 232 return node; 233 } 234 235 // 236 // This is the safe way to change the operator on an aggregate, as it 237 // does lots of error checking and fixing. Especially for establishing 238 // a function call's operation on it's set of parameters. Sequences 239 // of instructions are also aggregates, but they just direnctly set 240 // their operator to EOpSequence. 241 // 242 // Returns an aggregate node, which could be the one passed in if 243 // it was already an aggregate but no operator was set. 244 // 245 TIntermAggregate *TIntermediate::setAggregateOperator( 246 TIntermNode *node, TOperator op, const TSourceLoc &line) 247 { 248 TIntermAggregate *aggNode; 249 250 // 251 // Make sure we have an aggregate. If not turn it into one. 252 // 253 if (node) 254 { 255 aggNode = node->getAsAggregate(); 256 if (aggNode == NULL || aggNode->getOp() != EOpNull) 257 { 258 // 259 // Make an aggregate containing this node. 260 // 261 aggNode = new TIntermAggregate(); 262 aggNode->getSequence()->push_back(node); 263 } 264 } 265 else 266 { 267 aggNode = new TIntermAggregate(); 268 } 269 270 // 271 // Set the operator. 272 // 273 aggNode->setOp(op); 274 aggNode->setLine(line); 275 276 return aggNode; 277 } 278 279 // 280 // Safe way to combine two nodes into an aggregate. Works with null pointers, 281 // a node that's not a aggregate yet, etc. 282 // 283 // Returns the resulting aggregate, unless 0 was passed in for 284 // both existing nodes. 285 // 286 TIntermAggregate *TIntermediate::growAggregate( 287 TIntermNode *left, TIntermNode *right, const TSourceLoc &line) 288 { 289 if (left == NULL && right == NULL) 290 return NULL; 291 292 TIntermAggregate *aggNode = NULL; 293 if (left) 294 aggNode = left->getAsAggregate(); 295 if (!aggNode || aggNode->getOp() != EOpNull) 296 { 297 aggNode = new TIntermAggregate; 298 if (left) 299 aggNode->getSequence()->push_back(left); 300 } 301 302 if (right) 303 aggNode->getSequence()->push_back(right); 304 305 aggNode->setLine(line); 306 307 return aggNode; 308 } 309 310 // 311 // Turn an existing node into an aggregate. 312 // 313 // Returns an aggregate, unless NULL was passed in for the existing node. 314 // 315 TIntermAggregate *TIntermediate::makeAggregate( 316 TIntermNode *node, const TSourceLoc &line) 317 { 318 if (node == NULL) 319 return NULL; 320 321 TIntermAggregate *aggNode = new TIntermAggregate; 322 aggNode->getSequence()->push_back(node); 323 324 aggNode->setLine(line); 325 326 return aggNode; 327 } 328 329 // 330 // For "if" test nodes. There are three children; a condition, 331 // a true path, and a false path. The two paths are in the 332 // nodePair. 333 // 334 // Returns the selection node created. 335 // 336 TIntermNode *TIntermediate::addSelection( 337 TIntermTyped *cond, TIntermNodePair nodePair, const TSourceLoc &line) 338 { 339 // 340 // For compile time constant selections, prune the code and 341 // test now. 342 // 343 344 if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion()) 345 { 346 if (cond->getAsConstantUnion()->getBConst(0) == true) 347 { 348 return nodePair.node1 ? setAggregateOperator( 349 nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL; 350 } 351 else 352 { 353 return nodePair.node2 ? setAggregateOperator( 354 nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL; 355 } 356 } 357 358 TIntermSelection *node = new TIntermSelection( 359 cond, nodePair.node1, nodePair.node2); 360 node->setLine(line); 361 362 return node; 363 } 364 365 TIntermTyped *TIntermediate::addComma( 366 TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line) 367 { 368 if (left->getType().getQualifier() == EvqConst && 369 right->getType().getQualifier() == EvqConst) 370 { 371 return right; 372 } 373 else 374 { 375 TIntermTyped *commaAggregate = growAggregate(left, right, line); 376 commaAggregate->getAsAggregate()->setOp(EOpComma); 377 commaAggregate->setType(right->getType()); 378 commaAggregate->getTypePointer()->setQualifier(EvqTemporary); 379 return commaAggregate; 380 } 381 } 382 383 // 384 // For "?:" test nodes. There are three children; a condition, 385 // a true path, and a false path. The two paths are specified 386 // as separate parameters. 387 // 388 // Returns the selection node created, or 0 if one could not be. 389 // 390 TIntermTyped *TIntermediate::addSelection( 391 TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock, 392 const TSourceLoc &line) 393 { 394 if (!cond || !trueBlock || !falseBlock || 395 trueBlock->getType() != falseBlock->getType()) 396 { 397 return NULL; 398 } 399 400 // 401 // See if all the operands are constant, then fold it otherwise not. 402 // 403 404 if (cond->getAsConstantUnion() && 405 trueBlock->getAsConstantUnion() && 406 falseBlock->getAsConstantUnion()) 407 { 408 if (cond->getAsConstantUnion()->getBConst(0)) 409 return trueBlock; 410 else 411 return falseBlock; 412 } 413 414 // 415 // Make a selection node. 416 // 417 TIntermSelection *node = new TIntermSelection( 418 cond, trueBlock, falseBlock, trueBlock->getType()); 419 node->getTypePointer()->setQualifier(EvqTemporary); 420 node->setLine(line); 421 422 return node; 423 } 424 425 // 426 // Constant terminal nodes. Has a union that contains bool, float or int constants 427 // 428 // Returns the constant union node created. 429 // 430 431 TIntermConstantUnion *TIntermediate::addConstantUnion( 432 ConstantUnion *unionArrayPointer, const TType &t, const TSourceLoc &line) 433 { 434 TIntermConstantUnion *node = new TIntermConstantUnion(unionArrayPointer, t); 435 node->setLine(line); 436 437 return node; 438 } 439 440 TIntermTyped *TIntermediate::addSwizzle( 441 TVectorFields &fields, const TSourceLoc &line) 442 { 443 444 TIntermAggregate *node = new TIntermAggregate(EOpSequence); 445 446 node->setLine(line); 447 TIntermConstantUnion *constIntNode; 448 TIntermSequence *sequenceVector = node->getSequence(); 449 ConstantUnion *unionArray; 450 451 for (int i = 0; i < fields.num; i++) 452 { 453 unionArray = new ConstantUnion[1]; 454 unionArray->setIConst(fields.offsets[i]); 455 constIntNode = addConstantUnion( 456 unionArray, TType(EbtInt, EbpUndefined, EvqConst), line); 457 sequenceVector->push_back(constIntNode); 458 } 459 460 return node; 461 } 462 463 // 464 // Create loop nodes. 465 // 466 TIntermNode *TIntermediate::addLoop( 467 TLoopType type, TIntermNode *init, TIntermTyped *cond, TIntermTyped *expr, 468 TIntermNode *body, const TSourceLoc &line) 469 { 470 TIntermNode *node = new TIntermLoop(type, init, cond, expr, body); 471 node->setLine(line); 472 473 return node; 474 } 475 476 // 477 // Add branches. 478 // 479 TIntermBranch* TIntermediate::addBranch( 480 TOperator branchOp, const TSourceLoc &line) 481 { 482 return addBranch(branchOp, 0, line); 483 } 484 485 TIntermBranch* TIntermediate::addBranch( 486 TOperator branchOp, TIntermTyped *expression, const TSourceLoc &line) 487 { 488 TIntermBranch *node = new TIntermBranch(branchOp, expression); 489 node->setLine(line); 490 491 return node; 492 } 493 494 // 495 // This is to be executed once the final root is put on top by the parsing 496 // process. 497 // 498 bool TIntermediate::postProcess(TIntermNode *root) 499 { 500 if (root == NULL) 501 return true; 502 503 // 504 // First, finish off the top level sequence, if any 505 // 506 TIntermAggregate *aggRoot = root->getAsAggregate(); 507 if (aggRoot && aggRoot->getOp() == EOpNull) 508 aggRoot->setOp(EOpSequence); 509 510 return true; 511 } 512 513 // 514 // This deletes the tree. 515 // 516 void TIntermediate::remove(TIntermNode *root) 517 { 518 if (root) 519 RemoveAllTreeNodes(root); 520 } 521