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.
8 // Build the intermediate representation.
15 #include "compiler/translator/Intermediate.h"
16 #include "compiler/translator/RemoveTree.h"
17 #include "compiler/translator/SymbolTable.h"
19 ////////////////////////////////////////////////////////////////////////////
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.
25 /////////////////////////////////////////////////////////////////////////////
28 // Add a terminal node for an identifier in an expression.
30 // Returns the added node.
32 TIntermSymbol *TIntermediate::addSymbol(
33 int id, const TString &name, const TType &type, const TSourceLoc &line)
35 TIntermSymbol *node = new TIntermSymbol(id, name, type);
42 // Connect two nodes with a new parent that does a binary operation on the nodes.
44 // Returns the added node.
46 TIntermTyped *TIntermediate::addBinaryMath(
47 TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line)
58 case EOpLessThanEqual:
59 case EOpGreaterThanEqual:
60 if (left->isMatrix() || left->isArray() || left->isVector() ||
61 left->getBasicType() == EbtStruct)
69 if (left->getBasicType() != EbtBool ||
70 left->isMatrix() || left->isArray() || left->isVector())
79 if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool)
85 if (left->getBasicType() != right->getBasicType())
91 // Need a new node holding things together then. Make
92 // one and promote it to the right type.
94 TIntermBinary *node = new TIntermBinary(op);
98 node->setRight(right);
99 if (!node->promote(mInfoSink))
103 // See if we can fold constants.
105 TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
106 TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
107 if (leftTempConstant && rightTempConstant)
109 TIntermTyped *typedReturnNode =
110 leftTempConstant->fold(node->getOp(), rightTempConstant, mInfoSink);
113 return typedReturnNode;
120 // Connect two nodes through an assignment.
122 // Returns the added node.
124 TIntermTyped *TIntermediate::addAssign(
125 TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line)
127 if (left->getType().getStruct() || right->getType().getStruct())
129 if (left->getType() != right->getType())
135 TIntermBinary *node = new TIntermBinary(op);
139 node->setRight(right);
140 if (!node->promote(mInfoSink))
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.
150 // Returns the added node.
151 // The caller should set the type of the returned node.
153 TIntermTyped *TIntermediate::addIndex(
154 TOperator op, TIntermTyped *base, TIntermTyped *index, const TSourceLoc &line)
156 TIntermBinary *node = new TIntermBinary(op);
159 node->setRight(index);
161 // caller should set the type
167 // Add one node as the parent of another that it operates on.
169 // Returns the added node.
171 TIntermTyped *TIntermediate::addUnaryMath(
172 TOperator op, TIntermNode *childNode, const TSourceLoc &line)
175 TIntermTyped *child = childNode->getAsTyped();
179 mInfoSink.info.message(EPrefixInternalError, line,
180 "Bad type in AddUnaryMath");
187 if (child->getType().getBasicType() != EbtBool ||
188 child->getType().isMatrix() ||
189 child->getType().isArray() ||
190 child->getType().isVector())
196 case EOpPostIncrement:
197 case EOpPreIncrement:
198 case EOpPostDecrement:
199 case EOpPreDecrement:
202 if (child->getType().getBasicType() == EbtStruct ||
203 child->getType().isArray())
211 TIntermConstantUnion *childTempConstant = 0;
212 if (child->getAsConstantUnion())
213 childTempConstant = child->getAsConstantUnion();
216 // Make a new node for the operator.
218 node = new TIntermUnary(op);
220 node->setOperand(child);
222 if (!node->promote(mInfoSink))
225 if (childTempConstant)
227 TIntermTyped *newChild = childTempConstant->fold(op, 0, mInfoSink);
237 // This is the safe way to change the operator on an aggregate, as it
238 // does lots of error checking and fixing. Especially for establishing
239 // a function call's operation on it's set of parameters. Sequences
240 // of instructions are also aggregates, but they just direnctly set
241 // their operator to EOpSequence.
243 // Returns an aggregate node, which could be the one passed in if
244 // it was already an aggregate but no operator was set.
246 TIntermAggregate *TIntermediate::setAggregateOperator(
247 TIntermNode *node, TOperator op, const TSourceLoc &line)
249 TIntermAggregate *aggNode;
252 // Make sure we have an aggregate. If not turn it into one.
256 aggNode = node->getAsAggregate();
257 if (aggNode == NULL || aggNode->getOp() != EOpNull)
260 // Make an aggregate containing this node.
262 aggNode = new TIntermAggregate();
263 aggNode->getSequence()->push_back(node);
268 aggNode = new TIntermAggregate();
275 aggNode->setLine(line);
281 // Safe way to combine two nodes into an aggregate. Works with null pointers,
282 // a node that's not a aggregate yet, etc.
284 // Returns the resulting aggregate, unless 0 was passed in for
285 // both existing nodes.
287 TIntermAggregate *TIntermediate::growAggregate(
288 TIntermNode *left, TIntermNode *right, const TSourceLoc &line)
290 if (left == NULL && right == NULL)
293 TIntermAggregate *aggNode = NULL;
295 aggNode = left->getAsAggregate();
296 if (!aggNode || aggNode->getOp() != EOpNull)
298 aggNode = new TIntermAggregate;
300 aggNode->getSequence()->push_back(left);
304 aggNode->getSequence()->push_back(right);
306 aggNode->setLine(line);
312 // Turn an existing node into an aggregate.
314 // Returns an aggregate, unless NULL was passed in for the existing node.
316 TIntermAggregate *TIntermediate::makeAggregate(
317 TIntermNode *node, const TSourceLoc &line)
322 TIntermAggregate *aggNode = new TIntermAggregate;
323 aggNode->getSequence()->push_back(node);
325 aggNode->setLine(line);
331 // For "if" test nodes. There are three children; a condition,
332 // a true path, and a false path. The two paths are in the
335 // Returns the selection node created.
337 TIntermNode *TIntermediate::addSelection(
338 TIntermTyped *cond, TIntermNodePair nodePair, const TSourceLoc &line)
341 // For compile time constant selections, prune the code and
345 if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion())
347 if (cond->getAsConstantUnion()->getBConst(0) == true)
349 return nodePair.node1 ? setAggregateOperator(
350 nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL;
354 return nodePair.node2 ? setAggregateOperator(
355 nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL;
359 TIntermSelection *node = new TIntermSelection(
360 cond, nodePair.node1, nodePair.node2);
366 TIntermTyped *TIntermediate::addComma(
367 TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line)
369 if (left->getType().getQualifier() == EvqConst &&
370 right->getType().getQualifier() == EvqConst)
376 TIntermTyped *commaAggregate = growAggregate(left, right, line);
377 commaAggregate->getAsAggregate()->setOp(EOpComma);
378 commaAggregate->setType(right->getType());
379 commaAggregate->getTypePointer()->setQualifier(EvqTemporary);
380 return commaAggregate;
385 // For "?:" test nodes. There are three children; a condition,
386 // a true path, and a false path. The two paths are specified
387 // as separate parameters.
389 // Returns the selection node created, or 0 if one could not be.
391 TIntermTyped *TIntermediate::addSelection(
392 TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock,
393 const TSourceLoc &line)
395 if (!cond || !trueBlock || !falseBlock ||
396 trueBlock->getType() != falseBlock->getType())
402 // See if all the operands are constant, then fold it otherwise not.
405 if (cond->getAsConstantUnion() &&
406 trueBlock->getAsConstantUnion() &&
407 falseBlock->getAsConstantUnion())
409 if (cond->getAsConstantUnion()->getBConst(0))
416 // Make a selection node.
418 TIntermSelection *node = new TIntermSelection(
419 cond, trueBlock, falseBlock, trueBlock->getType());
420 node->getTypePointer()->setQualifier(EvqTemporary);
427 // Constant terminal nodes. Has a union that contains bool, float or int constants
429 // Returns the constant union node created.
432 TIntermConstantUnion *TIntermediate::addConstantUnion(
433 ConstantUnion *unionArrayPointer, const TType &t, const TSourceLoc &line)
435 TIntermConstantUnion *node = new TIntermConstantUnion(unionArrayPointer, t);
441 TIntermTyped *TIntermediate::addSwizzle(
442 TVectorFields &fields, const TSourceLoc &line)
445 TIntermAggregate *node = new TIntermAggregate(EOpSequence);
448 TIntermConstantUnion *constIntNode;
449 TIntermSequence *sequenceVector = node->getSequence();
450 ConstantUnion *unionArray;
452 for (int i = 0; i < fields.num; i++)
454 unionArray = new ConstantUnion[1];
455 unionArray->setIConst(fields.offsets[i]);
456 constIntNode = addConstantUnion(
457 unionArray, TType(EbtInt, EbpUndefined, EvqConst), line);
458 sequenceVector->push_back(constIntNode);
465 // Create loop nodes.
467 TIntermNode *TIntermediate::addLoop(
468 TLoopType type, TIntermNode *init, TIntermTyped *cond, TIntermTyped *expr,
469 TIntermNode *body, const TSourceLoc &line)
471 TIntermNode *node = new TIntermLoop(type, init, cond, expr, body);
480 TIntermBranch* TIntermediate::addBranch(
481 TOperator branchOp, const TSourceLoc &line)
483 return addBranch(branchOp, 0, line);
486 TIntermBranch* TIntermediate::addBranch(
487 TOperator branchOp, TIntermTyped *expression, const TSourceLoc &line)
489 TIntermBranch *node = new TIntermBranch(branchOp, expression);
496 // This is to be executed once the final root is put on top by the parsing
499 bool TIntermediate::postProcess(TIntermNode *root)
505 // First, finish off the top level sequence, if any
507 TIntermAggregate *aggRoot = root->getAsAggregate();
508 if (aggRoot && aggRoot->getOp() == EOpNull)
509 aggRoot->setOp(EOpSequence);
515 // This deletes the tree.
517 void TIntermediate::remove(TIntermNode *root)
520 RemoveAllTreeNodes(root);