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 // Definition of the in-memory high-level intermediate representation
     17 // of shaders.  This is a tree that parser creates.
     18 //
     19 // Nodes in the tree are defined as a hierarchy of classes derived from
     20 // TIntermNode. Each is a node in a tree.  There is no preset branching factor;
     21 // each node can have it's own type of list of children.
     22 //
     23 
     24 #ifndef __INTERMEDIATE_H
     25 #define __INTERMEDIATE_H
     26 
     27 #include "Common.h"
     28 #include "Types.h"
     29 #include "ConstantUnion.h"
     30 
     31 //
     32 // Operators used by the high-level (parse tree) representation.
     33 //
     34 enum TOperator {
     35 	EOpNull,            // if in a node, should only mean a node is still being built
     36 	EOpSequence,        // denotes a list of statements, or parameters, etc.
     37 	EOpFunctionCall,
     38 	EOpFunction,        // For function definition
     39 	EOpParameters,      // an aggregate listing the parameters to a function
     40 
     41 	EOpDeclaration,
     42 	EOpInvariantDeclaration, // Specialized declarations for attributing invariance
     43 	EOpPrototype,
     44 
     45 	//
     46 	// Unary operators
     47 	//
     48 
     49 	EOpNegative,
     50 	EOpLogicalNot,
     51 	EOpVectorLogicalNot,
     52 	EOpBitwiseNot,
     53 
     54 	EOpPostIncrement,
     55 	EOpPostDecrement,
     56 	EOpPreIncrement,
     57 	EOpPreDecrement,
     58 
     59 	//
     60 	// binary operations
     61 	//
     62 
     63 	EOpAdd,
     64 	EOpSub,
     65 	EOpMul,
     66 	EOpDiv,
     67 	EOpEqual,
     68 	EOpNotEqual,
     69 	EOpVectorEqual,
     70 	EOpVectorNotEqual,
     71 	EOpLessThan,
     72 	EOpGreaterThan,
     73 	EOpLessThanEqual,
     74 	EOpGreaterThanEqual,
     75 	EOpComma,
     76 
     77 	EOpOuterProduct,
     78 	EOpTranspose,
     79 	EOpDeterminant,
     80 	EOpInverse,
     81 
     82 	EOpVectorTimesScalar,
     83 	EOpVectorTimesMatrix,
     84 	EOpMatrixTimesVector,
     85 	EOpMatrixTimesScalar,
     86 
     87 	EOpLogicalOr,
     88 	EOpLogicalXor,
     89 	EOpLogicalAnd,
     90 
     91 	EOpIMod,
     92 	EOpBitShiftLeft,
     93 	EOpBitShiftRight,
     94 	EOpBitwiseAnd,
     95 	EOpBitwiseXor,
     96 	EOpBitwiseOr,
     97 
     98 	EOpIndexDirect,
     99 	EOpIndexIndirect,
    100 	EOpIndexDirectStruct,
    101 	EOpIndexDirectInterfaceBlock,
    102 
    103 	EOpVectorSwizzle,
    104 
    105 	//
    106 	// Built-in functions potentially mapped to operators
    107 	//
    108 
    109 	EOpRadians,
    110 	EOpDegrees,
    111 	EOpSin,
    112 	EOpCos,
    113 	EOpTan,
    114 	EOpAsin,
    115 	EOpAcos,
    116 	EOpAtan,
    117 	EOpSinh,
    118 	EOpCosh,
    119 	EOpTanh,
    120 	EOpAsinh,
    121 	EOpAcosh,
    122 	EOpAtanh,
    123 
    124 	EOpPow,
    125 	EOpExp,
    126 	EOpLog,
    127 	EOpExp2,
    128 	EOpLog2,
    129 	EOpSqrt,
    130 	EOpInverseSqrt,
    131 
    132 	EOpAbs,
    133 	EOpSign,
    134 	EOpFloor,
    135 	EOpTrunc,
    136 	EOpRound,
    137 	EOpRoundEven,
    138 	EOpCeil,
    139 	EOpFract,
    140 	EOpMod,
    141 	EOpModf,
    142 	EOpMin,
    143 	EOpMax,
    144 	EOpClamp,
    145 	EOpMix,
    146 	EOpStep,
    147 	EOpSmoothStep,
    148 	EOpIsNan,
    149 	EOpIsInf,
    150 	EOpFloatBitsToInt,
    151 	EOpFloatBitsToUint,
    152 	EOpIntBitsToFloat,
    153 	EOpUintBitsToFloat,
    154 	EOpPackSnorm2x16,
    155 	EOpPackUnorm2x16,
    156 	EOpPackHalf2x16,
    157 	EOpUnpackSnorm2x16,
    158 	EOpUnpackUnorm2x16,
    159 	EOpUnpackHalf2x16,
    160 
    161 	EOpLength,
    162 	EOpDistance,
    163 	EOpDot,
    164 	EOpCross,
    165 	EOpNormalize,
    166 	EOpFaceForward,
    167 	EOpReflect,
    168 	EOpRefract,
    169 
    170 	EOpDFdx,            // Fragment only, OES_standard_derivatives extension
    171 	EOpDFdy,            // Fragment only, OES_standard_derivatives extension
    172 	EOpFwidth,          // Fragment only, OES_standard_derivatives extension
    173 
    174 	EOpMatrixTimesMatrix,
    175 
    176 	EOpAny,
    177 	EOpAll,
    178 
    179 	//
    180 	// Branch
    181 	//
    182 
    183 	EOpKill,            // Fragment only
    184 	EOpReturn,
    185 	EOpBreak,
    186 	EOpContinue,
    187 
    188 	//
    189 	// Constructors
    190 	//
    191 
    192 	EOpConstructInt,
    193 	EOpConstructUInt,
    194 	EOpConstructBool,
    195 	EOpConstructFloat,
    196 	EOpConstructVec2,
    197 	EOpConstructVec3,
    198 	EOpConstructVec4,
    199 	EOpConstructBVec2,
    200 	EOpConstructBVec3,
    201 	EOpConstructBVec4,
    202 	EOpConstructIVec2,
    203 	EOpConstructIVec3,
    204 	EOpConstructIVec4,
    205 	EOpConstructUVec2,
    206 	EOpConstructUVec3,
    207 	EOpConstructUVec4,
    208 	EOpConstructMat2,
    209 	EOpConstructMat2x3,
    210 	EOpConstructMat2x4,
    211 	EOpConstructMat3x2,
    212 	EOpConstructMat3,
    213 	EOpConstructMat3x4,
    214 	EOpConstructMat4x2,
    215 	EOpConstructMat4x3,
    216 	EOpConstructMat4,
    217 	EOpConstructStruct,
    218 
    219 	//
    220 	// moves
    221 	//
    222 
    223 	EOpAssign,
    224 	EOpInitialize,
    225 	EOpAddAssign,
    226 	EOpSubAssign,
    227 	EOpMulAssign,
    228 	EOpVectorTimesMatrixAssign,
    229 	EOpVectorTimesScalarAssign,
    230 	EOpMatrixTimesScalarAssign,
    231 	EOpMatrixTimesMatrixAssign,
    232 	EOpDivAssign,
    233 	EOpIModAssign,
    234 	EOpBitShiftLeftAssign,
    235 	EOpBitShiftRightAssign,
    236 	EOpBitwiseAndAssign,
    237 	EOpBitwiseXorAssign,
    238 	EOpBitwiseOrAssign
    239 };
    240 
    241 extern const char* getOperatorString(TOperator op);
    242 
    243 class TIntermTraverser;
    244 class TIntermAggregate;
    245 class TIntermBinary;
    246 class TIntermUnary;
    247 class TIntermConstantUnion;
    248 class TIntermSelection;
    249 class TIntermTyped;
    250 class TIntermSymbol;
    251 class TIntermLoop;
    252 class TIntermBranch;
    253 class TInfoSink;
    254 class TIntermSwitch;
    255 class TIntermCase;
    256 
    257 //
    258 // Base class for the tree nodes
    259 //
    260 class TIntermNode {
    261 public:
    262 	POOL_ALLOCATOR_NEW_DELETE();
    263 
    264 	TIntermNode()
    265 	{
    266 		// TODO: Move this to TSourceLoc constructor
    267 		// after getting rid of TPublicType.
    268 		line.first_file = line.last_file = 0;
    269 		line.first_line = line.last_line = 0;
    270 	}
    271 
    272 	const TSourceLoc& getLine() const { return line; }
    273 	void setLine(const TSourceLoc& l) { line = l; }
    274 
    275 	virtual void traverse(TIntermTraverser*) = 0;
    276 	virtual TIntermTyped* getAsTyped() { return 0; }
    277 	virtual TIntermConstantUnion* getAsConstantUnion() { return 0; }
    278 	virtual TIntermAggregate* getAsAggregate() { return 0; }
    279 	virtual TIntermBinary* getAsBinaryNode() { return 0; }
    280 	virtual TIntermUnary* getAsUnaryNode() { return 0; }
    281 	virtual TIntermSelection* getAsSelectionNode() { return 0; }
    282 	virtual TIntermSymbol* getAsSymbolNode() { return 0; }
    283 	virtual TIntermLoop* getAsLoopNode() { return 0; }
    284 	virtual TIntermBranch* getAsBranchNode() { return 0; }
    285 	virtual TIntermSwitch *getAsSwitchNode() { return 0; }
    286 	virtual TIntermCase *getAsCaseNode() { return 0; }
    287 	virtual ~TIntermNode() { }
    288 
    289 protected:
    290 	TSourceLoc line;
    291 };
    292 
    293 //
    294 // This is just to help yacc.
    295 //
    296 struct TIntermNodePair {
    297 	TIntermNode* node1;
    298 	TIntermNode* node2;
    299 };
    300 
    301 //
    302 // Intermediate class for nodes that have a type.
    303 //
    304 class TIntermTyped : public TIntermNode {
    305 public:
    306 	TIntermTyped(const TType& t) : type(t)  { }
    307 	virtual TIntermTyped* getAsTyped() { return this; }
    308 
    309 	virtual void setType(const TType& t) { type = t; }
    310 	const TType& getType() const { return type; }
    311 	TType* getTypePointer() { return &type; }
    312 
    313 	TBasicType getBasicType() const { return type.getBasicType(); }
    314 	TQualifier getQualifier() const { return type.getQualifier(); }
    315 	TPrecision getPrecision() const { return type.getPrecision(); }
    316 	int getNominalSize() const { return type.getNominalSize(); }
    317 	int getSecondarySize() const { return type.getSecondarySize(); }
    318 
    319 	bool isInterfaceBlock() const { return type.isInterfaceBlock(); }
    320 	bool isMatrix() const { return type.isMatrix(); }
    321 	bool isArray()  const { return type.isArray(); }
    322 	bool isVector() const { return type.isVector(); }
    323 	bool isScalar() const { return type.isScalar(); }
    324 	bool isScalarInt() const { return type.isScalarInt(); }
    325 	bool isRegister() const { return type.isRegister(); }   // Fits in a 4-element register
    326 	bool isStruct() const { return type.isStruct(); }
    327 	const char* getBasicString() const { return type.getBasicString(); }
    328 	const char* getQualifierString() const { return type.getQualifierString(); }
    329 	TString getCompleteString() const { return type.getCompleteString(); }
    330 
    331 	int totalRegisterCount() const { return type.totalRegisterCount(); }
    332 	int blockRegisterCount() const { return type.blockRegisterCount(); }
    333 	int elementRegisterCount() const { return type.elementRegisterCount(); }
    334 	int registerSize() const { return type.registerSize(); }
    335 	int getArraySize() const { return type.getArraySize(); }
    336 
    337 protected:
    338 	TType type;
    339 };
    340 
    341 //
    342 // Handle for, do-while, and while loops.
    343 //
    344 enum TLoopType {
    345 	ELoopFor,
    346 	ELoopWhile,
    347 	ELoopDoWhile
    348 };
    349 
    350 class TIntermLoop : public TIntermNode {
    351 public:
    352 	TIntermLoop(TLoopType aType,
    353 	            TIntermNode *aInit, TIntermTyped* aCond, TIntermTyped* aExpr,
    354 	            TIntermNode* aBody) :
    355 			type(aType),
    356 			init(aInit),
    357 			cond(aCond),
    358 			expr(aExpr),
    359 			body(aBody),
    360 			unrollFlag(false) { }
    361 
    362 	virtual TIntermLoop* getAsLoopNode() { return this; }
    363 	virtual void traverse(TIntermTraverser*);
    364 
    365 	TLoopType getType() const { return type; }
    366 	TIntermNode* getInit() { return init; }
    367 	TIntermTyped* getCondition() { return cond; }
    368 	TIntermTyped* getExpression() { return expr; }
    369 	TIntermNode* getBody() { return body; }
    370 
    371 	void setUnrollFlag(bool flag) { unrollFlag = flag; }
    372 	bool getUnrollFlag() { return unrollFlag; }
    373 
    374 protected:
    375 	TLoopType type;
    376 	TIntermNode* init;  // for-loop initialization
    377 	TIntermTyped* cond; // loop exit condition
    378 	TIntermTyped* expr; // for-loop expression
    379 	TIntermNode* body;  // loop body
    380 
    381 	bool unrollFlag; // Whether the loop should be unrolled or not.
    382 };
    383 
    384 //
    385 // Handle break, continue, return, and kill.
    386 //
    387 class TIntermBranch : public TIntermNode {
    388 public:
    389 	TIntermBranch(TOperator op, TIntermTyped* e) :
    390 			flowOp(op),
    391 			expression(e) { }
    392 
    393 	virtual TIntermBranch* getAsBranchNode() { return this; }
    394 	virtual void traverse(TIntermTraverser*);
    395 
    396 	TOperator getFlowOp() { return flowOp; }
    397 	TIntermTyped* getExpression() { return expression; }
    398 
    399 protected:
    400 	TOperator flowOp;
    401 	TIntermTyped* expression;  // non-zero except for "return exp;" statements
    402 };
    403 
    404 //
    405 // Nodes that correspond to symbols or constants in the source code.
    406 //
    407 class TIntermSymbol : public TIntermTyped {
    408 public:
    409 	// if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. If sym comes from
    410 	// per process globalpoolallocator, then it causes increased memory usage per compile
    411 	// it is essential to use "symbol = sym" to assign to symbol
    412 	TIntermSymbol(int i, const TString& sym, const TType& t) :
    413 			TIntermTyped(t), id(i)  { symbol = sym; }
    414 
    415 	int getId() const { return id; }
    416 	const TString& getSymbol() const { return symbol; }
    417 
    418 	void setId(int newId) { id = newId; }
    419 
    420 	virtual void traverse(TIntermTraverser*);
    421 	virtual TIntermSymbol* getAsSymbolNode() { return this; }
    422 
    423 protected:
    424 	int id;
    425 	TString symbol;
    426 };
    427 
    428 class TIntermConstantUnion : public TIntermTyped {
    429 public:
    430 	TIntermConstantUnion(ConstantUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer)
    431 	{
    432 		getTypePointer()->setQualifier(EvqConstExpr);
    433 	}
    434 
    435 	ConstantUnion* getUnionArrayPointer() const { return unionArrayPointer; }
    436 
    437 	int getIConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getIConst() : 0; }
    438 	int getUConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getUConst() : 0; }
    439 	float getFConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getFConst() : 0.0f; }
    440 	bool getBConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getBConst() : false; }
    441 
    442 	// Previous union pointer freed on pool deallocation.
    443 	void replaceConstantUnion(ConstantUnion *safeConstantUnion) { unionArrayPointer = safeConstantUnion; }
    444 
    445 	virtual TIntermConstantUnion* getAsConstantUnion()  { return this; }
    446 	virtual void traverse(TIntermTraverser*);
    447 
    448 	TIntermTyped* fold(TOperator, TIntermTyped*, TInfoSink&);
    449 
    450 protected:
    451 	ConstantUnion *unionArrayPointer;
    452 };
    453 
    454 //
    455 // Intermediate class for node types that hold operators.
    456 //
    457 class TIntermOperator : public TIntermTyped {
    458 public:
    459 	TOperator getOp() const { return op; }
    460 	void setOp(TOperator o) { op = o; }
    461 
    462 	bool modifiesState() const;
    463 	bool isConstructor() const;
    464 
    465 protected:
    466 	TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat, EbpUndefined)), op(o) {}
    467 	TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o) {}
    468 	TOperator op;
    469 };
    470 
    471 //
    472 // Nodes for all the basic binary math operators.
    473 //
    474 class TIntermBinary : public TIntermOperator {
    475 public:
    476 	TIntermBinary(TOperator o) : TIntermOperator(o) {}
    477 
    478 	virtual TIntermBinary* getAsBinaryNode() { return this; }
    479 	virtual void traverse(TIntermTraverser*);
    480 
    481 	void setType(const TType &t) override
    482 	{
    483 		type = t;
    484 
    485 		if(left->getQualifier() == EvqConstExpr && right->getQualifier() == EvqConstExpr)
    486 		{
    487 			type.setQualifier(EvqConstExpr);
    488 		}
    489 	}
    490 
    491 	void setLeft(TIntermTyped* n) { left = n; }
    492 	void setRight(TIntermTyped* n) { right = n; }
    493 	TIntermTyped* getLeft() const { return left; }
    494 	TIntermTyped* getRight() const { return right; }
    495 	bool promote(TInfoSink&);
    496 
    497 protected:
    498 	TIntermTyped* left;
    499 	TIntermTyped* right;
    500 };
    501 
    502 //
    503 // Nodes for unary math operators.
    504 //
    505 class TIntermUnary : public TIntermOperator {
    506 public:
    507 	TIntermUnary(TOperator o, TType& t) : TIntermOperator(o, t), operand(0) {}
    508 	TIntermUnary(TOperator o) : TIntermOperator(o), operand(0) {}
    509 
    510 	void setType(const TType &t) override
    511 	{
    512 		type = t;
    513 
    514 		if(operand->getQualifier() == EvqConstExpr)
    515 		{
    516 			type.setQualifier(EvqConstExpr);
    517 		}
    518 	}
    519 
    520 	virtual void traverse(TIntermTraverser*);
    521 	virtual TIntermUnary* getAsUnaryNode() { return this; }
    522 
    523 	void setOperand(TIntermTyped* o) { operand = o; }
    524 	TIntermTyped* getOperand() { return operand; }
    525 	bool promote(TInfoSink&, const TType *funcReturnType);
    526 
    527 protected:
    528 	TIntermTyped* operand;
    529 };
    530 
    531 typedef TVector<TIntermNode*> TIntermSequence;
    532 typedef TVector<int> TQualifierList;
    533 
    534 //
    535 // Nodes that operate on an arbitrary sized set of children.
    536 //
    537 class TIntermAggregate : public TIntermOperator {
    538 public:
    539 	TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false) { endLine = { 0, 0, 0, 0 }; }
    540 	TIntermAggregate(TOperator o) : TIntermOperator(o) { }
    541 	~TIntermAggregate() { }
    542 
    543 	virtual TIntermAggregate* getAsAggregate() { return this; }
    544 	virtual void traverse(TIntermTraverser*);
    545 
    546 	TIntermSequence& getSequence() { return sequence; }
    547 
    548 	void setType(const TType &t) override
    549 	{
    550 		type = t;
    551 
    552 		if(op != EOpFunctionCall)
    553 		{
    554 			for(TIntermNode *node : sequence)
    555 			{
    556 				if(!node->getAsTyped() || node->getAsTyped()->getQualifier() != EvqConstExpr)
    557 				{
    558 					return;
    559 				}
    560 			}
    561 
    562 			type.setQualifier(EvqConstExpr);
    563 		}
    564 	}
    565 
    566 	void setName(const TString& n) { name = n; }
    567 	const TString& getName() const { return name; }
    568 
    569 	void setUserDefined() { userDefined = true; }
    570 	bool isUserDefined() const { return userDefined; }
    571 
    572 	void setOptimize(bool o) { optimize = o; }
    573 	bool getOptimize() { return optimize; }
    574 	void setDebug(bool d) { debug = d; }
    575 	bool getDebug() { return debug; }
    576 
    577 	void setEndLine(const TSourceLoc& line) { endLine = line; }
    578 	const TSourceLoc& getEndLine() const { return endLine; }
    579 
    580 	bool isConstantFoldable()
    581 	{
    582 		for(TIntermNode *node : sequence)
    583 		{
    584 			if(!node->getAsConstantUnion() || !node->getAsConstantUnion()->getUnionArrayPointer())
    585 			{
    586 				return false;
    587 			}
    588 		}
    589 
    590 		return true;
    591 	}
    592 
    593 protected:
    594 	TIntermAggregate(const TIntermAggregate&); // disallow copy constructor
    595 	TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator
    596 	TIntermSequence sequence;
    597 	TString name;
    598 	bool userDefined; // used for user defined function names
    599 
    600 	bool optimize;
    601 	bool debug;
    602 	TSourceLoc endLine;
    603 };
    604 
    605 //
    606 // For if tests.  Simplified since there is no switch statement.
    607 //
    608 class TIntermSelection : public TIntermTyped {
    609 public:
    610 	TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) :
    611 			TIntermTyped(TType(EbtVoid, EbpUndefined)), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
    612 	TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) :
    613 			TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB)
    614 	{
    615 		this->type.setQualifier(EvqTemporary);
    616 	}
    617 
    618 	virtual void traverse(TIntermTraverser*);
    619 
    620 	bool usesTernaryOperator() const { return getBasicType() != EbtVoid; }
    621 	TIntermTyped* getCondition() const { return condition; }
    622 	TIntermNode* getTrueBlock() const { return trueBlock; }
    623 	TIntermNode* getFalseBlock() const { return falseBlock; }
    624 	TIntermSelection* getAsSelectionNode() { return this; }
    625 
    626 protected:
    627 	TIntermTyped* condition;
    628 	TIntermNode* trueBlock;
    629 	TIntermNode* falseBlock;
    630 };
    631 
    632 //
    633 // Switch statement.
    634 //
    635 class TIntermSwitch : public TIntermNode
    636 {
    637 public:
    638 	TIntermSwitch(TIntermTyped *init, TIntermAggregate *statementList)
    639 		: TIntermNode(), mInit(init), mStatementList(statementList)
    640 	{}
    641 
    642 	void traverse(TIntermTraverser *it);
    643 
    644 	TIntermSwitch *getAsSwitchNode() { return this; }
    645 
    646 	TIntermTyped *getInit() { return mInit; }
    647 	TIntermAggregate *getStatementList() { return mStatementList; }
    648 	void setStatementList(TIntermAggregate *statementList) { mStatementList = statementList; }
    649 
    650 protected:
    651 	TIntermTyped *mInit;
    652 	TIntermAggregate *mStatementList;
    653 };
    654 
    655 //
    656 // Case label.
    657 //
    658 class TIntermCase : public TIntermNode
    659 {
    660 public:
    661 	TIntermCase(TIntermTyped *condition)
    662 		: TIntermNode(), mCondition(condition)
    663 	{}
    664 
    665 	void traverse(TIntermTraverser *it);
    666 
    667 	TIntermCase *getAsCaseNode() { return this; }
    668 
    669 	bool hasCondition() const { return mCondition != nullptr; }
    670 	TIntermTyped *getCondition() const { return mCondition; }
    671 
    672 protected:
    673 	TIntermTyped *mCondition;
    674 };
    675 
    676 enum Visit
    677 {
    678 	PreVisit,
    679 	InVisit,
    680 	PostVisit
    681 };
    682 
    683 //
    684 // For traversing the tree.  User should derive from this,
    685 // put their traversal specific data in it, and then pass
    686 // it to a Traverse method.
    687 //
    688 // When using this, just fill in the methods for nodes you want visited.
    689 // Return false from a pre-visit to skip visiting that node's subtree.
    690 //
    691 class TIntermTraverser
    692 {
    693 public:
    694 	POOL_ALLOCATOR_NEW_DELETE();
    695 	TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) :
    696 			preVisit(preVisit),
    697 			inVisit(inVisit),
    698 			postVisit(postVisit),
    699 			rightToLeft(rightToLeft),
    700 			mDepth(0) {}
    701 	virtual ~TIntermTraverser() {};
    702 
    703 	virtual void visitSymbol(TIntermSymbol*) {}
    704 	virtual void visitConstantUnion(TIntermConstantUnion*) {}
    705 	virtual bool visitBinary(Visit visit, TIntermBinary*) {return true;}
    706 	virtual bool visitUnary(Visit visit, TIntermUnary*) {return true;}
    707 	virtual bool visitSelection(Visit visit, TIntermSelection*) {return true;}
    708 	virtual bool visitAggregate(Visit visit, TIntermAggregate*) {return true;}
    709 	virtual bool visitLoop(Visit visit, TIntermLoop*) {return true;}
    710 	virtual bool visitBranch(Visit visit, TIntermBranch*) {return true;}
    711 	virtual bool visitSwitch(Visit, TIntermSwitch*) { return true; }
    712 	virtual bool visitCase(Visit, TIntermCase*) { return true; }
    713 
    714 	void incrementDepth(TIntermNode *current)
    715 	{
    716 		mDepth++;
    717 		mPath.push_back(current);
    718 	}
    719 
    720 	void decrementDepth()
    721 	{
    722 		mDepth--;
    723 		mPath.pop_back();
    724 	}
    725 
    726 	TIntermNode *getParentNode()
    727 	{
    728 		return mPath.size() == 0 ? nullptr : mPath.back();
    729 	}
    730 
    731 	const bool preVisit;
    732 	const bool inVisit;
    733 	const bool postVisit;
    734 	const bool rightToLeft;
    735 
    736 protected:
    737 	int mDepth;
    738 
    739 	// All the nodes from root to the current node's parent during traversing.
    740 	TVector<TIntermNode *> mPath;
    741 
    742 private:
    743 	struct ParentBlock
    744 	{
    745 		ParentBlock(TIntermAggregate *nodeIn, TIntermSequence::size_type posIn)
    746 		: node(nodeIn), pos(posIn)
    747 		{}
    748 
    749 		TIntermAggregate *node;
    750 		TIntermSequence::size_type pos;
    751 	};
    752 	// All the code blocks from the root to the current node's parent during traversal.
    753 	std::vector<ParentBlock> mParentBlockStack;
    754 };
    755 
    756 #endif // __INTERMEDIATE_H
    757