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 
TIntermNode()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 
getLine()272 	const TSourceLoc& getLine() const { return line; }
setLine(const TSourceLoc & l)273 	void setLine(const TSourceLoc& l) { line = l; }
274 
275 	virtual void traverse(TIntermTraverser*) = 0;
getAsTyped()276 	virtual TIntermTyped* getAsTyped() { return 0; }
getAsConstantUnion()277 	virtual TIntermConstantUnion* getAsConstantUnion() { return 0; }
getAsAggregate()278 	virtual TIntermAggregate* getAsAggregate() { return 0; }
getAsBinaryNode()279 	virtual TIntermBinary* getAsBinaryNode() { return 0; }
getAsUnaryNode()280 	virtual TIntermUnary* getAsUnaryNode() { return 0; }
getAsSelectionNode()281 	virtual TIntermSelection* getAsSelectionNode() { return 0; }
getAsSymbolNode()282 	virtual TIntermSymbol* getAsSymbolNode() { return 0; }
getAsLoopNode()283 	virtual TIntermLoop* getAsLoopNode() { return 0; }
getAsBranchNode()284 	virtual TIntermBranch* getAsBranchNode() { return 0; }
getAsSwitchNode()285 	virtual TIntermSwitch *getAsSwitchNode() { return 0; }
getAsCaseNode()286 	virtual TIntermCase *getAsCaseNode() { return 0; }
~TIntermNode()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:
TIntermTyped(const TType & t)306 	TIntermTyped(const TType& t) : type(t)  { }
getAsTyped()307 	virtual TIntermTyped* getAsTyped() { return this; }
308 
setType(const TType & t)309 	virtual void setType(const TType& t) { type = t; }
getType()310 	const TType& getType() const { return type; }
getTypePointer()311 	TType* getTypePointer() { return &type; }
312 
getBasicType()313 	TBasicType getBasicType() const { return type.getBasicType(); }
getQualifier()314 	TQualifier getQualifier() const { return type.getQualifier(); }
getPrecision()315 	TPrecision getPrecision() const { return type.getPrecision(); }
getNominalSize()316 	int getNominalSize() const { return type.getNominalSize(); }
getSecondarySize()317 	int getSecondarySize() const { return type.getSecondarySize(); }
318 
isInterfaceBlock()319 	bool isInterfaceBlock() const { return type.isInterfaceBlock(); }
isMatrix()320 	bool isMatrix() const { return type.isMatrix(); }
isArray()321 	bool isArray()  const { return type.isArray(); }
isVector()322 	bool isVector() const { return type.isVector(); }
isScalar()323 	bool isScalar() const { return type.isScalar(); }
isScalarInt()324 	bool isScalarInt() const { return type.isScalarInt(); }
isRegister()325 	bool isRegister() const { return type.isRegister(); }   // Fits in a 4-element register
isStruct()326 	bool isStruct() const { return type.isStruct(); }
getBasicString()327 	const char* getBasicString() const { return type.getBasicString(); }
getQualifierString()328 	const char* getQualifierString() const { return type.getQualifierString(); }
getCompleteString()329 	TString getCompleteString() const { return type.getCompleteString(); }
330 
totalRegisterCount()331 	int totalRegisterCount() const { return type.totalRegisterCount(); }
blockRegisterCount()332 	int blockRegisterCount() const { return type.blockRegisterCount(); }
elementRegisterCount()333 	int elementRegisterCount() const { return type.elementRegisterCount(); }
registerSize()334 	int registerSize() const { return type.registerSize(); }
getArraySize()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:
TIntermLoop(TLoopType aType,TIntermNode * aInit,TIntermTyped * aCond,TIntermTyped * aExpr,TIntermNode * aBody)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 
getAsLoopNode()362 	virtual TIntermLoop* getAsLoopNode() { return this; }
363 	virtual void traverse(TIntermTraverser*);
364 
getType()365 	TLoopType getType() const { return type; }
getInit()366 	TIntermNode* getInit() { return init; }
getCondition()367 	TIntermTyped* getCondition() { return cond; }
getExpression()368 	TIntermTyped* getExpression() { return expr; }
getBody()369 	TIntermNode* getBody() { return body; }
370 
setUnrollFlag(bool flag)371 	void setUnrollFlag(bool flag) { unrollFlag = flag; }
getUnrollFlag()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:
TIntermBranch(TOperator op,TIntermTyped * e)389 	TIntermBranch(TOperator op, TIntermTyped* e) :
390 			flowOp(op),
391 			expression(e) { }
392 
getAsBranchNode()393 	virtual TIntermBranch* getAsBranchNode() { return this; }
394 	virtual void traverse(TIntermTraverser*);
395 
getFlowOp()396 	TOperator getFlowOp() { return flowOp; }
getExpression()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
TIntermSymbol(int i,const TString & sym,const TType & t)412 	TIntermSymbol(int i, const TString& sym, const TType& t) :
413 			TIntermTyped(t), id(i)  { symbol = sym; }
414 
getId()415 	int getId() const { return id; }
getSymbol()416 	const TString& getSymbol() const { return symbol; }
417 
setId(int newId)418 	void setId(int newId) { id = newId; }
419 
420 	virtual void traverse(TIntermTraverser*);
getAsSymbolNode()421 	virtual TIntermSymbol* getAsSymbolNode() { return this; }
422 
423 protected:
424 	int id;
425 	TString symbol;
426 };
427 
428 class TIntermConstantUnion : public TIntermTyped {
429 public:
TIntermConstantUnion(ConstantUnion * unionPointer,const TType & t)430 	TIntermConstantUnion(ConstantUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer)
431 	{
432 		getTypePointer()->setQualifier(EvqConstExpr);
433 	}
434 
getUnionArrayPointer()435 	ConstantUnion* getUnionArrayPointer() const { return unionArrayPointer; }
436 
getIConst(int index)437 	int getIConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getIConst() : 0; }
getUConst(int index)438 	int getUConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getUConst() : 0; }
getFConst(int index)439 	float getFConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getFConst() : 0.0f; }
getBConst(int index)440 	bool getBConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getBConst() : false; }
441 
442 	// Previous union pointer freed on pool deallocation.
replaceConstantUnion(ConstantUnion * safeConstantUnion)443 	void replaceConstantUnion(ConstantUnion *safeConstantUnion) { unionArrayPointer = safeConstantUnion; }
444 
getAsConstantUnion()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:
getOp()459 	TOperator getOp() const { return op; }
setOp(TOperator o)460 	void setOp(TOperator o) { op = o; }
461 
462 	bool modifiesState() const;
463 	bool isConstructor() const;
464 
465 protected:
TIntermOperator(TOperator o)466 	TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat, EbpUndefined)), op(o) {}
TIntermOperator(TOperator o,TType & t)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:
TIntermBinary(TOperator o)476 	TIntermBinary(TOperator o) : TIntermOperator(o) {}
477 
getAsBinaryNode()478 	virtual TIntermBinary* getAsBinaryNode() { return this; }
479 	virtual void traverse(TIntermTraverser*);
480 
setType(const TType & t)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 
setLeft(TIntermTyped * n)491 	void setLeft(TIntermTyped* n) { left = n; }
setRight(TIntermTyped * n)492 	void setRight(TIntermTyped* n) { right = n; }
getLeft()493 	TIntermTyped* getLeft() const { return left; }
getRight()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:
TIntermUnary(TOperator o,TType & t)507 	TIntermUnary(TOperator o, TType& t) : TIntermOperator(o, t), operand(0) {}
TIntermUnary(TOperator o)508 	TIntermUnary(TOperator o) : TIntermOperator(o), operand(0) {}
509 
setType(const TType & t)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*);
getAsUnaryNode()521 	virtual TIntermUnary* getAsUnaryNode() { return this; }
522 
setOperand(TIntermTyped * o)523 	void setOperand(TIntermTyped* o) { operand = o; }
getOperand()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:
TIntermAggregate()539 	TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false) { endLine = { 0, 0, 0, 0 }; }
TIntermAggregate(TOperator o)540 	TIntermAggregate(TOperator o) : TIntermOperator(o) { }
~TIntermAggregate()541 	~TIntermAggregate() { }
542 
getAsAggregate()543 	virtual TIntermAggregate* getAsAggregate() { return this; }
544 	virtual void traverse(TIntermTraverser*);
545 
getSequence()546 	TIntermSequence& getSequence() { return sequence; }
547 
setType(const TType & t)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 
setName(const TString & n)566 	void setName(const TString& n) { name = n; }
getName()567 	const TString& getName() const { return name; }
568 
setUserDefined()569 	void setUserDefined() { userDefined = true; }
isUserDefined()570 	bool isUserDefined() const { return userDefined; }
571 
setOptimize(bool o)572 	void setOptimize(bool o) { optimize = o; }
getOptimize()573 	bool getOptimize() { return optimize; }
setDebug(bool d)574 	void setDebug(bool d) { debug = d; }
getDebug()575 	bool getDebug() { return debug; }
576 
setEndLine(const TSourceLoc & line)577 	void setEndLine(const TSourceLoc& line) { endLine = line; }
getEndLine()578 	const TSourceLoc& getEndLine() const { return endLine; }
579 
isConstantFoldable()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:
TIntermSelection(TIntermTyped * cond,TIntermNode * trueB,TIntermNode * falseB)610 	TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) :
611 			TIntermTyped(TType(EbtVoid, EbpUndefined)), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
TIntermSelection(TIntermTyped * cond,TIntermNode * trueB,TIntermNode * falseB,const TType & type)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 
usesTernaryOperator()620 	bool usesTernaryOperator() const { return getBasicType() != EbtVoid; }
getCondition()621 	TIntermTyped* getCondition() const { return condition; }
getTrueBlock()622 	TIntermNode* getTrueBlock() const { return trueBlock; }
getFalseBlock()623 	TIntermNode* getFalseBlock() const { return falseBlock; }
getAsSelectionNode()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:
TIntermSwitch(TIntermTyped * init,TIntermAggregate * statementList)638 	TIntermSwitch(TIntermTyped *init, TIntermAggregate *statementList)
639 		: TIntermNode(), mInit(init), mStatementList(statementList)
640 	{}
641 
642 	void traverse(TIntermTraverser *it);
643 
getAsSwitchNode()644 	TIntermSwitch *getAsSwitchNode() { return this; }
645 
getInit()646 	TIntermTyped *getInit() { return mInit; }
getStatementList()647 	TIntermAggregate *getStatementList() { return mStatementList; }
setStatementList(TIntermAggregate * statementList)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:
TIntermCase(TIntermTyped * condition)661 	TIntermCase(TIntermTyped *condition)
662 		: TIntermNode(), mCondition(condition)
663 	{}
664 
665 	void traverse(TIntermTraverser *it);
666 
getAsCaseNode()667 	TIntermCase *getAsCaseNode() { return this; }
668 
hasCondition()669 	bool hasCondition() const { return mCondition != nullptr; }
getCondition()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) :
preVisit(preVisit)696 			preVisit(preVisit),
697 			inVisit(inVisit),
698 			postVisit(postVisit),
699 			rightToLeft(rightToLeft),
700 			mDepth(0) {}
~TIntermTraverser()701 	virtual ~TIntermTraverser() {};
702 
visitSymbol(TIntermSymbol *)703 	virtual void visitSymbol(TIntermSymbol*) {}
visitConstantUnion(TIntermConstantUnion *)704 	virtual void visitConstantUnion(TIntermConstantUnion*) {}
visitBinary(Visit visit,TIntermBinary *)705 	virtual bool visitBinary(Visit visit, TIntermBinary*) {return true;}
visitUnary(Visit visit,TIntermUnary *)706 	virtual bool visitUnary(Visit visit, TIntermUnary*) {return true;}
visitSelection(Visit visit,TIntermSelection *)707 	virtual bool visitSelection(Visit visit, TIntermSelection*) {return true;}
visitAggregate(Visit visit,TIntermAggregate *)708 	virtual bool visitAggregate(Visit visit, TIntermAggregate*) {return true;}
visitLoop(Visit visit,TIntermLoop *)709 	virtual bool visitLoop(Visit visit, TIntermLoop*) {return true;}
visitBranch(Visit visit,TIntermBranch *)710 	virtual bool visitBranch(Visit visit, TIntermBranch*) {return true;}
visitSwitch(Visit,TIntermSwitch *)711 	virtual bool visitSwitch(Visit, TIntermSwitch*) { return true; }
visitCase(Visit,TIntermCase *)712 	virtual bool visitCase(Visit, TIntermCase*) { return true; }
713 
incrementDepth(TIntermNode * current)714 	void incrementDepth(TIntermNode *current)
715 	{
716 		mDepth++;
717 		mPath.push_back(current);
718 	}
719 
decrementDepth()720 	void decrementDepth()
721 	{
722 		mDepth--;
723 		mPath.pop_back();
724 	}
725 
getParentNode()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 	{
ParentBlockParentBlock745 		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