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 TOperator TypeToConstructorOperator(const TType &type);
    242 extern const char* getOperatorString(TOperator op);
    243 
    244 class TIntermTraverser;
    245 class TIntermAggregate;
    246 class TIntermBinary;
    247 class TIntermUnary;
    248 class TIntermConstantUnion;
    249 class TIntermSelection;
    250 class TIntermTyped;
    251 class TIntermSymbol;
    252 class TIntermLoop;
    253 class TIntermBranch;
    254 class TInfoSink;
    255 class TIntermSwitch;
    256 class TIntermCase;
    257 
    258 //
    259 // Base class for the tree nodes
    260 //
    261 class TIntermNode {
    262 public:
    263 	POOL_ALLOCATOR_NEW_DELETE();
    264 
    265 	TIntermNode()
    266 	{
    267 		// TODO: Move this to TSourceLoc constructor
    268 		// after getting rid of TPublicType.
    269 		line.first_file = line.last_file = 0;
    270 		line.first_line = line.last_line = 0;
    271 	}
    272 
    273 	const TSourceLoc& getLine() const { return line; }
    274 	void setLine(const TSourceLoc& l) { line = l; }
    275 
    276 	virtual void traverse(TIntermTraverser*) = 0;
    277 	virtual TIntermTyped* getAsTyped() { return 0; }
    278 	virtual TIntermConstantUnion* getAsConstantUnion() { return 0; }
    279 	virtual TIntermAggregate* getAsAggregate() { return 0; }
    280 	virtual TIntermBinary* getAsBinaryNode() { return 0; }
    281 	virtual TIntermUnary* getAsUnaryNode() { return 0; }
    282 	virtual TIntermSelection* getAsSelectionNode() { return 0; }
    283 	virtual TIntermSymbol* getAsSymbolNode() { return 0; }
    284 	virtual TIntermLoop* getAsLoopNode() { return 0; }
    285 	virtual TIntermBranch* getAsBranchNode() { return 0; }
    286 	virtual TIntermSwitch *getAsSwitchNode() { return 0; }
    287 	virtual TIntermCase *getAsCaseNode() { return 0; }
    288 	virtual ~TIntermNode() { }
    289 
    290 protected:
    291 	TSourceLoc line;
    292 };
    293 
    294 //
    295 // This is just to help yacc.
    296 //
    297 struct TIntermNodePair {
    298 	TIntermNode* node1;
    299 	TIntermNode* node2;
    300 };
    301 
    302 //
    303 // Intermediate class for nodes that have a type.
    304 //
    305 class TIntermTyped : public TIntermNode {
    306 public:
    307 	TIntermTyped(const TType& t) : type(t)  { }
    308 	virtual TIntermTyped* getAsTyped() { return this; }
    309 
    310 	virtual void setType(const TType& t) { type = t; }
    311 	const TType& getType() const { return type; }
    312 	TType* getTypePointer() { return &type; }
    313 
    314 	TBasicType getBasicType() const { return type.getBasicType(); }
    315 	TQualifier getQualifier() const { return type.getQualifier(); }
    316 	TPrecision getPrecision() const { return type.getPrecision(); }
    317 	int getNominalSize() const { return type.getNominalSize(); }
    318 	int getSecondarySize() const { return type.getSecondarySize(); }
    319 
    320 	bool isInterfaceBlock() const { return type.isInterfaceBlock(); }
    321 	bool isMatrix() const { return type.isMatrix(); }
    322 	bool isArray()  const { return type.isArray(); }
    323 	bool isVector() const { return type.isVector(); }
    324 	bool isScalar() const { return type.isScalar(); }
    325 	bool isScalarInt() const { return type.isScalarInt(); }
    326 	bool isRegister() const { return type.isRegister(); }   // Fits in a 4-element register
    327 	bool isStruct() const { return type.isStruct(); }
    328 	const char* getBasicString() const { return type.getBasicString(); }
    329 	const char* getQualifierString() const { return type.getQualifierString(); }
    330 	TString getCompleteString() const { return type.getCompleteString(); }
    331 
    332 	int totalRegisterCount() const { return type.totalRegisterCount(); }
    333 	int blockRegisterCount(bool samplersOnly) const { return samplersOnly ? type.totalSamplerRegisterCount() : type.blockRegisterCount(); }
    334 	int elementRegisterCount() const { return type.elementRegisterCount(); }
    335 	int registerSize() const { return type.registerSize(); }
    336 	int getArraySize() const { return type.getArraySize(); }
    337 
    338 	static TIntermTyped *CreateIndexNode(int index);
    339 protected:
    340 	TType type;
    341 };
    342 
    343 //
    344 // Handle for, do-while, and while loops.
    345 //
    346 enum TLoopType {
    347 	ELoopFor,
    348 	ELoopWhile,
    349 	ELoopDoWhile
    350 };
    351 
    352 class TIntermLoop : public TIntermNode {
    353 public:
    354 	TIntermLoop(TLoopType aType,
    355 	            TIntermNode *aInit, TIntermTyped* aCond, TIntermTyped* aExpr,
    356 	            TIntermNode* aBody) :
    357 			type(aType),
    358 			init(aInit),
    359 			cond(aCond),
    360 			expr(aExpr),
    361 			body(aBody),
    362 			unrollFlag(false) { }
    363 
    364 	virtual TIntermLoop* getAsLoopNode() { return this; }
    365 	virtual void traverse(TIntermTraverser*);
    366 
    367 	TLoopType getType() const { return type; }
    368 	TIntermNode* getInit() { return init; }
    369 	TIntermTyped* getCondition() { return cond; }
    370 	TIntermTyped* getExpression() { return expr; }
    371 	TIntermNode* getBody() { return body; }
    372 
    373 	void setUnrollFlag(bool flag) { unrollFlag = flag; }
    374 	bool getUnrollFlag() { return unrollFlag; }
    375 
    376 protected:
    377 	TLoopType type;
    378 	TIntermNode* init;  // for-loop initialization
    379 	TIntermTyped* cond; // loop exit condition
    380 	TIntermTyped* expr; // for-loop expression
    381 	TIntermNode* body;  // loop body
    382 
    383 	bool unrollFlag; // Whether the loop should be unrolled or not.
    384 };
    385 
    386 //
    387 // Handle break, continue, return, and kill.
    388 //
    389 class TIntermBranch : public TIntermNode {
    390 public:
    391 	TIntermBranch(TOperator op, TIntermTyped* e) :
    392 			flowOp(op),
    393 			expression(e) { }
    394 
    395 	virtual TIntermBranch* getAsBranchNode() { return this; }
    396 	virtual void traverse(TIntermTraverser*);
    397 
    398 	TOperator getFlowOp() { return flowOp; }
    399 	TIntermTyped* getExpression() { return expression; }
    400 
    401 protected:
    402 	TOperator flowOp;
    403 	TIntermTyped* expression;  // non-zero except for "return exp;" statements
    404 };
    405 
    406 //
    407 // Nodes that correspond to symbols or constants in the source code.
    408 //
    409 class TIntermSymbol : public TIntermTyped {
    410 public:
    411 	// if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. If sym comes from
    412 	// per process globalpoolallocator, then it causes increased memory usage per compile
    413 	// it is essential to use "symbol = sym" to assign to symbol
    414 	TIntermSymbol(int i, const TString& sym, const TType& t) :
    415 			TIntermTyped(t), id(i)  { symbol = sym; }
    416 
    417 	int getId() const { return id; }
    418 	const TString& getSymbol() const { return symbol; }
    419 
    420 	void setId(int newId) { id = newId; }
    421 
    422 	virtual void traverse(TIntermTraverser*);
    423 	virtual TIntermSymbol* getAsSymbolNode() { return this; }
    424 
    425 protected:
    426 	int id;
    427 	TString symbol;
    428 };
    429 
    430 class TIntermConstantUnion : public TIntermTyped {
    431 public:
    432 	TIntermConstantUnion(ConstantUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer)
    433 	{
    434 		getTypePointer()->setQualifier(EvqConstExpr);
    435 	}
    436 
    437 	ConstantUnion* getUnionArrayPointer() const { return unionArrayPointer; }
    438 
    439 	int getIConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getIConst() : 0; }
    440 	int getUConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getUConst() : 0; }
    441 	float getFConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getFConst() : 0.0f; }
    442 	bool getBConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getBConst() : false; }
    443 
    444 	// Previous union pointer freed on pool deallocation.
    445 	void replaceConstantUnion(ConstantUnion *safeConstantUnion) { unionArrayPointer = safeConstantUnion; }
    446 
    447 	virtual TIntermConstantUnion* getAsConstantUnion()  { return this; }
    448 	virtual void traverse(TIntermTraverser*);
    449 
    450 	TIntermTyped* fold(TOperator, TIntermTyped*, TInfoSink&);
    451 
    452 protected:
    453 	ConstantUnion *unionArrayPointer;
    454 };
    455 
    456 //
    457 // Intermediate class for node types that hold operators.
    458 //
    459 class TIntermOperator : public TIntermTyped {
    460 public:
    461 	TOperator getOp() const { return op; }
    462 	void setOp(TOperator o) { op = o; }
    463 
    464 	bool modifiesState() const;
    465 	bool isConstructor() const;
    466 
    467 protected:
    468 	TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat, EbpUndefined)), op(o) {}
    469 	TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o) {}
    470 	TOperator op;
    471 };
    472 
    473 //
    474 // Nodes for all the basic binary math operators.
    475 //
    476 class TIntermBinary : public TIntermOperator {
    477 public:
    478 	TIntermBinary(TOperator o) : TIntermOperator(o) {}
    479 
    480 	virtual TIntermBinary* getAsBinaryNode() { return this; }
    481 	virtual void traverse(TIntermTraverser*);
    482 
    483 	void setType(const TType &t) override
    484 	{
    485 		type = t;
    486 
    487 		if(left->getQualifier() == EvqConstExpr && right->getQualifier() == EvqConstExpr)
    488 		{
    489 			type.setQualifier(EvqConstExpr);
    490 		}
    491 	}
    492 
    493 	void setLeft(TIntermTyped* n) { left = n; }
    494 	void setRight(TIntermTyped* n) { right = n; }
    495 	TIntermTyped* getLeft() const { return left; }
    496 	TIntermTyped* getRight() const { return right; }
    497 	bool promote(TInfoSink&);
    498 
    499 protected:
    500 	TIntermTyped* left;
    501 	TIntermTyped* right;
    502 };
    503 
    504 //
    505 // Nodes for unary math operators.
    506 //
    507 class TIntermUnary : public TIntermOperator {
    508 public:
    509 	TIntermUnary(TOperator o, TType& t) : TIntermOperator(o, t), operand(0) {}
    510 	TIntermUnary(TOperator o) : TIntermOperator(o), operand(0) {}
    511 
    512 	void setType(const TType &t) override
    513 	{
    514 		type = t;
    515 
    516 		if(operand->getQualifier() == EvqConstExpr)
    517 		{
    518 			type.setQualifier(EvqConstExpr);
    519 		}
    520 	}
    521 
    522 	virtual void traverse(TIntermTraverser*);
    523 	virtual TIntermUnary* getAsUnaryNode() { return this; }
    524 
    525 	void setOperand(TIntermTyped* o) { operand = o; }
    526 	TIntermTyped* getOperand() { return operand; }
    527 	bool promote(TInfoSink&, const TType *funcReturnType);
    528 
    529 protected:
    530 	TIntermTyped* operand;
    531 };
    532 
    533 typedef TVector<TIntermNode*> TIntermSequence;
    534 typedef TVector<int> TQualifierList;
    535 
    536 //
    537 // Nodes that operate on an arbitrary sized set of children.
    538 //
    539 class TIntermAggregate : public TIntermOperator {
    540 public:
    541 	TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false) { endLine = { 0, 0, 0, 0 }; }
    542 	TIntermAggregate(TOperator o) : TIntermOperator(o), userDefined(false) { endLine = { 0, 0, 0, 0 }; }
    543 	~TIntermAggregate() { }
    544 
    545 	virtual TIntermAggregate* getAsAggregate() { return this; }
    546 	virtual void traverse(TIntermTraverser*);
    547 
    548 	TIntermSequence& getSequence() { return sequence; }
    549 
    550 	void setType(const TType &t) override
    551 	{
    552 		type = t;
    553 
    554 		if(op != EOpFunctionCall)
    555 		{
    556 			for(TIntermNode *node : sequence)
    557 			{
    558 				if(!node->getAsTyped() || node->getAsTyped()->getQualifier() != EvqConstExpr)
    559 				{
    560 					return;
    561 				}
    562 			}
    563 
    564 			type.setQualifier(EvqConstExpr);
    565 		}
    566 	}
    567 
    568 	void setName(const TString& n) { name = n; }
    569 	const TString& getName() const { return name; }
    570 
    571 	void setUserDefined() { userDefined = true; }
    572 	bool isUserDefined() const { return userDefined; }
    573 
    574 	void setOptimize(bool o) { optimize = o; }
    575 	bool getOptimize() { return optimize; }
    576 	void setDebug(bool d) { debug = d; }
    577 	bool getDebug() { return debug; }
    578 
    579 	void setEndLine(const TSourceLoc& line) { endLine = line; }
    580 	const TSourceLoc& getEndLine() const { return endLine; }
    581 
    582 	bool isConstantFoldable()
    583 	{
    584 		for(TIntermNode *node : sequence)
    585 		{
    586 			if(!node->getAsConstantUnion() || !node->getAsConstantUnion()->getUnionArrayPointer())
    587 			{
    588 				return false;
    589 			}
    590 		}
    591 
    592 		return true;
    593 	}
    594 
    595 protected:
    596 	TIntermAggregate(const TIntermAggregate&); // disallow copy constructor
    597 	TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator
    598 	TIntermSequence sequence;
    599 	TString name;
    600 	bool userDefined; // used for user defined function names
    601 
    602 	bool optimize;
    603 	bool debug;
    604 	TSourceLoc endLine;
    605 };
    606 
    607 //
    608 // For if tests.  Simplified since there is no switch statement.
    609 //
    610 class TIntermSelection : public TIntermTyped {
    611 public:
    612 	TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) :
    613 			TIntermTyped(TType(EbtVoid, EbpUndefined)), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
    614 	TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) :
    615 			TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB)
    616 	{
    617 		this->type.setQualifier(EvqTemporary);
    618 	}
    619 
    620 	virtual void traverse(TIntermTraverser*);
    621 
    622 	bool usesTernaryOperator() const { return getBasicType() != EbtVoid; }
    623 	TIntermTyped* getCondition() const { return condition; }
    624 	TIntermNode* getTrueBlock() const { return trueBlock; }
    625 	TIntermNode* getFalseBlock() const { return falseBlock; }
    626 	TIntermSelection* getAsSelectionNode() { return this; }
    627 
    628 protected:
    629 	TIntermTyped* condition;
    630 	TIntermNode* trueBlock;
    631 	TIntermNode* falseBlock;
    632 };
    633 
    634 //
    635 // Switch statement.
    636 //
    637 class TIntermSwitch : public TIntermNode
    638 {
    639 public:
    640 	TIntermSwitch(TIntermTyped *init, TIntermAggregate *statementList)
    641 		: TIntermNode(), mInit(init), mStatementList(statementList)
    642 	{}
    643 
    644 	void traverse(TIntermTraverser *it);
    645 
    646 	TIntermSwitch *getAsSwitchNode() { return this; }
    647 
    648 	TIntermTyped *getInit() { return mInit; }
    649 	TIntermAggregate *getStatementList() { return mStatementList; }
    650 	void setStatementList(TIntermAggregate *statementList) { mStatementList = statementList; }
    651 
    652 protected:
    653 	TIntermTyped *mInit;
    654 	TIntermAggregate *mStatementList;
    655 };
    656 
    657 //
    658 // Case label.
    659 //
    660 class TIntermCase : public TIntermNode
    661 {
    662 public:
    663 	TIntermCase(TIntermTyped *condition)
    664 		: TIntermNode(), mCondition(condition)
    665 	{}
    666 
    667 	void traverse(TIntermTraverser *it);
    668 
    669 	TIntermCase *getAsCaseNode() { return this; }
    670 
    671 	bool hasCondition() const { return mCondition != nullptr; }
    672 	TIntermTyped *getCondition() const { return mCondition; }
    673 
    674 protected:
    675 	TIntermTyped *mCondition;
    676 };
    677 
    678 enum Visit
    679 {
    680 	PreVisit,
    681 	InVisit,
    682 	PostVisit
    683 };
    684 
    685 //
    686 // For traversing the tree.  User should derive from this,
    687 // put their traversal specific data in it, and then pass
    688 // it to a Traverse method.
    689 //
    690 // When using this, just fill in the methods for nodes you want visited.
    691 // Return false from a pre-visit to skip visiting that node's subtree.
    692 //
    693 class TIntermTraverser
    694 {
    695 public:
    696 	POOL_ALLOCATOR_NEW_DELETE();
    697 	TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) :
    698 			preVisit(preVisit),
    699 			inVisit(inVisit),
    700 			postVisit(postVisit),
    701 			rightToLeft(rightToLeft),
    702 			mDepth(0) {}
    703 	virtual ~TIntermTraverser() {};
    704 
    705 	virtual void visitSymbol(TIntermSymbol*) {}
    706 	virtual void visitConstantUnion(TIntermConstantUnion*) {}
    707 	virtual bool visitBinary(Visit visit, TIntermBinary*) {return true;}
    708 	virtual bool visitUnary(Visit visit, TIntermUnary*) {return true;}
    709 	virtual bool visitSelection(Visit visit, TIntermSelection*) {return true;}
    710 	virtual bool visitAggregate(Visit visit, TIntermAggregate*) {return true;}
    711 	virtual bool visitLoop(Visit visit, TIntermLoop*) {return true;}
    712 	virtual bool visitBranch(Visit visit, TIntermBranch*) {return true;}
    713 	virtual bool visitSwitch(Visit, TIntermSwitch*) { return true; }
    714 	virtual bool visitCase(Visit, TIntermCase*) { return true; }
    715 
    716 	void incrementDepth(TIntermNode *current)
    717 	{
    718 		mDepth++;
    719 		mPath.push_back(current);
    720 	}
    721 
    722 	void decrementDepth()
    723 	{
    724 		mDepth--;
    725 		mPath.pop_back();
    726 	}
    727 
    728 	TIntermNode *getParentNode()
    729 	{
    730 		return mPath.size() == 0 ? nullptr : mPath.back();
    731 	}
    732 
    733 	const bool preVisit;
    734 	const bool inVisit;
    735 	const bool postVisit;
    736 	const bool rightToLeft;
    737 
    738 protected:
    739 	int mDepth;
    740 
    741 	// All the nodes from root to the current node's parent during traversing.
    742 	TVector<TIntermNode *> mPath;
    743 
    744 private:
    745 	struct ParentBlock
    746 	{
    747 		ParentBlock(TIntermAggregate *nodeIn, TIntermSequence::size_type posIn)
    748 		: node(nodeIn), pos(posIn)
    749 		{}
    750 
    751 		TIntermAggregate *node;
    752 		TIntermSequence::size_type pos;
    753 	};
    754 	// All the code blocks from the root to the current node's parent during traversal.
    755 	std::vector<ParentBlock> mParentBlockStack;
    756 };
    757 
    758 #endif // __INTERMEDIATE_H
    759