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