updated some printfs, added comment about sched_yield
[mesa.git] / src / mesa / shader / slang / MachineIndependent / intermOut.cpp
1 //
2 //Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
3 //All rights reserved.
4 //
5 //Redistribution and use in source and binary forms, with or without
6 //modification, are permitted provided that the following conditions
7 //are met:
8 //
9 // Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //
12 // Redistributions in binary form must reproduce the above
13 // copyright notice, this list of conditions and the following
14 // disclaimer in the documentation and/or other materials provided
15 // with the distribution.
16 //
17 // Neither the name of 3Dlabs Inc. Ltd. nor the names of its
18 // contributors may be used to endorse or promote products derived
19 // from this software without specific prior written permission.
20 //
21 //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 //"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 //LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 //FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 //COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 //INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 //BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 //LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 //CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 //LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 //ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 //POSSIBILITY OF SUCH DAMAGE.
33 //
34
35 #include "localintermediate.h"
36 #include "../Include/ShHandle.h"
37
38 //
39 // Two purposes:
40 // 1. Show an example of how to iterate tree. Functions can
41 // also directly call Traverse() on children themselves to
42 // have finer grained control over the process than shown here.
43 // See the last function for how to get started.
44 // 2. Print out a text based description of the tree.
45 //
46
47 //
48 // Use this class to carry along data from node to node in
49 // the traversal
50 //
51 class TOutputTraverser : public TIntermTraverser {
52 public:
53 TOutputTraverser(TInfoSink& i) : infoSink(i) { }
54 TInfoSink& infoSink;
55 };
56
57 TString TType::getCompleteString() const
58 {
59 char buf[100];
60 char *p = &buf[0];
61
62 if (qualifier != EvqTemporary && qualifier != EvqGlobal)
63 p += sprintf(p, "%s ", getQualifierString());
64 if (array)
65 p += sprintf(p, "array of ");
66 if (matrix)
67 p += sprintf(p, "%dX%d matrix of ", size, size);
68 else if (size > 1)
69 p += sprintf(p, "%d-component vector of ", size);
70
71 sprintf(p, "%s", getBasicString());
72
73 return TString(buf);
74 }
75
76 //
77 // Helper functions for printing, not part of traversing.
78 //
79
80 void OutputTreeText(TInfoSink& infoSink, TIntermNode* node, const int depth)
81 {
82 int i;
83
84 infoSink.debug << FormatSourceLoc(node->getLine());
85
86 for (i = 0; i < depth; ++i)
87 infoSink.debug << " ";
88 }
89
90 //
91 // The rest of the file are the traversal functions. The last one
92 // is the one that starts the traversal.
93 //
94 // Return true from interior nodes to have the external traversal
95 // continue on to children. If you process children yourself,
96 // return false.
97 //
98
99 void OutputSymbol(TIntermSymbol* node, TIntermTraverser* it)
100 {
101 TOutputTraverser* oit = static_cast<TOutputTraverser*>(it);
102
103 OutputTreeText(oit->infoSink, node, oit->depth);
104
105 char buf[100];
106 sprintf(buf, "'%s' (%s)\n",
107 node->getSymbol().c_str(),
108 node->getCompleteString().c_str());
109
110 oit->infoSink.debug << buf;
111 }
112
113 bool OutputBinary(bool /* preVisit */, TIntermBinary* node, TIntermTraverser* it)
114 {
115 TOutputTraverser* oit = static_cast<TOutputTraverser*>(it);
116 TInfoSink& out = oit->infoSink;
117
118 OutputTreeText(out, node, oit->depth);
119
120 switch (node->getOp()) {
121 case EOpAssign: out.debug << "move second child to first child"; break;
122 case EOpAddAssign: out.debug << "add second child into first child"; break;
123 case EOpSubAssign: out.debug << "subtract second child into first child"; break;
124 case EOpMulAssign: out.debug << "multiply second child into first child"; break;
125 case EOpVectorTimesMatrixAssign: out.debug << "matrix mult second child into first child"; break;
126 case EOpVectorTimesScalarAssign: out.debug << "vector scale second child into first child"; break;
127 case EOpMatrixTimesScalarAssign: out.debug << "matrix scale second child into first child"; break;
128 case EOpMatrixTimesMatrixAssign: out.debug << "matrix mult second child into first child"; break;
129 case EOpDivAssign: out.debug << "divide second child into first child"; break;
130 case EOpModAssign: out.debug << "mod second child into first child"; break;
131 case EOpAndAssign: out.debug << "and second child into first child"; break;
132 case EOpInclusiveOrAssign: out.debug << "or second child into first child"; break;
133 case EOpExclusiveOrAssign: out.debug << "exclusive or second child into first child"; break;
134 case EOpLeftShiftAssign: out.debug << "left shift second child into first child"; break;
135 case EOpRightShiftAssign: out.debug << "right shift second child into first child"; break;
136
137 case EOpIndexDirect: out.debug << "direct index"; break;
138 case EOpIndexIndirect: out.debug << "indirect index"; break;
139 case EOpIndexDirectStruct: out.debug << "direct index for structure"; break;
140 case EOpVectorSwizzle: out.debug << "vector swizzle"; break;
141
142 case EOpAdd: out.debug << "add"; break;
143 case EOpSub: out.debug << "subtract"; break;
144 case EOpMul: out.debug << "component-wise multiply"; break;
145 case EOpDiv: out.debug << "divide"; break;
146 case EOpMod: out.debug << "mod"; break;
147 case EOpRightShift: out.debug << "right-shift"; break;
148 case EOpLeftShift: out.debug << "left-shift"; break;
149 case EOpAnd: out.debug << "bitwise and"; break;
150 case EOpInclusiveOr: out.debug << "inclusive-or"; break;
151 case EOpExclusiveOr: out.debug << "exclusive-or"; break;
152 case EOpEqual: out.debug << "Compare Equal"; break;
153 case EOpNotEqual: out.debug << "Compare Not Equal"; break;
154 case EOpLessThan: out.debug << "Compare Less Than"; break;
155 case EOpGreaterThan: out.debug << "Compare Greater Than"; break;
156 case EOpLessThanEqual: out.debug << "Compare Less Than or Equal"; break;
157 case EOpGreaterThanEqual: out.debug << "Compare Greater Than or Equal"; break;
158
159 case EOpVectorTimesScalar: out.debug << "vector-scale"; break;
160 case EOpVectorTimesMatrix: out.debug << "vector-times-matrix"; break;
161 case EOpMatrixTimesVector: out.debug << "matrix-times-vector"; break;
162 case EOpMatrixTimesScalar: out.debug << "matrix-scale"; break;
163 case EOpMatrixTimesMatrix: out.debug << "matrix-multiply"; break;
164
165 case EOpLogicalOr: out.debug << "logical-or"; break;
166 case EOpLogicalXor: out.debug << "logical-xor"; break;
167 case EOpLogicalAnd: out.debug << "logical-and"; break;
168 default: out.debug << "<unknown op>";
169 }
170
171 out.debug << " (" << node->getCompleteString() << ")";
172
173 out.debug << "\n";
174
175 return true;
176 }
177
178 bool OutputUnary(bool /* preVisit */, TIntermUnary* node, TIntermTraverser* it)
179 {
180 TOutputTraverser* oit = static_cast<TOutputTraverser*>(it);
181 TInfoSink& out = oit->infoSink;
182
183 OutputTreeText(out, node, oit->depth);
184
185 switch (node->getOp()) {
186 case EOpNegative: out.debug << "Negate value"; break;
187 case EOpVectorLogicalNot:
188 case EOpLogicalNot: out.debug << "Negate conditional"; break;
189 case EOpBitwiseNot: out.debug << "Bitwise not"; break;
190
191 case EOpPostIncrement: out.debug << "Post-Increment"; break;
192 case EOpPostDecrement: out.debug << "Post-Decrement"; break;
193 case EOpPreIncrement: out.debug << "Pre-Increment"; break;
194 case EOpPreDecrement: out.debug << "Pre-Decrement"; break;
195
196 case EOpConvIntToBool: out.debug << "Convert int to bool"; break;
197 case EOpConvFloatToBool:out.debug << "Convert float to bool";break;
198 case EOpConvBoolToFloat:out.debug << "Convert bool to float";break;
199 case EOpConvIntToFloat: out.debug << "Convert int to float"; break;
200 case EOpConvFloatToInt: out.debug << "Convert float to int"; break;
201 case EOpConvBoolToInt: out.debug << "Convert bool to int"; break;
202
203 case EOpRadians: out.debug << "radians"; break;
204 case EOpDegrees: out.debug << "degrees"; break;
205 case EOpSin: out.debug << "sine"; break;
206 case EOpCos: out.debug << "cosine"; break;
207 case EOpTan: out.debug << "tangent"; break;
208 case EOpAsin: out.debug << "arc sine"; break;
209 case EOpAcos: out.debug << "arc cosine"; break;
210 case EOpAtan: out.debug << "arc tangent"; break;
211
212 case EOpExp: out.debug << "exp"; break;
213 case EOpLog: out.debug << "log"; break;
214 case EOpExp2: out.debug << "exp2"; break;
215 case EOpLog2: out.debug << "log2"; break;
216 case EOpSqrt: out.debug << "sqrt"; break;
217 case EOpInverseSqrt: out.debug << "inverse sqrt"; break;
218
219 case EOpAbs: out.debug << "Absolute value"; break;
220 case EOpSign: out.debug << "Sign"; break;
221 case EOpFloor: out.debug << "Floor"; break;
222 case EOpCeil: out.debug << "Ceiling"; break;
223 case EOpFract: out.debug << "Fraction"; break;
224
225 case EOpLength: out.debug << "length"; break;
226 case EOpNormalize: out.debug << "normalize"; break;
227 case EOpDPdx: out.debug << "dPdx"; break;
228 case EOpDPdy: out.debug << "dPdy"; break;
229 case EOpFwidth: out.debug << "fwidth"; break;
230
231 case EOpAny: out.debug << "any"; break;
232 case EOpAll: out.debug << "all"; break;
233
234 default: out.debug.message(EPrefixError, "Bad unary op");
235 }
236
237 out.debug << " (" << node->getCompleteString() << ")";
238
239 out.debug << "\n";
240
241 return true;
242 }
243
244 bool OutputAggregate(bool /* preVisit */, TIntermAggregate* node, TIntermTraverser* it)
245 {
246 TOutputTraverser* oit = static_cast<TOutputTraverser*>(it);
247 TInfoSink& out = oit->infoSink;
248
249 if (node->getOp() == EOpNull) {
250 out.debug.message(EPrefixError, "node is still EOpNull!");
251 return true;
252 }
253
254 OutputTreeText(out, node, oit->depth);
255
256 switch (node->getOp()) {
257 case EOpSequence: out.debug << "Sequence\n"; return true;
258 case EOpComma: out.debug << "Comma\n"; return true;
259 case EOpFunction: out.debug << "Function Definition: " << node->getName(); break;
260 case EOpFunctionCall: out.debug << "Function Call: " << node->getName(); break;
261 case EOpParameters: out.debug << "Function Parameters: "; break;
262
263 case EOpConstructFloat: out.debug << "Construct float"; break;
264 case EOpConstructVec2: out.debug << "Construct vec2"; break;
265 case EOpConstructVec3: out.debug << "Construct vec3"; break;
266 case EOpConstructVec4: out.debug << "Construct vec4"; break;
267 case EOpConstructBool: out.debug << "Construct bool"; break;
268 case EOpConstructBVec2: out.debug << "Construct bvec2"; break;
269 case EOpConstructBVec3: out.debug << "Construct bvec3"; break;
270 case EOpConstructBVec4: out.debug << "Construct bvec4"; break;
271 case EOpConstructInt: out.debug << "Construct int"; break;
272 case EOpConstructIVec2: out.debug << "Construct ivec2"; break;
273 case EOpConstructIVec3: out.debug << "Construct ivec3"; break;
274 case EOpConstructIVec4: out.debug << "Construct ivec4"; break;
275 case EOpConstructMat2: out.debug << "Construct mat2"; break;
276 case EOpConstructMat3: out.debug << "Construct mat3"; break;
277 case EOpConstructMat4: out.debug << "Construct mat4"; break;
278 case EOpConstructStruct: out.debug << "Construct structure"; break;
279
280 case EOpLessThan: out.debug << "Compare Less Than"; break;
281 case EOpGreaterThan: out.debug << "Compare Greater Than"; break;
282 case EOpLessThanEqual: out.debug << "Compare Less Than or Equal"; break;
283 case EOpGreaterThanEqual: out.debug << "Compare Greater Than or Equal"; break;
284 case EOpVectorEqual: out.debug << "Equal"; break;
285 case EOpVectorNotEqual: out.debug << "NotEqual"; break;
286
287 case EOpMod: out.debug << "mod"; break;
288 case EOpPow: out.debug << "pow"; break;
289
290 case EOpAtan: out.debug << "arc tangent"; break;
291
292 case EOpMin: out.debug << "min"; break;
293 case EOpMax: out.debug << "max"; break;
294 case EOpClamp: out.debug << "clamp"; break;
295 case EOpMix: out.debug << "mix"; break;
296 case EOpStep: out.debug << "step"; break;
297 case EOpSmoothStep: out.debug << "smoothstep"; break;
298
299 case EOpDistance: out.debug << "distance"; break;
300 case EOpDot: out.debug << "dot-product"; break;
301 case EOpCross: out.debug << "cross-product"; break;
302 case EOpFaceForward: out.debug << "face-forward"; break;
303 case EOpReflect: out.debug << "reflect"; break;
304 case EOpRefract: out.debug << "refract"; break;
305 case EOpMul: out.debug << "component-wise multiply"; break;
306
307 case EOpItof: out.debug << "itof"; break;
308 case EOpFtoi: out.debug << "ftoi"; break;
309 case EOpSkipPixels: out.debug << "skipPixels"; break;
310 case EOpReadInput: out.debug << "readInput"; break;
311 case EOpWritePixel: out.debug << "writePixel"; break;
312 case EOpBitmapLsb: out.debug << "bitmapLSB"; break;
313 case EOpBitmapMsb: out.debug << "bitmapMSB"; break;
314 case EOpWriteOutput: out.debug << "writeOutput"; break;
315 case EOpReadPixel: out.debug << "readPixel"; break;
316
317 default: out.debug.message(EPrefixError, "Bad aggregation op");
318 }
319
320 if (node->getOp() != EOpSequence && node->getOp() != EOpParameters)
321 out.debug << " (" << node->getCompleteString() << ")";
322
323 out.debug << "\n";
324
325 return true;
326 }
327
328 bool OutputSelection(bool /* preVisit */, TIntermSelection* node, TIntermTraverser* it)
329 {
330 TOutputTraverser* oit = static_cast<TOutputTraverser*>(it);
331 TInfoSink& out = oit->infoSink;
332
333 OutputTreeText(out, node, oit->depth);
334
335 out.debug << "Test condition and select";
336 out.debug << " (" << node->getCompleteString() << ")\n";
337
338 ++oit->depth;
339
340 OutputTreeText(oit->infoSink, node, oit->depth);
341 out.debug << "Condition\n";
342 node->getCondition()->traverse(it);
343
344 OutputTreeText(oit->infoSink, node, oit->depth);
345 if (node->getTrueBlock()) {
346 out.debug << "true case\n";
347 node->getTrueBlock()->traverse(it);
348 } else
349 out.debug << "true case is null\n";
350
351 if (node->getFalseBlock()) {
352 OutputTreeText(oit->infoSink, node, oit->depth);
353 out.debug << "false case\n";
354 node->getFalseBlock()->traverse(it);
355 }
356
357 --oit->depth;
358
359 return false;
360 }
361
362 void OutputConstantUnion(TIntermConstantUnion* node, TIntermTraverser* it)
363 {
364 TOutputTraverser* oit = static_cast<TOutputTraverser*>(it);
365 TInfoSink& out = oit->infoSink;
366
367 int size = 0;
368 if (node->getType().getBasicType() == EbtStruct)
369 size = node->getType().getStructSize();
370 else
371 size = node->getType().getInstanceSize();
372
373 for (int i = 0; i < size; i++) {
374 OutputTreeText(out, node, oit->depth);
375 switch (node->getType().getBasicType()) {
376 case EbtBool:
377 if (node->getUnionArrayPointer()[i].bConst)
378 out.debug << "true";
379 else
380 out.debug << "false";
381
382 out.debug << " (" << "const bool" << ")";
383
384 out.debug << "\n";
385 break;
386 case EbtFloat:
387 {
388 char buf[300];
389 sprintf(buf, "%f (%s)", node->getUnionArrayPointer()[i].fConst, "const float");
390
391 out.debug << buf << "\n";
392 }
393 break;
394 case EbtInt:
395 {
396 char buf[300];
397 sprintf(buf, "%d (%s)", node->getUnionArrayPointer()[i].iConst, "const int");
398
399 out.debug << buf << "\n";
400 break;
401 }
402 default:
403 out.info.message(EPrefixInternalError, "Unknown constant", node->getLine());
404 break;
405 }
406 }
407 }
408
409 bool OutputLoop(bool /* preVisit */, TIntermLoop* node, TIntermTraverser* it)
410 {
411 TOutputTraverser* oit = static_cast<TOutputTraverser*>(it);
412 TInfoSink& out = oit->infoSink;
413
414 OutputTreeText(out, node, oit->depth);
415
416 out.debug << "Loop with condition ";
417 if (! node->testFirst())
418 out.debug << "not ";
419 out.debug << "tested first\n";
420
421 ++oit->depth;
422
423 OutputTreeText(oit->infoSink, node, oit->depth);
424 if (node->getTest()) {
425 out.debug << "Loop Condition\n";
426 node->getTest()->traverse(it);
427 } else
428 out.debug << "No loop condition\n";
429
430 OutputTreeText(oit->infoSink, node, oit->depth);
431 if (node->getBody()) {
432 out.debug << "Loop Body\n";
433 node->getBody()->traverse(it);
434 } else
435 out.debug << "No loop body\n";
436
437 if (node->getTerminal()) {
438 OutputTreeText(oit->infoSink, node, oit->depth);
439 out.debug << "Loop Terminal Expression\n";
440 node->getTerminal()->traverse(it);
441 }
442
443 --oit->depth;
444
445 return false;
446 }
447
448 bool OutputBranch(bool /* previsit*/, TIntermBranch* node, TIntermTraverser* it)
449 {
450 TOutputTraverser* oit = static_cast<TOutputTraverser*>(it);
451 TInfoSink& out = oit->infoSink;
452
453 OutputTreeText(out, node, oit->depth);
454
455 switch (node->getFlowOp()) {
456 case EOpKill: out.debug << "Branch: Kill"; break;
457 case EOpBreak: out.debug << "Branch: Break"; break;
458 case EOpContinue: out.debug << "Branch: Continue"; break;
459 case EOpReturn: out.debug << "Branch: Return"; break;
460 default: out.debug << "Branch: Unknown Branch"; break;
461 }
462
463 if (node->getExpression()) {
464 out.debug << " with expression\n";
465 ++oit->depth;
466 node->getExpression()->traverse(it);
467 --oit->depth;
468 } else
469 out.debug << "\n";
470
471 return false;
472 }
473
474 //
475 // This function is the one to call externally to start the traversal.
476 // Individual functions can be initialized to 0 to skip processing of that
477 // type of node. It's children will still be processed.
478 //
479 void TIntermediate::outputTree(TIntermNode* root)
480 {
481 if (root == 0)
482 return;
483
484 TOutputTraverser it(infoSink);
485
486 it.visitAggregate = OutputAggregate;
487 it.visitBinary = OutputBinary;
488 it.visitConstantUnion = OutputConstantUnion;
489 it.visitSelection = OutputSelection;
490 it.visitSymbol = OutputSymbol;
491 it.visitUnary = OutputUnary;
492 it.visitLoop = OutputLoop;
493 it.visitBranch = OutputBranch;
494
495 root->traverse(&it);
496 }