OSDN Git Service

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