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:
205 0 : POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
206 :
207 0 : TIntermNode() : line(0) {}
208 :
209 0 : TSourceLoc getLine() const { return line; }
210 0 : void setLine(TSourceLoc l) { line = l; }
211 :
212 : virtual void traverse(TIntermTraverser*) = 0;
213 0 : virtual TIntermTyped* getAsTyped() { return 0; }
214 0 : virtual TIntermConstantUnion* getAsConstantUnion() { return 0; }
215 0 : virtual TIntermAggregate* getAsAggregate() { return 0; }
216 0 : virtual TIntermBinary* getAsBinaryNode() { return 0; }
217 0 : virtual TIntermUnary* getAsUnaryNode() { return 0; }
218 0 : virtual TIntermSelection* getAsSelectionNode() { return 0; }
219 0 : virtual TIntermSymbol* getAsSymbolNode() { return 0; }
220 0 : virtual TIntermLoop* getAsLoopNode() { return 0; }
221 0 : 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 0 : class TIntermTyped : public TIntermNode {
239 : public:
240 0 : TIntermTyped(const TType& t) : type(t) { }
241 0 : virtual TIntermTyped* getAsTyped() { return this; }
242 :
243 0 : void setType(const TType& t) { type = t; }
244 0 : const TType& getType() const { return type; }
245 0 : TType* getTypePointer() { return &type; }
246 :
247 0 : TBasicType getBasicType() const { return type.getBasicType(); }
248 0 : TQualifier getQualifier() const { return type.getQualifier(); }
249 0 : TPrecision getPrecision() const { return type.getPrecision(); }
250 0 : int getNominalSize() const { return type.getNominalSize(); }
251 :
252 0 : bool isMatrix() const { return type.isMatrix(); }
253 0 : bool isArray() const { return type.isArray(); }
254 0 : bool isVector() const { return type.isVector(); }
255 0 : bool isScalar() const { return type.isScalar(); }
256 : const char* getBasicString() const { return type.getBasicString(); }
257 : const char* getQualifierString() const { return type.getQualifierString(); }
258 0 : 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 0 : class TIntermLoop : public TIntermNode {
274 : public:
275 0 : 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 0 : unrollFlag(false) { }
284 :
285 0 : virtual TIntermLoop* getAsLoopNode() { return this; }
286 : virtual void traverse(TIntermTraverser*);
287 :
288 0 : TLoopType getType() const { return type; }
289 0 : TIntermNode* getInit() { return init; }
290 0 : TIntermTyped* getCondition() { return cond; }
291 0 : TIntermTyped* getExpression() { return expr; }
292 0 : TIntermNode* getBody() { return body; }
293 :
294 0 : void setUnrollFlag(bool flag) { unrollFlag = flag; }
295 0 : bool getUnrollFlag() { return unrollFlag; }
296 :
297 : protected:
298 : TLoopType type;
299 : TIntermNode* init; // for-loop initialization
300 : TIntermTyped* cond; // loop exit condition
301 : TIntermTyped* expr; // for-loop expression
302 : TIntermNode* body; // loop body
303 :
304 : bool unrollFlag; // Whether the loop should be unrolled or not.
305 : };
306 :
307 : //
308 : // Handle break, continue, return, and kill.
309 : //
310 0 : class TIntermBranch : public TIntermNode {
311 : public:
312 0 : TIntermBranch(TOperator op, TIntermTyped* e) :
313 : flowOp(op),
314 0 : expression(e) { }
315 :
316 : virtual void traverse(TIntermTraverser*);
317 :
318 0 : TOperator getFlowOp() { return flowOp; }
319 0 : TIntermTyped* getExpression() { return expression; }
320 :
321 : protected:
322 : TOperator flowOp;
323 : TIntermTyped* expression; // non-zero except for "return exp;" statements
324 : };
325 :
326 : //
327 : // Nodes that correspond to symbols or constants in the source code.
328 : //
329 0 : class TIntermSymbol : public TIntermTyped {
330 : public:
331 : // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. If sym comes from
332 : // per process globalpoolallocator, then it causes increased memory usage per compile
333 : // it is essential to use "symbol = sym" to assign to symbol
334 0 : TIntermSymbol(int i, const TString& sym, const TType& t) :
335 0 : TIntermTyped(t), id(i) { symbol = sym; originalSymbol = sym; }
336 :
337 0 : int getId() const { return id; }
338 0 : const TString& getSymbol() const { return symbol; }
339 :
340 0 : void setId(int newId) { id = newId; }
341 0 : void setSymbol(const TString& sym) { symbol = sym; }
342 :
343 0 : const TString& getOriginalSymbol() const { return originalSymbol; }
344 :
345 : virtual void traverse(TIntermTraverser*);
346 0 : virtual TIntermSymbol* getAsSymbolNode() { return this; }
347 :
348 : protected:
349 : int id;
350 : TString symbol;
351 : TString originalSymbol;
352 : };
353 :
354 0 : class TIntermConstantUnion : public TIntermTyped {
355 : public:
356 0 : TIntermConstantUnion(ConstantUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer) { }
357 :
358 0 : ConstantUnion* getUnionArrayPointer() const { return unionArrayPointer; }
359 : void setUnionArrayPointer(ConstantUnion *c) { unionArrayPointer = c; }
360 :
361 0 : virtual TIntermConstantUnion* getAsConstantUnion() { return this; }
362 : virtual void traverse(TIntermTraverser*);
363 :
364 : TIntermTyped* fold(TOperator, TIntermTyped*, TInfoSink&);
365 :
366 : protected:
367 : ConstantUnion *unionArrayPointer;
368 : };
369 :
370 : //
371 : // Intermediate class for node types that hold operators.
372 : //
373 0 : class TIntermOperator : public TIntermTyped {
374 : public:
375 0 : TOperator getOp() const { return op; }
376 0 : void setOp(TOperator o) { op = o; }
377 :
378 : bool modifiesState() const;
379 : bool isConstructor() const;
380 :
381 : protected:
382 0 : TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat, EbpUndefined)), op(o) {}
383 0 : TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o) {}
384 : TOperator op;
385 : };
386 :
387 : //
388 : // Nodes for all the basic binary math operators.
389 : //
390 0 : class TIntermBinary : public TIntermOperator {
391 : public:
392 0 : TIntermBinary(TOperator o) : TIntermOperator(o) {}
393 :
394 0 : virtual TIntermBinary* getAsBinaryNode() { return this; }
395 : virtual void traverse(TIntermTraverser*);
396 :
397 0 : void setLeft(TIntermTyped* n) { left = n; }
398 0 : void setRight(TIntermTyped* n) { right = n; }
399 0 : TIntermTyped* getLeft() const { return left; }
400 0 : TIntermTyped* getRight() const { return right; }
401 : bool promote(TInfoSink&);
402 :
403 : protected:
404 : TIntermTyped* left;
405 : TIntermTyped* right;
406 : };
407 :
408 : //
409 : // Nodes for unary math operators.
410 : //
411 0 : class TIntermUnary : public TIntermOperator {
412 : public:
413 0 : TIntermUnary(TOperator o, TType& t) : TIntermOperator(o, t), operand(0), useEmulatedFunction(false) {}
414 0 : TIntermUnary(TOperator o) : TIntermOperator(o), operand(0), useEmulatedFunction(false) {}
415 :
416 : virtual void traverse(TIntermTraverser*);
417 0 : virtual TIntermUnary* getAsUnaryNode() { return this; }
418 :
419 0 : void setOperand(TIntermTyped* o) { operand = o; }
420 0 : TIntermTyped* getOperand() { return operand; }
421 : bool promote(TInfoSink&);
422 :
423 0 : void setUseEmulatedFunction() { useEmulatedFunction = true; }
424 0 : bool getUseEmulatedFunction() { return useEmulatedFunction; }
425 :
426 : protected:
427 : TIntermTyped* operand;
428 :
429 : // If set to true, replace the built-in function call with an emulated one
430 : // to work around driver bugs.
431 : bool useEmulatedFunction;
432 : };
433 :
434 : typedef TVector<TIntermNode*> TIntermSequence;
435 : typedef TVector<int> TQualifierList;
436 : typedef TMap<TString, TString> TPragmaTable;
437 : //
438 : // Nodes that operate on an arbitrary sized set of children.
439 : //
440 : class TIntermAggregate : public TIntermOperator {
441 : public:
442 0 : TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), pragmaTable(0), endLine(0), useEmulatedFunction(false) { }
443 0 : TIntermAggregate(TOperator o) : TIntermOperator(o), pragmaTable(0), useEmulatedFunction(false) { }
444 0 : ~TIntermAggregate() { delete pragmaTable; }
445 :
446 0 : virtual TIntermAggregate* getAsAggregate() { return this; }
447 : virtual void traverse(TIntermTraverser*);
448 :
449 0 : TIntermSequence& getSequence() { return sequence; }
450 :
451 0 : void setName(const TString& n) { name = n; }
452 0 : const TString& getName() const { return name; }
453 :
454 0 : void setUserDefined() { userDefined = true; }
455 : bool isUserDefined() { return userDefined; }
456 :
457 0 : void setOptimize(bool o) { optimize = o; }
458 : bool getOptimize() { return optimize; }
459 0 : void setDebug(bool d) { debug = d; }
460 : bool getDebug() { return debug; }
461 : void addToPragmaTable(const TPragmaTable& pTable);
462 : const TPragmaTable& getPragmaTable() const { return *pragmaTable; }
463 0 : void setEndLine(TSourceLoc line) { endLine = line; }
464 0 : TSourceLoc getEndLine() const { return endLine; }
465 :
466 0 : void setUseEmulatedFunction() { useEmulatedFunction = true; }
467 0 : bool getUseEmulatedFunction() { return useEmulatedFunction; }
468 :
469 : protected:
470 : TIntermAggregate(const TIntermAggregate&); // disallow copy constructor
471 : TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator
472 : TIntermSequence sequence;
473 : TString name;
474 : bool userDefined; // used for user defined function names
475 :
476 : bool optimize;
477 : bool debug;
478 : TPragmaTable *pragmaTable;
479 : TSourceLoc endLine;
480 :
481 : // If set to true, replace the built-in function call with an emulated one
482 : // to work around driver bugs.
483 : bool useEmulatedFunction;
484 : };
485 :
486 : //
487 : // For if tests. Simplified since there is no switch statement.
488 : //
489 0 : class TIntermSelection : public TIntermTyped {
490 : public:
491 0 : TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) :
492 0 : TIntermTyped(TType(EbtVoid, EbpUndefined)), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
493 0 : TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) :
494 0 : TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
495 :
496 : virtual void traverse(TIntermTraverser*);
497 :
498 0 : bool usesTernaryOperator() const { return getBasicType() != EbtVoid; }
499 0 : TIntermNode* getCondition() const { return condition; }
500 0 : TIntermNode* getTrueBlock() const { return trueBlock; }
501 0 : TIntermNode* getFalseBlock() const { return falseBlock; }
502 0 : TIntermSelection* getAsSelectionNode() { return this; }
503 :
504 : protected:
505 : TIntermTyped* condition;
506 : TIntermNode* trueBlock;
507 : TIntermNode* falseBlock;
508 : };
509 :
510 : enum Visit
511 : {
512 : PreVisit,
513 : InVisit,
514 : PostVisit
515 : };
516 :
517 : //
518 : // For traversing the tree. User should derive from this,
519 : // put their traversal specific data in it, and then pass
520 : // it to a Traverse method.
521 : //
522 : // When using this, just fill in the methods for nodes you want visited.
523 : // Return false from a pre-visit to skip visiting that node's subtree.
524 : //
525 : class TIntermTraverser
526 : {
527 : public:
528 : POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
529 :
530 0 : TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) :
531 : preVisit(preVisit),
532 : inVisit(inVisit),
533 : postVisit(postVisit),
534 : rightToLeft(rightToLeft),
535 0 : depth(0) {}
536 :
537 0 : virtual void visitSymbol(TIntermSymbol*) {}
538 0 : virtual void visitConstantUnion(TIntermConstantUnion*) {}
539 0 : virtual bool visitBinary(Visit visit, TIntermBinary*) {return true;}
540 0 : virtual bool visitUnary(Visit visit, TIntermUnary*) {return true;}
541 0 : virtual bool visitSelection(Visit visit, TIntermSelection*) {return true;}
542 0 : virtual bool visitAggregate(Visit visit, TIntermAggregate*) {return true;}
543 0 : virtual bool visitLoop(Visit visit, TIntermLoop*) {return true;}
544 0 : virtual bool visitBranch(Visit visit, TIntermBranch*) {return true;}
545 :
546 0 : void incrementDepth() {depth++;}
547 0 : void decrementDepth() {depth--;}
548 :
549 : const bool preVisit;
550 : const bool inVisit;
551 : const bool postVisit;
552 : const bool rightToLeft;
553 :
554 : protected:
555 : int depth;
556 : };
557 :
558 : #endif // __INTERMEDIATE_H
|