Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / angle / src / compiler / translator / intermediate.h
1 //
2 // Copyright (c) 2002-2013 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 "GLSLANG/ShaderLang.h"
20
21 #include <algorithm>
22 #include <queue>
23 #include "compiler/translator/Common.h"
24 #include "compiler/translator/Types.h"
25 #include "compiler/translator/ConstantUnion.h"
26
27 //
28 // Operators used by the high-level (parse tree) representation.
29 //
30 enum TOperator {
31     EOpNull,            // if in a node, should only mean a node is still being built
32     EOpSequence,        // denotes a list of statements, or parameters, etc.
33     EOpFunctionCall,    
34     EOpFunction,        // For function definition
35     EOpParameters,      // an aggregate listing the parameters to a function
36
37     EOpDeclaration,
38     EOpPrototype,
39
40     //
41     // Unary operators
42     //
43
44     EOpNegative,
45     EOpLogicalNot,
46     EOpVectorLogicalNot,
47
48     EOpPostIncrement,
49     EOpPostDecrement,
50     EOpPreIncrement,
51     EOpPreDecrement,
52
53     EOpConvIntToBool,
54     EOpConvFloatToBool,
55     EOpConvBoolToFloat,
56     EOpConvIntToFloat,
57     EOpConvFloatToInt,
58     EOpConvBoolToInt,
59
60     //
61     // binary operations
62     //
63
64     EOpAdd,
65     EOpSub,
66     EOpMul,
67     EOpDiv,
68     EOpEqual,
69     EOpNotEqual,
70     EOpVectorEqual,
71     EOpVectorNotEqual,
72     EOpLessThan,
73     EOpGreaterThan,
74     EOpLessThanEqual,
75     EOpGreaterThanEqual,
76     EOpComma,
77
78     EOpVectorTimesScalar,
79     EOpVectorTimesMatrix,
80     EOpMatrixTimesVector,
81     EOpMatrixTimesScalar,
82
83     EOpLogicalOr,
84     EOpLogicalXor,
85     EOpLogicalAnd,
86
87     EOpIndexDirect,
88     EOpIndexIndirect,
89     EOpIndexDirectStruct,
90
91     EOpVectorSwizzle,
92
93     //
94     // Built-in functions potentially mapped to operators
95     //
96
97     EOpRadians,
98     EOpDegrees,
99     EOpSin,
100     EOpCos,
101     EOpTan,
102     EOpAsin,
103     EOpAcos,
104     EOpAtan,
105
106     EOpPow,
107     EOpExp,
108     EOpLog,
109     EOpExp2,
110     EOpLog2,
111     EOpSqrt,
112     EOpInverseSqrt,
113
114     EOpAbs,
115     EOpSign,
116     EOpFloor,
117     EOpCeil,
118     EOpFract,
119     EOpMod,
120     EOpMin,
121     EOpMax,
122     EOpClamp,
123     EOpMix,
124     EOpStep,
125     EOpSmoothStep,
126
127     EOpLength,
128     EOpDistance,
129     EOpDot,
130     EOpCross,
131     EOpNormalize,
132     EOpFaceForward,
133     EOpReflect,
134     EOpRefract,
135
136     EOpDFdx,            // Fragment only, OES_standard_derivatives extension
137     EOpDFdy,            // Fragment only, OES_standard_derivatives extension
138     EOpFwidth,          // Fragment only, OES_standard_derivatives extension
139
140     EOpMatrixTimesMatrix,
141
142     EOpAny,
143     EOpAll,
144
145     //
146     // Branch
147     //
148
149     EOpKill,            // Fragment only
150     EOpReturn,
151     EOpBreak,
152     EOpContinue,
153
154     //
155     // Constructors
156     //
157
158     EOpConstructInt,
159     EOpConstructBool,
160     EOpConstructFloat,
161     EOpConstructVec2,
162     EOpConstructVec3,
163     EOpConstructVec4,
164     EOpConstructBVec2,
165     EOpConstructBVec3,
166     EOpConstructBVec4,
167     EOpConstructIVec2,
168     EOpConstructIVec3,
169     EOpConstructIVec4,
170     EOpConstructMat2,
171     EOpConstructMat3,
172     EOpConstructMat4,
173     EOpConstructStruct,
174
175     //
176     // moves
177     //
178
179     EOpAssign,
180     EOpInitialize,
181     EOpAddAssign,
182     EOpSubAssign,
183     EOpMulAssign,
184     EOpVectorTimesMatrixAssign,
185     EOpVectorTimesScalarAssign,
186     EOpMatrixTimesScalarAssign,
187     EOpMatrixTimesMatrixAssign,
188     EOpDivAssign
189 };
190
191 extern const char* getOperatorString(TOperator op);
192
193 class TIntermTraverser;
194 class TIntermAggregate;
195 class TIntermBinary;
196 class TIntermUnary;
197 class TIntermConstantUnion;
198 class TIntermSelection;
199 class TIntermTyped;
200 class TIntermSymbol;
201 class TIntermLoop;
202 class TInfoSink;
203 class TIntermRaw;
204
205 //
206 // Base class for the tree nodes
207 //
208 class TIntermNode {
209 public:
210     POOL_ALLOCATOR_NEW_DELETE();
211     TIntermNode() {
212         // TODO: Move this to TSourceLoc constructor
213         // after getting rid of TPublicType.
214         line.first_file = line.last_file = 0;
215         line.first_line = line.last_line = 0;
216     }
217     virtual ~TIntermNode() { }
218
219     const TSourceLoc& getLine() const { return line; }
220     void setLine(const TSourceLoc& l) { line = l; }
221
222     virtual void traverse(TIntermTraverser*) = 0;
223     virtual TIntermTyped* getAsTyped() { return 0; }
224     virtual TIntermConstantUnion* getAsConstantUnion() { return 0; }
225     virtual TIntermAggregate* getAsAggregate() { return 0; }
226     virtual TIntermBinary* getAsBinaryNode() { return 0; }
227     virtual TIntermUnary* getAsUnaryNode() { return 0; }
228     virtual TIntermSelection* getAsSelectionNode() { return 0; }
229     virtual TIntermSymbol* getAsSymbolNode() { return 0; }
230     virtual TIntermLoop* getAsLoopNode() { return 0; }
231     virtual TIntermRaw* getAsRawNode() { return 0; }
232
233     // Replace a child node. Return true if |original| is a child
234     // node and it is replaced; otherwise, return false.
235     virtual bool replaceChildNode(
236         TIntermNode *original, TIntermNode *replacement) = 0;
237
238     // For traversing a tree in no particular order, but using
239     // heap memory.
240     virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const = 0;
241
242 protected:
243     TSourceLoc line;
244 };
245
246 //
247 // This is just to help yacc.
248 //
249 struct TIntermNodePair {
250     TIntermNode* node1;
251     TIntermNode* node2;
252 };
253
254 //
255 // Intermediate class for nodes that have a type.
256 //
257 class TIntermTyped : public TIntermNode {
258 public:
259     TIntermTyped(const TType& t) : type(t)  { }
260     virtual TIntermTyped* getAsTyped() { return this; }
261
262     virtual bool hasSideEffects() const = 0;
263
264     void setType(const TType& t) { type = t; }
265     const TType& getType() const { return type; }
266     TType* getTypePointer() { return &type; }
267
268     TBasicType getBasicType() const { return type.getBasicType(); }
269     TQualifier getQualifier() const { return type.getQualifier(); }
270     TPrecision getPrecision() const { return type.getPrecision(); }
271     int getNominalSize() const { return type.getNominalSize(); }
272     
273     bool isMatrix() const { return type.isMatrix(); }
274     bool isArray()  const { return type.isArray(); }
275     bool isVector() const { return type.isVector(); }
276     bool isScalar() const { return type.isScalar(); }
277     const char* getBasicString() const { return type.getBasicString(); }
278     const char* getQualifierString() const { return type.getQualifierString(); }
279     TString getCompleteString() const { return type.getCompleteString(); }
280
281     int totalRegisterCount() const { return type.totalRegisterCount(); }
282     int elementRegisterCount() const { return type.elementRegisterCount(); }
283     int getArraySize() const { return type.getArraySize(); }
284
285 protected:
286     TType type;
287 };
288
289 //
290 // Handle for, do-while, and while loops.
291 //
292 enum TLoopType {
293     ELoopFor,
294     ELoopWhile,
295     ELoopDoWhile
296 };
297
298 class TIntermLoop : public TIntermNode {
299 public:
300     TIntermLoop(TLoopType aType,
301                 TIntermNode *aInit, TIntermTyped* aCond, TIntermTyped* aExpr,
302                 TIntermNode* aBody) :
303             type(aType),
304             init(aInit),
305             cond(aCond),
306             expr(aExpr),
307             body(aBody),
308             unrollFlag(false) { }
309
310     virtual TIntermLoop* getAsLoopNode() { return this; }
311     virtual void traverse(TIntermTraverser*);
312     virtual bool replaceChildNode(
313         TIntermNode *original, TIntermNode *replacement);
314
315     TLoopType getType() const { return type; }
316     TIntermNode* getInit() { return init; }
317     TIntermTyped* getCondition() { return cond; }
318     TIntermTyped* getExpression() { return expr; }
319     TIntermNode* getBody() { return body; }
320
321     void setUnrollFlag(bool flag) { unrollFlag = flag; }
322     bool getUnrollFlag() { return unrollFlag; }
323
324     virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
325
326 protected:
327     TLoopType type;
328     TIntermNode* init;  // for-loop initialization
329     TIntermTyped* cond; // loop exit condition
330     TIntermTyped* expr; // for-loop expression
331     TIntermNode* body;  // loop body
332
333     bool unrollFlag; // Whether the loop should be unrolled or not.
334 };
335
336 //
337 // Handle break, continue, return, and kill.
338 //
339 class TIntermBranch : public TIntermNode {
340 public:
341     TIntermBranch(TOperator op, TIntermTyped* e) :
342             flowOp(op),
343             expression(e) { }
344
345     virtual void traverse(TIntermTraverser*);
346     virtual bool replaceChildNode(
347         TIntermNode *original, TIntermNode *replacement);
348
349     TOperator getFlowOp() { return flowOp; }
350     TIntermTyped* getExpression() { return expression; }
351
352     virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
353
354 protected:
355     TOperator flowOp;
356     TIntermTyped* expression;  // non-zero except for "return exp;" statements
357 };
358
359 //
360 // Nodes that correspond to symbols or constants in the source code.
361 //
362 class TIntermSymbol : public TIntermTyped {
363 public:
364     // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. If sym comes from
365     // per process globalpoolallocator, then it causes increased memory usage per compile
366     // it is essential to use "symbol = sym" to assign to symbol
367     TIntermSymbol(int i, const TString& sym, const TType& t) : 
368         TIntermTyped(t), id(i)  { symbol = sym; }
369
370     virtual bool hasSideEffects() const { return false; }
371
372     int getId() const { return id; }
373     const TString& getSymbol() const { return symbol; }
374
375     void setId(int newId) { id = newId; }
376
377     virtual void traverse(TIntermTraverser*);
378     virtual TIntermSymbol* getAsSymbolNode() { return this; }
379     virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
380
381     virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const {}
382
383 protected:
384     int id;
385     TString symbol;
386 };
387
388 // A Raw node stores raw code, that the translator will insert verbatim
389 // into the output stream. Useful for transformation operations that make
390 // complex code that might not fit naturally into the GLSL model.
391 class TIntermRaw : public TIntermTyped {
392 public:
393     TIntermRaw(const TType &t, const TString &rawTextIn)
394         : TIntermTyped(t), rawText(rawTextIn)
395     {}
396
397     virtual bool hasSideEffects() const { return false; }
398
399     TString getRawText() const { return rawText; }
400
401     virtual void traverse(TIntermTraverser*);
402
403     virtual TIntermRaw* getAsRawNode() { return this; }
404     virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
405
406     virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const {}
407
408 protected:
409     TString rawText;
410 };
411
412 class TIntermConstantUnion : public TIntermTyped {
413 public:
414     TIntermConstantUnion(ConstantUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer) { }
415
416     virtual bool hasSideEffects() const { return false; }
417
418     ConstantUnion* getUnionArrayPointer() const { return unionArrayPointer; }
419     
420     int getIConst(size_t index) const { return unionArrayPointer ? unionArrayPointer[index].getIConst() : 0; }
421     float getFConst(size_t index) const { return unionArrayPointer ? unionArrayPointer[index].getFConst() : 0.0f; }
422     bool getBConst(size_t index) const { return unionArrayPointer ? unionArrayPointer[index].getBConst() : false; }
423
424     virtual TIntermConstantUnion* getAsConstantUnion()  { return this; }
425     virtual void traverse(TIntermTraverser*);
426     virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
427
428     TIntermTyped* fold(TOperator, TIntermTyped*, TInfoSink&);
429
430     virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const {}
431
432 protected:
433     ConstantUnion *unionArrayPointer;
434 };
435
436 //
437 // Intermediate class for node types that hold operators.
438 //
439 class TIntermOperator : public TIntermTyped {
440 public:
441     TOperator getOp() const { return op; }
442     void setOp(TOperator o) { op = o; }
443
444     bool isAssignment() const;
445     bool isConstructor() const;
446
447     virtual bool hasSideEffects() const { return isAssignment(); }
448
449 protected:
450     TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat, EbpUndefined)), op(o) {}
451     TIntermOperator(TOperator o, const TType& t) : TIntermTyped(t), op(o) {}
452     TOperator op;
453 };
454
455 //
456 // Nodes for all the basic binary math operators.
457 //
458 class TIntermBinary : public TIntermOperator {
459 public:
460     TIntermBinary(TOperator o) : TIntermOperator(o), addIndexClamp(false) {}
461
462     virtual TIntermBinary* getAsBinaryNode() { return this; }
463     virtual void traverse(TIntermTraverser*);
464     virtual bool replaceChildNode(
465         TIntermNode *original, TIntermNode *replacement);
466
467     virtual bool hasSideEffects() const { return (isAssignment() || left->hasSideEffects() || right->hasSideEffects()); }
468
469     void setLeft(TIntermTyped* n) { left = n; }
470     void setRight(TIntermTyped* n) { right = n; }
471     TIntermTyped* getLeft() const { return left; }
472     TIntermTyped* getRight() const { return right; }
473     bool promote(TInfoSink&);
474
475     void setAddIndexClamp() { addIndexClamp = true; }
476     bool getAddIndexClamp() { return addIndexClamp; }
477
478     virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
479
480 protected:
481     TIntermTyped* left;
482     TIntermTyped* right;
483
484     // If set to true, wrap any EOpIndexIndirect with a clamp to bounds.
485     bool addIndexClamp;
486 };
487
488 //
489 // Nodes for unary math operators.
490 //
491 class TIntermUnary : public TIntermOperator {
492 public:
493     TIntermUnary(TOperator o, const TType& t) : TIntermOperator(o, t), operand(0), useEmulatedFunction(false) {}
494     TIntermUnary(TOperator o) : TIntermOperator(o), operand(0), useEmulatedFunction(false) {}
495
496     virtual void traverse(TIntermTraverser*);
497     virtual TIntermUnary* getAsUnaryNode() { return this; }
498     virtual bool replaceChildNode(
499         TIntermNode *original, TIntermNode *replacement);
500
501     virtual bool hasSideEffects() const { return (isAssignment() || operand->hasSideEffects()); }
502
503     void setOperand(TIntermTyped* o) { operand = o; }
504     TIntermTyped* getOperand() { return operand; }    
505     bool promote(TInfoSink&);
506
507     void setUseEmulatedFunction() { useEmulatedFunction = true; }
508     bool getUseEmulatedFunction() { return useEmulatedFunction; }
509
510     virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
511
512 protected:
513     TIntermTyped* operand;
514
515     // If set to true, replace the built-in function call with an emulated one
516     // to work around driver bugs.
517     bool useEmulatedFunction;
518 };
519
520 typedef TVector<TIntermNode*> TIntermSequence;
521 typedef TVector<int> TQualifierList;
522
523 //
524 // Nodes that operate on an arbitrary sized set of children.
525 //
526 class TIntermAggregate : public TIntermOperator {
527 public:
528     TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), useEmulatedFunction(false) { }
529     TIntermAggregate(TOperator o) : TIntermOperator(o), useEmulatedFunction(false) { }
530     ~TIntermAggregate() { }
531
532     virtual TIntermAggregate* getAsAggregate() { return this; }
533     virtual void traverse(TIntermTraverser*);
534     virtual bool replaceChildNode(
535         TIntermNode *original, TIntermNode *replacement);
536
537     // Conservatively assume function calls and other aggregate operators have side-effects
538     virtual bool hasSideEffects() const { return true; }
539
540     TIntermSequence& getSequence() { return sequence; }
541
542     void setName(const TString& n) { name = n; }
543     const TString& getName() const { return name; }
544
545     void setUserDefined() { userDefined = true; }
546     bool isUserDefined() const { return userDefined; }
547
548     void setOptimize(bool o) { optimize = o; }
549     bool getOptimize() { return optimize; }
550     void setDebug(bool d) { debug = d; }
551     bool getDebug() { return debug; }
552
553     void setUseEmulatedFunction() { useEmulatedFunction = true; }
554     bool getUseEmulatedFunction() { return useEmulatedFunction; }
555
556     virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
557
558 protected:
559     TIntermAggregate(const TIntermAggregate&); // disallow copy constructor
560     TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator
561     TIntermSequence sequence;
562     TString name;
563     bool userDefined; // used for user defined function names
564
565     bool optimize;
566     bool debug;
567
568     // If set to true, replace the built-in function call with an emulated one
569     // to work around driver bugs.
570     bool useEmulatedFunction;
571 };
572
573 //
574 // For if tests.  Simplified since there is no switch statement.
575 //
576 class TIntermSelection : public TIntermTyped {
577 public:
578     TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) :
579             TIntermTyped(TType(EbtVoid, EbpUndefined)), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
580     TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) :
581             TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
582
583     virtual void traverse(TIntermTraverser*);
584     virtual bool replaceChildNode(
585         TIntermNode *original, TIntermNode *replacement);
586
587     // Conservatively assume selections have side-effects
588     virtual bool hasSideEffects() const { return true; }
589
590     bool usesTernaryOperator() const { return getBasicType() != EbtVoid; }
591     TIntermNode* getCondition() const { return condition; }
592     TIntermNode* getTrueBlock() const { return trueBlock; }
593     TIntermNode* getFalseBlock() const { return falseBlock; }
594     TIntermSelection* getAsSelectionNode() { return this; }
595
596     virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
597
598 protected:
599     TIntermTyped* condition;
600     TIntermNode* trueBlock;
601     TIntermNode* falseBlock;
602 };
603
604 enum Visit
605 {
606     PreVisit,
607     InVisit,
608     PostVisit
609 };
610
611 //
612 // For traversing the tree.  User should derive from this, 
613 // put their traversal specific data in it, and then pass
614 // it to a Traverse method.
615 //
616 // When using this, just fill in the methods for nodes you want visited.
617 // Return false from a pre-visit to skip visiting that node's subtree.
618 //
619 class TIntermTraverser
620 {
621 public:
622     POOL_ALLOCATOR_NEW_DELETE();
623     TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) : 
624             preVisit(preVisit),
625             inVisit(inVisit),
626             postVisit(postVisit),
627             rightToLeft(rightToLeft),
628             depth(0),
629             maxDepth(0) {}
630     virtual ~TIntermTraverser() {}
631
632     virtual void visitSymbol(TIntermSymbol*) {}
633     virtual void visitRaw(TIntermRaw*) {}
634     virtual void visitConstantUnion(TIntermConstantUnion*) {}
635     virtual bool visitBinary(Visit visit, TIntermBinary*) {return true;}
636     virtual bool visitUnary(Visit visit, TIntermUnary*) {return true;}
637     virtual bool visitSelection(Visit visit, TIntermSelection*) {return true;}
638     virtual bool visitAggregate(Visit visit, TIntermAggregate*) {return true;}
639     virtual bool visitLoop(Visit visit, TIntermLoop*) {return true;}
640     virtual bool visitBranch(Visit visit, TIntermBranch*) {return true;}
641
642     int getMaxDepth() const {return maxDepth;}
643
644     void incrementDepth(TIntermNode *current)
645     {
646         depth++;
647         maxDepth = std::max(maxDepth, depth);
648         path.push_back(current);
649     }
650
651     void decrementDepth()
652     {
653         depth--;
654         path.pop_back();
655     }
656
657     TIntermNode *getParentNode()
658     {
659         return path.size() == 0 ? NULL : path.back();
660     }
661
662     // Return the original name if hash function pointer is NULL;
663     // otherwise return the hashed name.
664     static TString hash(const TString& name, ShHashFunction64 hashFunction);
665
666     const bool preVisit;
667     const bool inVisit;
668     const bool postVisit;
669     const bool rightToLeft;
670
671 protected:
672     int depth;
673     int maxDepth;
674
675     // All the nodes from root to the current node's parent during traversing.
676     TVector<TIntermNode *> path;
677 };
678
679 //
680 // For traversing the tree, and computing max depth.
681 // Takes a maximum depth limit to prevent stack overflow.
682 //
683 class TMaxDepthTraverser : public TIntermTraverser
684 {
685 public:
686     POOL_ALLOCATOR_NEW_DELETE();
687     TMaxDepthTraverser(int depthLimit)
688       : TIntermTraverser(true, true, false, false),
689         depthLimit(depthLimit)
690     {}
691
692     virtual bool visitBinary(Visit visit, TIntermBinary*) { return depthCheck(); }
693     virtual bool visitUnary(Visit visit, TIntermUnary*) { return depthCheck(); }
694     virtual bool visitSelection(Visit visit, TIntermSelection*) { return depthCheck(); }
695     virtual bool visitAggregate(Visit visit, TIntermAggregate*) { return depthCheck(); }
696     virtual bool visitLoop(Visit visit, TIntermLoop*) { return depthCheck(); }
697     virtual bool visitBranch(Visit visit, TIntermBranch*) { return depthCheck(); }
698
699 protected:
700     int depthLimit;
701
702     bool depthCheck() const { return maxDepth < depthLimit; }
703 };
704
705 #endif // __INTERMEDIATE_H