1 //
2 // Copyright (c) 2002-2010 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 // Definition of the in-memory high-level intermediate representation
9 // of shaders.  This is a tree that parser creates.
10 //
11 // Nodes in the tree are defined as a hierarchy of classes derived from
12 // TIntermNode. Each is a node in a tree.  There is no preset branching factor;
13 // each node can have it's own type of list of children.
14 //
15 
16 #ifndef __INTERMEDIATE_H
17 #define __INTERMEDIATE_H
18 
19 #include "compiler/Common.h"
20 #include "compiler/Types.h"
21 #include "compiler/ConstantUnion.h"
22 
23 //
24 // Operators used by the high-level (parse tree) representation.
25 //
26 enum TOperator {
27     EOpNull,            // if in a node, should only mean a node is still being built
28     EOpSequence,        // denotes a list of statements, or parameters, etc.
29     EOpFunctionCall,
30     EOpFunction,        // For function definition
31     EOpParameters,      // an aggregate listing the parameters to a function
32 
33     EOpDeclaration,
34     EOpPrototype,
35 
36     //
37     // Unary operators
38     //
39 
40     EOpNegative,
41     EOpLogicalNot,
42     EOpVectorLogicalNot,
43 
44     EOpPostIncrement,
45     EOpPostDecrement,
46     EOpPreIncrement,
47     EOpPreDecrement,
48 
49     EOpConvIntToBool,
50     EOpConvFloatToBool,
51     EOpConvBoolToFloat,
52     EOpConvIntToFloat,
53     EOpConvFloatToInt,
54     EOpConvBoolToInt,
55 
56     //
57     // binary operations
58     //
59 
60     EOpAdd,
61     EOpSub,
62     EOpMul,
63     EOpDiv,
64     EOpEqual,
65     EOpNotEqual,
66     EOpVectorEqual,
67     EOpVectorNotEqual,
68     EOpLessThan,
69     EOpGreaterThan,
70     EOpLessThanEqual,
71     EOpGreaterThanEqual,
72     EOpComma,
73 
74     EOpVectorTimesScalar,
75     EOpVectorTimesMatrix,
76     EOpMatrixTimesVector,
77     EOpMatrixTimesScalar,
78 
79     EOpLogicalOr,
80     EOpLogicalXor,
81     EOpLogicalAnd,
82 
83     EOpIndexDirect,
84     EOpIndexIndirect,
85     EOpIndexDirectStruct,
86 
87     EOpVectorSwizzle,
88 
89     //
90     // Built-in functions potentially mapped to operators
91     //
92 
93     EOpRadians,
94     EOpDegrees,
95     EOpSin,
96     EOpCos,
97     EOpTan,
98     EOpAsin,
99     EOpAcos,
100     EOpAtan,
101 
102     EOpPow,
103     EOpExp,
104     EOpLog,
105     EOpExp2,
106     EOpLog2,
107     EOpSqrt,
108     EOpInverseSqrt,
109 
110     EOpAbs,
111     EOpSign,
112     EOpFloor,
113     EOpCeil,
114     EOpFract,
115     EOpMod,
116     EOpMin,
117     EOpMax,
118     EOpClamp,
119     EOpMix,
120     EOpStep,
121     EOpSmoothStep,
122 
123     EOpLength,
124     EOpDistance,
125     EOpDot,
126     EOpCross,
127     EOpNormalize,
128     EOpFaceForward,
129     EOpReflect,
130     EOpRefract,
131 
132     EOpDFdx,            // Fragment only, OES_standard_derivatives extension
133     EOpDFdy,            // Fragment only, OES_standard_derivatives extension
134     EOpFwidth,          // Fragment only, OES_standard_derivatives extension
135 
136     EOpMatrixTimesMatrix,
137 
138     EOpAny,
139     EOpAll,
140 
141     //
142     // Branch
143     //
144 
145     EOpKill,            // Fragment only
146     EOpReturn,
147     EOpBreak,
148     EOpContinue,
149 
150     //
151     // Constructors
152     //
153 
154     EOpConstructInt,
155     EOpConstructBool,
156     EOpConstructFloat,
157     EOpConstructVec2,
158     EOpConstructVec3,
159     EOpConstructVec4,
160     EOpConstructBVec2,
161     EOpConstructBVec3,
162     EOpConstructBVec4,
163     EOpConstructIVec2,
164     EOpConstructIVec3,
165     EOpConstructIVec4,
166     EOpConstructMat2,
167     EOpConstructMat3,
168     EOpConstructMat4,
169     EOpConstructStruct,
170 
171     //
172     // moves
173     //
174 
175     EOpAssign,
176     EOpInitialize,
177     EOpAddAssign,
178     EOpSubAssign,
179     EOpMulAssign,
180     EOpVectorTimesMatrixAssign,
181     EOpVectorTimesScalarAssign,
182     EOpMatrixTimesScalarAssign,
183     EOpMatrixTimesMatrixAssign,
184     EOpDivAssign,
185 };
186 
187 extern const char* getOperatorString(TOperator op);
188 
189 class TIntermTraverser;
190 class TIntermAggregate;
191 class TIntermBinary;
192 class TIntermUnary;
193 class TIntermConstantUnion;
194 class TIntermSelection;
195 class TIntermTyped;
196 class TIntermSymbol;
197 class TIntermLoop;
198 class TInfoSink;
199 
200 //
201 // Base class for the tree nodes
202 //
203 class TIntermNode {
204 public:
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)205     POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
206 
207     TIntermNode() : line(0) {}
208 
getLine()209     TSourceLoc getLine() const { return line; }
setLine(TSourceLoc l)210     void setLine(TSourceLoc l) { line = l; }
211 
212     virtual void traverse(TIntermTraverser*) = 0;
getAsTyped()213     virtual TIntermTyped* getAsTyped() { return 0; }
getAsConstantUnion()214     virtual TIntermConstantUnion* getAsConstantUnion() { return 0; }
getAsAggregate()215     virtual TIntermAggregate* getAsAggregate() { return 0; }
getAsBinaryNode()216     virtual TIntermBinary* getAsBinaryNode() { return 0; }
getAsUnaryNode()217     virtual TIntermUnary* getAsUnaryNode() { return 0; }
getAsSelectionNode()218     virtual TIntermSelection* getAsSelectionNode() { return 0; }
getAsSymbolNode()219     virtual TIntermSymbol* getAsSymbolNode() { return 0; }
getAsLoopNode()220     virtual TIntermLoop* getAsLoopNode() { return 0; }
~TIntermNode()221     virtual ~TIntermNode() { }
222 
223 protected:
224     TSourceLoc line;
225 };
226 
227 //
228 // This is just to help yacc.
229 //
230 struct TIntermNodePair {
231     TIntermNode* node1;
232     TIntermNode* node2;
233 };
234 
235 //
236 // Intermediate class for nodes that have a type.
237 //
238 class TIntermTyped : public TIntermNode {
239 public:
TIntermTyped(const TType & t)240     TIntermTyped(const TType& t) : type(t)  { }
getAsTyped()241     virtual TIntermTyped* getAsTyped() { return this; }
242 
setType(const TType & t)243     void setType(const TType& t) { type = t; }
getType()244     const TType& getType() const { return type; }
getTypePointer()245     TType* getTypePointer() { return &type; }
246 
getBasicType()247     TBasicType getBasicType() const { return type.getBasicType(); }
getQualifier()248     TQualifier getQualifier() const { return type.getQualifier(); }
getPrecision()249     TPrecision getPrecision() const { return type.getPrecision(); }
getNominalSize()250     int getNominalSize() const { return type.getNominalSize(); }
251 
isMatrix()252     bool isMatrix() const { return type.isMatrix(); }
isArray()253     bool isArray()  const { return type.isArray(); }
isVector()254     bool isVector() const { return type.isVector(); }
isScalar()255     bool isScalar() const { return type.isScalar(); }
getBasicString()256     const char* getBasicString() const { return type.getBasicString(); }
getQualifierString()257     const char* getQualifierString() const { return type.getQualifierString(); }
getCompleteString()258     TString getCompleteString() const { return type.getCompleteString(); }
259 
260 protected:
261     TType type;
262 };
263 
264 //
265 // Handle for, do-while, and while loops.
266 //
267 enum TLoopType {
268     ELoopFor,
269     ELoopWhile,
270     ELoopDoWhile,
271 };
272 
273 class TIntermLoop : public TIntermNode {
274 public:
TIntermLoop(TLoopType aType,TIntermNode * aInit,TIntermTyped * aCond,TIntermTyped * aExpr,TIntermNode * aBody)275     TIntermLoop(TLoopType aType,
276                 TIntermNode *aInit, TIntermTyped* aCond, TIntermTyped* aExpr,
277                 TIntermNode* aBody) :
278             type(aType),
279             init(aInit),
280             cond(aCond),
281             expr(aExpr),
282             body(aBody) { }
283 
getAsLoopNode()284     virtual TIntermLoop* getAsLoopNode() { return this; }
285     virtual void traverse(TIntermTraverser*);
286 
getType()287     TLoopType getType() const { return type; }
getInit()288     TIntermNode* getInit() { return init; }
getCondition()289     TIntermTyped* getCondition() { return cond; }
getExpression()290     TIntermTyped* getExpression() { return expr; }
getBody()291     TIntermNode* getBody() { return body; }
292 
293 protected:
294     TLoopType type;
295     TIntermNode* init;  // for-loop initialization
296     TIntermTyped* cond; // loop exit condition
297     TIntermTyped* expr; // for-loop expression
298     TIntermNode* body;  // loop body
299 };
300 
301 //
302 // Handle break, continue, return, and kill.
303 //
304 class TIntermBranch : public TIntermNode {
305 public:
TIntermBranch(TOperator op,TIntermTyped * e)306     TIntermBranch(TOperator op, TIntermTyped* e) :
307             flowOp(op),
308             expression(e) { }
309 
310     virtual void traverse(TIntermTraverser*);
311 
getFlowOp()312     TOperator getFlowOp() { return flowOp; }
getExpression()313     TIntermTyped* getExpression() { return expression; }
314 
315 protected:
316     TOperator flowOp;
317     TIntermTyped* expression;  // non-zero except for "return exp;" statements
318 };
319 
320 //
321 // Nodes that correspond to symbols or constants in the source code.
322 //
323 class TIntermSymbol : public TIntermTyped {
324 public:
325     // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. If sym comes from
326     // per process globalpoolallocator, then it causes increased memory usage per compile
327     // it is essential to use "symbol = sym" to assign to symbol
TIntermSymbol(int i,const TString & sym,const TType & t)328     TIntermSymbol(int i, const TString& sym, const TType& t) :
329             TIntermTyped(t), id(i)  { symbol = sym;}
330 
getId()331     int getId() const { return id; }
getSymbol()332     const TString& getSymbol() const { return symbol; }
333 
334     virtual void traverse(TIntermTraverser*);
getAsSymbolNode()335     virtual TIntermSymbol* getAsSymbolNode() { return this; }
336 
337 protected:
338     int id;
339     TString symbol;
340 };
341 
342 class TIntermConstantUnion : public TIntermTyped {
343 public:
TIntermConstantUnion(ConstantUnion * unionPointer,const TType & t)344     TIntermConstantUnion(ConstantUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer) { }
345 
getUnionArrayPointer()346     ConstantUnion* getUnionArrayPointer() const { return unionArrayPointer; }
setUnionArrayPointer(ConstantUnion * c)347     void setUnionArrayPointer(ConstantUnion *c) { unionArrayPointer = c; }
348 
getAsConstantUnion()349     virtual TIntermConstantUnion* getAsConstantUnion()  { return this; }
350     virtual void traverse(TIntermTraverser*);
351 
352     TIntermTyped* fold(TOperator, TIntermTyped*, TInfoSink&);
353 
354 protected:
355     ConstantUnion *unionArrayPointer;
356 };
357 
358 //
359 // Intermediate class for node types that hold operators.
360 //
361 class TIntermOperator : public TIntermTyped {
362 public:
getOp()363     TOperator getOp() const { return op; }
setOp(TOperator o)364     void setOp(TOperator o) { op = o; }
365 
366     bool modifiesState() const;
367     bool isConstructor() const;
368 
369 protected:
TIntermOperator(TOperator o)370     TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat, EbpUndefined)), op(o) {}
TIntermOperator(TOperator o,TType & t)371     TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o) {}
372     TOperator op;
373 };
374 
375 //
376 // Nodes for all the basic binary math operators.
377 //
378 class TIntermBinary : public TIntermOperator {
379 public:
TIntermBinary(TOperator o)380     TIntermBinary(TOperator o) : TIntermOperator(o) {}
381 
getAsBinaryNode()382     virtual TIntermBinary* getAsBinaryNode() { return this; }
383     virtual void traverse(TIntermTraverser*);
384 
setLeft(TIntermTyped * n)385     void setLeft(TIntermTyped* n) { left = n; }
setRight(TIntermTyped * n)386     void setRight(TIntermTyped* n) { right = n; }
getLeft()387     TIntermTyped* getLeft() const { return left; }
getRight()388     TIntermTyped* getRight() const { return right; }
389     bool promote(TInfoSink&);
390 
391 protected:
392     TIntermTyped* left;
393     TIntermTyped* right;
394 };
395 
396 //
397 // Nodes for unary math operators.
398 //
399 class TIntermUnary : public TIntermOperator {
400 public:
TIntermUnary(TOperator o,TType & t)401     TIntermUnary(TOperator o, TType& t) : TIntermOperator(o, t), operand(0) {}
TIntermUnary(TOperator o)402     TIntermUnary(TOperator o) : TIntermOperator(o), operand(0) {}
403 
404     virtual void traverse(TIntermTraverser*);
getAsUnaryNode()405     virtual TIntermUnary* getAsUnaryNode() { return this; }
406 
setOperand(TIntermTyped * o)407     void setOperand(TIntermTyped* o) { operand = o; }
getOperand()408     TIntermTyped* getOperand() { return operand; }
409     bool promote(TInfoSink&);
410 
411 protected:
412     TIntermTyped* operand;
413 };
414 
415 typedef TVector<TIntermNode*> TIntermSequence;
416 typedef TVector<int> TQualifierList;
417 typedef TMap<TString, TString> TPragmaTable;
418 //
419 // Nodes that operate on an arbitrary sized set of children.
420 //
421 class TIntermAggregate : public TIntermOperator {
422 public:
TIntermAggregate()423     TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), pragmaTable(0) { }
TIntermAggregate(TOperator o)424     TIntermAggregate(TOperator o) : TIntermOperator(o), pragmaTable(0) { }
~TIntermAggregate()425     ~TIntermAggregate() { delete pragmaTable; }
426 
getAsAggregate()427     virtual TIntermAggregate* getAsAggregate() { return this; }
428     virtual void traverse(TIntermTraverser*);
429 
getSequence()430     TIntermSequence& getSequence() { return sequence; }
431 
setName(const TString & n)432     void setName(const TString& n) { name = n; }
getName()433     const TString& getName() const { return name; }
434 
setUserDefined()435     void setUserDefined() { userDefined = true; }
isUserDefined()436     bool isUserDefined() { return userDefined; }
437 
setOptimize(bool o)438     void setOptimize(bool o) { optimize = o; }
getOptimize()439     bool getOptimize() { return optimize; }
setDebug(bool d)440     void setDebug(bool d) { debug = d; }
getDebug()441     bool getDebug() { return debug; }
442     void addToPragmaTable(const TPragmaTable& pTable);
getPragmaTable()443     const TPragmaTable& getPragmaTable() const { return *pragmaTable; }
444 
445 protected:
446     TIntermAggregate(const TIntermAggregate&); // disallow copy constructor
447     TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator
448     TIntermSequence sequence;
449     TString name;
450     bool userDefined; // used for user defined function names
451 
452     bool optimize;
453     bool debug;
454     TPragmaTable *pragmaTable;
455 };
456 
457 //
458 // For if tests.  Simplified since there is no switch statement.
459 //
460 class TIntermSelection : public TIntermTyped {
461 public:
TIntermSelection(TIntermTyped * cond,TIntermNode * trueB,TIntermNode * falseB)462     TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) :
463             TIntermTyped(TType(EbtVoid, EbpUndefined)), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
TIntermSelection(TIntermTyped * cond,TIntermNode * trueB,TIntermNode * falseB,const TType & type)464     TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) :
465             TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
466 
467     virtual void traverse(TIntermTraverser*);
468 
usesTernaryOperator()469     bool usesTernaryOperator() const { return getBasicType() != EbtVoid; }
getCondition()470     TIntermNode* getCondition() const { return condition; }
getTrueBlock()471     TIntermNode* getTrueBlock() const { return trueBlock; }
getFalseBlock()472     TIntermNode* getFalseBlock() const { return falseBlock; }
getAsSelectionNode()473     TIntermSelection* getAsSelectionNode() { return this; }
474 
475 protected:
476     TIntermTyped* condition;
477     TIntermNode* trueBlock;
478     TIntermNode* falseBlock;
479 };
480 
481 enum Visit
482 {
483     PreVisit,
484     InVisit,
485     PostVisit
486 };
487 
488 //
489 // For traversing the tree.  User should derive from this,
490 // put their traversal specific data in it, and then pass
491 // it to a Traverse method.
492 //
493 // When using this, just fill in the methods for nodes you want visited.
494 // Return false from a pre-visit to skip visiting that node's subtree.
495 //
496 class TIntermTraverser
497 {
498 public:
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)499     POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
500 
501     TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) :
502             preVisit(preVisit),
503             inVisit(inVisit),
504             postVisit(postVisit),
505             rightToLeft(rightToLeft),
506             depth(0) {}
507 
visitSymbol(TIntermSymbol *)508     virtual void visitSymbol(TIntermSymbol*) {}
visitConstantUnion(TIntermConstantUnion *)509     virtual void visitConstantUnion(TIntermConstantUnion*) {}
visitBinary(Visit visit,TIntermBinary *)510     virtual bool visitBinary(Visit visit, TIntermBinary*) {return true;}
visitUnary(Visit visit,TIntermUnary *)511     virtual bool visitUnary(Visit visit, TIntermUnary*) {return true;}
visitSelection(Visit visit,TIntermSelection *)512     virtual bool visitSelection(Visit visit, TIntermSelection*) {return true;}
visitAggregate(Visit visit,TIntermAggregate *)513     virtual bool visitAggregate(Visit visit, TIntermAggregate*) {return true;}
visitLoop(Visit visit,TIntermLoop *)514     virtual bool visitLoop(Visit visit, TIntermLoop*) {return true;}
visitBranch(Visit visit,TIntermBranch *)515     virtual bool visitBranch(Visit visit, TIntermBranch*) {return true;}
516 
incrementDepth()517     void incrementDepth() {depth++;}
decrementDepth()518     void decrementDepth() {depth--;}
519 
520     const bool preVisit;
521     const bool inVisit;
522     const bool postVisit;
523     const bool rightToLeft;
524 
525 protected:
526     int depth;
527 };
528 
529 #endif // __INTERMEDIATE_H
530