Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / angle / src / compiler / translator / intermOut.cpp
1 //
2 // Copyright (c) 2002-2014 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 #include "compiler/translator/Intermediate.h"
8 #include "compiler/translator/SymbolTable.h"
9
10 namespace
11 {
12
13 //
14 // Two purposes:
15 // 1.  Show an example of how to iterate tree.  Functions can
16 //     also directly call Traverse() on children themselves to
17 //     have finer grained control over the process than shown here.
18 //     See the last function for how to get started.
19 // 2.  Print out a text based description of the tree.
20 //
21
22 //
23 // Use this class to carry along data from node to node in
24 // the traversal
25 //
26 class TOutputTraverser : public TIntermTraverser
27 {
28   public:
29     TOutputTraverser(TInfoSinkBase &i)
30         : sink(i) { }
31     TInfoSinkBase& sink;
32
33   protected:
34     void visitSymbol(TIntermSymbol *);
35     void visitConstantUnion(TIntermConstantUnion *);
36     bool visitBinary(Visit visit, TIntermBinary *);
37     bool visitUnary(Visit visit, TIntermUnary *);
38     bool visitSelection(Visit visit, TIntermSelection *);
39     bool visitAggregate(Visit visit, TIntermAggregate *);
40     bool visitLoop(Visit visit, TIntermLoop *);
41     bool visitBranch(Visit visit, TIntermBranch *);
42 };
43
44 //
45 // Helper functions for printing, not part of traversing.
46 //
47 void OutputTreeText(TInfoSinkBase &sink, TIntermNode *node, const int depth)
48 {
49     int i;
50
51     sink.location(node->getLine());
52
53     for (i = 0; i < depth; ++i)
54         sink << "  ";
55 }
56
57 }  // namespace anonymous
58
59
60 TString TType::getCompleteString() const
61 {
62     TStringStream stream;
63
64     if (qualifier != EvqTemporary && qualifier != EvqGlobal)
65         stream << getQualifierString() << " " << getPrecisionString() << " ";
66     if (array)
67         stream << "array[" << getArraySize() << "] of ";
68     if (isMatrix())
69         stream << getCols() << "X" << getRows() << " matrix of ";
70     else if (isVector())
71         stream << getNominalSize() << "-component vector of ";
72
73     stream << getBasicString();
74     return stream.str();
75 }
76
77 //
78 // The rest of the file are the traversal functions.  The last one
79 // is the one that starts the traversal.
80 //
81 // Return true from interior nodes to have the external traversal
82 // continue on to children.  If you process children yourself,
83 // return false.
84 //
85
86 void TOutputTraverser::visitSymbol(TIntermSymbol *node)
87 {
88     OutputTreeText(sink, node, mDepth);
89
90     sink << "'" << node->getSymbol() << "' ";
91     sink << "(" << node->getCompleteString() << ")\n";
92 }
93
94 bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node)
95 {
96     TInfoSinkBase& out = sink;
97
98     OutputTreeText(out, node, mDepth);
99
100     switch (node->getOp())
101     {
102       case EOpAssign:
103         out << "move second child to first child";
104         break;
105       case EOpInitialize:
106         out << "initialize first child with second child";
107         break;
108       case EOpAddAssign:
109         out << "add second child into first child";
110         break;
111       case EOpSubAssign:
112         out << "subtract second child into first child";
113         break;
114       case EOpMulAssign:
115         out << "multiply second child into first child";
116         break;
117       case EOpVectorTimesMatrixAssign:
118         out << "matrix mult second child into first child";
119         break;
120       case EOpVectorTimesScalarAssign:
121         out << "vector scale second child into first child";
122         break;
123       case EOpMatrixTimesScalarAssign:
124         out << "matrix scale second child into first child";
125         break;
126       case EOpMatrixTimesMatrixAssign:
127         out << "matrix mult second child into first child";
128         break;
129       case EOpDivAssign:
130         out << "divide second child into first child";
131         break;
132       case EOpIndexDirect:
133         out << "direct index";
134         break;
135       case EOpIndexIndirect:
136         out << "indirect index";
137         break;
138       case EOpIndexDirectStruct:
139         out << "direct index for structure";
140         break;
141       case EOpIndexDirectInterfaceBlock:
142         out << "direct index for interface block";
143         break;
144       case EOpVectorSwizzle:
145         out << "vector swizzle";
146         break;
147
148       case EOpAdd:
149         out << "add";
150         break;
151       case EOpSub:
152         out << "subtract";
153         break;
154       case EOpMul:
155         out << "component-wise multiply";
156         break;
157       case EOpDiv:
158         out << "divide";
159         break;
160       case EOpEqual:
161         out << "Compare Equal";
162         break;
163       case EOpNotEqual:
164         out << "Compare Not Equal";
165         break;
166       case EOpLessThan:
167         out << "Compare Less Than";
168         break;
169       case EOpGreaterThan:
170         out << "Compare Greater Than";
171         break;
172       case EOpLessThanEqual:
173         out << "Compare Less Than or Equal";
174         break;
175       case EOpGreaterThanEqual:
176         out << "Compare Greater Than or Equal";
177         break;
178
179       case EOpVectorTimesScalar:
180         out << "vector-scale";
181         break;
182       case EOpVectorTimesMatrix:
183         out << "vector-times-matrix";
184         break;
185       case EOpMatrixTimesVector:
186         out << "matrix-times-vector";
187         break;
188       case EOpMatrixTimesScalar:
189         out << "matrix-scale";
190         break;
191       case EOpMatrixTimesMatrix:
192         out << "matrix-multiply";
193         break;
194
195       case EOpLogicalOr:
196         out << "logical-or";
197         break;
198       case EOpLogicalXor:
199         out << "logical-xor";
200         break;
201       case EOpLogicalAnd:
202         out << "logical-and";
203         break;
204       default:
205         out << "<unknown op>";
206     }
207
208     out << " (" << node->getCompleteString() << ")";
209
210     out << "\n";
211
212     return true;
213 }
214
215 bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node)
216 {
217     TInfoSinkBase& out = sink;
218
219     OutputTreeText(out, node, mDepth);
220
221     switch (node->getOp())
222     {
223       case EOpNegative:       out << "Negate value";         break;
224       case EOpVectorLogicalNot:
225       case EOpLogicalNot:     out << "Negate conditional";   break;
226
227       case EOpPostIncrement:  out << "Post-Increment";       break;
228       case EOpPostDecrement:  out << "Post-Decrement";       break;
229       case EOpPreIncrement:   out << "Pre-Increment";        break;
230       case EOpPreDecrement:   out << "Pre-Decrement";        break;
231
232       case EOpRadians:        out << "radians";              break;
233       case EOpDegrees:        out << "degrees";              break;
234       case EOpSin:            out << "sine";                 break;
235       case EOpCos:            out << "cosine";               break;
236       case EOpTan:            out << "tangent";              break;
237       case EOpAsin:           out << "arc sine";             break;
238       case EOpAcos:           out << "arc cosine";           break;
239       case EOpAtan:           out << "arc tangent";          break;
240
241       case EOpExp:            out << "exp";                  break;
242       case EOpLog:            out << "log";                  break;
243       case EOpExp2:           out << "exp2";                 break;
244       case EOpLog2:           out << "log2";                 break;
245       case EOpSqrt:           out << "sqrt";                 break;
246       case EOpInverseSqrt:    out << "inverse sqrt";         break;
247
248       case EOpAbs:            out << "Absolute value";       break;
249       case EOpSign:           out << "Sign";                 break;
250       case EOpFloor:          out << "Floor";                break;
251       case EOpCeil:           out << "Ceiling";              break;
252       case EOpFract:          out << "Fraction";             break;
253
254       case EOpLength:         out << "length";               break;
255       case EOpNormalize:      out << "normalize";            break;
256       // case EOpDPdx:           out << "dPdx";                 break;
257       // case EOpDPdy:           out << "dPdy";                 break;
258       // case EOpFwidth:         out << "fwidth";               break;
259
260       case EOpAny:            out << "any";                  break;
261       case EOpAll:            out << "all";                  break;
262
263       default:
264         out.prefix(EPrefixError);
265         out << "Bad unary op";
266     }
267
268     out << " (" << node->getCompleteString() << ")";
269
270     out << "\n";
271
272     return true;
273 }
274
275 bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
276 {
277     TInfoSinkBase &out = sink;
278
279     if (node->getOp() == EOpNull)
280     {
281         out.prefix(EPrefixError);
282         out << "node is still EOpNull!";
283         return true;
284     }
285
286     OutputTreeText(out, node, mDepth);
287
288     switch (node->getOp())
289     {
290       case EOpSequence:      out << "Sequence\n"; return true;
291       case EOpComma:         out << "Comma\n"; return true;
292       case EOpFunction:      out << "Function Definition: " << node->getName(); break;
293       case EOpFunctionCall:  out << "Function Call: " << node->getName(); break;
294       case EOpParameters:    out << "Function Parameters: ";              break;
295
296       case EOpConstructFloat: out << "Construct float"; break;
297       case EOpConstructVec2:  out << "Construct vec2";  break;
298       case EOpConstructVec3:  out << "Construct vec3";  break;
299       case EOpConstructVec4:  out << "Construct vec4";  break;
300       case EOpConstructBool:  out << "Construct bool";  break;
301       case EOpConstructBVec2: out << "Construct bvec2"; break;
302       case EOpConstructBVec3: out << "Construct bvec3"; break;
303       case EOpConstructBVec4: out << "Construct bvec4"; break;
304       case EOpConstructInt:   out << "Construct int";   break;
305       case EOpConstructIVec2: out << "Construct ivec2"; break;
306       case EOpConstructIVec3: out << "Construct ivec3"; break;
307       case EOpConstructIVec4: out << "Construct ivec4"; break;
308       case EOpConstructUInt:  out << "Construct uint";  break;
309       case EOpConstructUVec2: out << "Construct uvec2"; break;
310       case EOpConstructUVec3: out << "Construct uvec3"; break;
311       case EOpConstructUVec4: out << "Construct uvec4"; break;
312       case EOpConstructMat2:  out << "Construct mat2";  break;
313       case EOpConstructMat3:  out << "Construct mat3";  break;
314       case EOpConstructMat4:  out << "Construct mat4";  break;
315       case EOpConstructStruct:  out << "Construct structure";  break;
316
317       case EOpLessThan:         out << "Compare Less Than";             break;
318       case EOpGreaterThan:      out << "Compare Greater Than";          break;
319       case EOpLessThanEqual:    out << "Compare Less Than or Equal";    break;
320       case EOpGreaterThanEqual: out << "Compare Greater Than or Equal"; break;
321       case EOpVectorEqual:      out << "Equal";                         break;
322       case EOpVectorNotEqual:   out << "NotEqual";                      break;
323
324       case EOpMod:           out << "mod";         break;
325       case EOpPow:           out << "pow";         break;
326
327       case EOpAtan:          out << "arc tangent"; break;
328
329       case EOpMin:           out << "min";         break;
330       case EOpMax:           out << "max";         break;
331       case EOpClamp:         out << "clamp";       break;
332       case EOpMix:           out << "mix";         break;
333       case EOpStep:          out << "step";        break;
334       case EOpSmoothStep:    out << "smoothstep";  break;
335
336       case EOpDistance:      out << "distance";                break;
337       case EOpDot:           out << "dot-product";             break;
338       case EOpCross:         out << "cross-product";           break;
339       case EOpFaceForward:   out << "face-forward";            break;
340       case EOpReflect:       out << "reflect";                 break;
341       case EOpRefract:       out << "refract";                 break;
342       case EOpMul:           out << "component-wise multiply"; break;
343
344       case EOpDeclaration:   out << "Declaration: ";   break;
345       case EOpInvariantDeclaration: out << "Invariant Declaration: "; break;
346
347       default:
348         out.prefix(EPrefixError);
349         out << "Bad aggregation op";
350     }
351
352     if (node->getOp() != EOpSequence && node->getOp() != EOpParameters)
353         out << " (" << node->getCompleteString() << ")";
354
355     out << "\n";
356
357     return true;
358 }
359
360 bool TOutputTraverser::visitSelection(Visit visit, TIntermSelection *node)
361 {
362     TInfoSinkBase &out = sink;
363
364     OutputTreeText(out, node, mDepth);
365
366     out << "Test condition and select";
367     out << " (" << node->getCompleteString() << ")\n";
368
369     ++mDepth;
370
371     OutputTreeText(sink, node, mDepth);
372     out << "Condition\n";
373     node->getCondition()->traverse(this);
374
375     OutputTreeText(sink, node, mDepth);
376     if (node->getTrueBlock())
377     {
378         out << "true case\n";
379         node->getTrueBlock()->traverse(this);
380     }
381     else
382     {
383         out << "true case is null\n";
384     }
385
386     if (node->getFalseBlock())
387     {
388         OutputTreeText(sink, node, mDepth);
389         out << "false case\n";
390         node->getFalseBlock()->traverse(this);
391     }
392
393     --mDepth;
394
395     return false;
396 }
397
398 void TOutputTraverser::visitConstantUnion(TIntermConstantUnion *node)
399 {
400     TInfoSinkBase &out = sink;
401
402     size_t size = node->getType().getObjectSize();
403
404     for (size_t i = 0; i < size; i++)
405     {
406         OutputTreeText(out, node, mDepth);
407         switch (node->getUnionArrayPointer()[i].getType())
408         {
409           case EbtBool:
410             if (node->getUnionArrayPointer()[i].getBConst())
411                 out << "true";
412             else
413                 out << "false";
414
415             out << " (" << "const bool" << ")";
416             out << "\n";
417             break;
418           case EbtFloat:
419             out << node->getUnionArrayPointer()[i].getFConst();
420             out << " (const float)\n";
421             break;
422           case EbtInt:
423             out << node->getUnionArrayPointer()[i].getIConst();
424             out << " (const int)\n";
425             break;
426           case EbtUInt:
427             out << node->getUnionArrayPointer()[i].getUConst();
428             out << " (const uint)\n";
429             break;
430           default:
431             out.message(EPrefixInternalError, node->getLine(), "Unknown constant");
432             break;
433         }
434     }
435 }
436
437 bool TOutputTraverser::visitLoop(Visit visit, TIntermLoop *node)
438 {
439     TInfoSinkBase &out = sink;
440
441     OutputTreeText(out, node, mDepth);
442
443     out << "Loop with condition ";
444     if (node->getType() == ELoopDoWhile)
445         out << "not ";
446     out << "tested first\n";
447
448     ++mDepth;
449
450     OutputTreeText(sink, node, mDepth);
451     if (node->getCondition())
452     {
453         out << "Loop Condition\n";
454         node->getCondition()->traverse(this);
455     }
456     else
457     {
458         out << "No loop condition\n";
459     }
460
461     OutputTreeText(sink, node, mDepth);
462     if (node->getBody())
463     {
464         out << "Loop Body\n";
465         node->getBody()->traverse(this);
466     }
467     else
468     {
469         out << "No loop body\n";
470     }
471
472     if (node->getExpression())
473     {
474         OutputTreeText(sink, node, mDepth);
475         out << "Loop Terminal Expression\n";
476         node->getExpression()->traverse(this);
477     }
478
479     --mDepth;
480
481     return false;
482 }
483
484 bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch *node)
485 {
486     TInfoSinkBase &out = sink;
487
488     OutputTreeText(out, node, mDepth);
489
490     switch (node->getFlowOp())
491     {
492       case EOpKill:      out << "Branch: Kill";           break;
493       case EOpBreak:     out << "Branch: Break";          break;
494       case EOpContinue:  out << "Branch: Continue";       break;
495       case EOpReturn:    out << "Branch: Return";         break;
496       default:           out << "Branch: Unknown Branch"; break;
497     }
498
499     if (node->getExpression())
500     {
501         out << " with expression\n";
502         ++mDepth;
503         node->getExpression()->traverse(this);
504         --mDepth;
505     }
506     else
507     {
508         out << "\n";
509     }
510
511     return false;
512 }
513
514 //
515 // This function is the one to call externally to start the traversal.
516 // Individual functions can be initialized to 0 to skip processing of that
517 // type of node.  It's children will still be processed.
518 //
519 void TIntermediate::outputTree(TIntermNode *root)
520 {
521     if (root == NULL)
522         return;
523
524     TOutputTraverser it(mInfoSink.info);
525
526     root->traverse(&it);
527 }