1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/angle/src/compiler/intermOut.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,424 @@ 1.4 +// 1.5 +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. 1.6 +// Use of this source code is governed by a BSD-style license that can be 1.7 +// found in the LICENSE file. 1.8 +// 1.9 + 1.10 +#include "compiler/localintermediate.h" 1.11 + 1.12 +// 1.13 +// Two purposes: 1.14 +// 1. Show an example of how to iterate tree. Functions can 1.15 +// also directly call Traverse() on children themselves to 1.16 +// have finer grained control over the process than shown here. 1.17 +// See the last function for how to get started. 1.18 +// 2. Print out a text based description of the tree. 1.19 +// 1.20 + 1.21 +// 1.22 +// Use this class to carry along data from node to node in 1.23 +// the traversal 1.24 +// 1.25 +class TOutputTraverser : public TIntermTraverser { 1.26 +public: 1.27 + TOutputTraverser(TInfoSinkBase& i) : sink(i) { } 1.28 + TInfoSinkBase& sink; 1.29 + 1.30 +protected: 1.31 + void visitSymbol(TIntermSymbol*); 1.32 + void visitConstantUnion(TIntermConstantUnion*); 1.33 + bool visitBinary(Visit visit, TIntermBinary*); 1.34 + bool visitUnary(Visit visit, TIntermUnary*); 1.35 + bool visitSelection(Visit visit, TIntermSelection*); 1.36 + bool visitAggregate(Visit visit, TIntermAggregate*); 1.37 + bool visitLoop(Visit visit, TIntermLoop*); 1.38 + bool visitBranch(Visit visit, TIntermBranch*); 1.39 +}; 1.40 + 1.41 +TString TType::getCompleteString() const 1.42 +{ 1.43 + TStringStream stream; 1.44 + 1.45 + if (qualifier != EvqTemporary && qualifier != EvqGlobal) 1.46 + stream << getQualifierString() << " " << getPrecisionString() << " "; 1.47 + if (array) 1.48 + stream << "array[" << getArraySize() << "] of "; 1.49 + if (matrix) 1.50 + stream << size << "X" << size << " matrix of "; 1.51 + else if (size > 1) 1.52 + stream << size << "-component vector of "; 1.53 + 1.54 + stream << getBasicString(); 1.55 + return stream.str(); 1.56 +} 1.57 + 1.58 +// 1.59 +// Helper functions for printing, not part of traversing. 1.60 +// 1.61 + 1.62 +void OutputTreeText(TInfoSinkBase& sink, TIntermNode* node, const int depth) 1.63 +{ 1.64 + int i; 1.65 + 1.66 + sink.location(node->getLine()); 1.67 + 1.68 + for (i = 0; i < depth; ++i) 1.69 + sink << " "; 1.70 +} 1.71 + 1.72 +// 1.73 +// The rest of the file are the traversal functions. The last one 1.74 +// is the one that starts the traversal. 1.75 +// 1.76 +// Return true from interior nodes to have the external traversal 1.77 +// continue on to children. If you process children yourself, 1.78 +// return false. 1.79 +// 1.80 + 1.81 +void TOutputTraverser::visitSymbol(TIntermSymbol* node) 1.82 +{ 1.83 + OutputTreeText(sink, node, depth); 1.84 + 1.85 + sink << "'" << node->getSymbol() << "' "; 1.86 + sink << "(" << node->getCompleteString() << ")\n"; 1.87 +} 1.88 + 1.89 +bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary* node) 1.90 +{ 1.91 + TInfoSinkBase& out = sink; 1.92 + 1.93 + OutputTreeText(out, node, depth); 1.94 + 1.95 + switch (node->getOp()) { 1.96 + case EOpAssign: out << "move second child to first child"; break; 1.97 + case EOpInitialize: out << "initialize first child with second child"; break; 1.98 + case EOpAddAssign: out << "add second child into first child"; break; 1.99 + case EOpSubAssign: out << "subtract second child into first child"; break; 1.100 + case EOpMulAssign: out << "multiply second child into first child"; break; 1.101 + case EOpVectorTimesMatrixAssign: out << "matrix mult second child into first child"; break; 1.102 + case EOpVectorTimesScalarAssign: out << "vector scale second child into first child"; break; 1.103 + case EOpMatrixTimesScalarAssign: out << "matrix scale second child into first child"; break; 1.104 + case EOpMatrixTimesMatrixAssign: out << "matrix mult second child into first child"; break; 1.105 + case EOpDivAssign: out << "divide second child into first child"; break; 1.106 + case EOpIndexDirect: out << "direct index"; break; 1.107 + case EOpIndexIndirect: out << "indirect index"; break; 1.108 + case EOpIndexDirectStruct: out << "direct index for structure"; break; 1.109 + case EOpVectorSwizzle: out << "vector swizzle"; break; 1.110 + 1.111 + case EOpAdd: out << "add"; break; 1.112 + case EOpSub: out << "subtract"; break; 1.113 + case EOpMul: out << "component-wise multiply"; break; 1.114 + case EOpDiv: out << "divide"; break; 1.115 + case EOpEqual: out << "Compare Equal"; break; 1.116 + case EOpNotEqual: out << "Compare Not Equal"; break; 1.117 + case EOpLessThan: out << "Compare Less Than"; break; 1.118 + case EOpGreaterThan: out << "Compare Greater Than"; break; 1.119 + case EOpLessThanEqual: out << "Compare Less Than or Equal"; break; 1.120 + case EOpGreaterThanEqual: out << "Compare Greater Than or Equal"; break; 1.121 + 1.122 + case EOpVectorTimesScalar: out << "vector-scale"; break; 1.123 + case EOpVectorTimesMatrix: out << "vector-times-matrix"; break; 1.124 + case EOpMatrixTimesVector: out << "matrix-times-vector"; break; 1.125 + case EOpMatrixTimesScalar: out << "matrix-scale"; break; 1.126 + case EOpMatrixTimesMatrix: out << "matrix-multiply"; break; 1.127 + 1.128 + case EOpLogicalOr: out << "logical-or"; break; 1.129 + case EOpLogicalXor: out << "logical-xor"; break; 1.130 + case EOpLogicalAnd: out << "logical-and"; break; 1.131 + default: out << "<unknown op>"; 1.132 + } 1.133 + 1.134 + out << " (" << node->getCompleteString() << ")"; 1.135 + 1.136 + out << "\n"; 1.137 + 1.138 + return true; 1.139 +} 1.140 + 1.141 +bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary* node) 1.142 +{ 1.143 + TInfoSinkBase& out = sink; 1.144 + 1.145 + OutputTreeText(out, node, depth); 1.146 + 1.147 + switch (node->getOp()) { 1.148 + case EOpNegative: out << "Negate value"; break; 1.149 + case EOpVectorLogicalNot: 1.150 + case EOpLogicalNot: out << "Negate conditional"; break; 1.151 + 1.152 + case EOpPostIncrement: out << "Post-Increment"; break; 1.153 + case EOpPostDecrement: out << "Post-Decrement"; break; 1.154 + case EOpPreIncrement: out << "Pre-Increment"; break; 1.155 + case EOpPreDecrement: out << "Pre-Decrement"; break; 1.156 + 1.157 + case EOpConvIntToBool: out << "Convert int to bool"; break; 1.158 + case EOpConvFloatToBool:out << "Convert float to bool";break; 1.159 + case EOpConvBoolToFloat:out << "Convert bool to float";break; 1.160 + case EOpConvIntToFloat: out << "Convert int to float"; break; 1.161 + case EOpConvFloatToInt: out << "Convert float to int"; break; 1.162 + case EOpConvBoolToInt: out << "Convert bool to int"; break; 1.163 + 1.164 + case EOpRadians: out << "radians"; break; 1.165 + case EOpDegrees: out << "degrees"; break; 1.166 + case EOpSin: out << "sine"; break; 1.167 + case EOpCos: out << "cosine"; break; 1.168 + case EOpTan: out << "tangent"; break; 1.169 + case EOpAsin: out << "arc sine"; break; 1.170 + case EOpAcos: out << "arc cosine"; break; 1.171 + case EOpAtan: out << "arc tangent"; break; 1.172 + 1.173 + case EOpExp: out << "exp"; break; 1.174 + case EOpLog: out << "log"; break; 1.175 + case EOpExp2: out << "exp2"; break; 1.176 + case EOpLog2: out << "log2"; break; 1.177 + case EOpSqrt: out << "sqrt"; break; 1.178 + case EOpInverseSqrt: out << "inverse sqrt"; break; 1.179 + 1.180 + case EOpAbs: out << "Absolute value"; break; 1.181 + case EOpSign: out << "Sign"; break; 1.182 + case EOpFloor: out << "Floor"; break; 1.183 + case EOpCeil: out << "Ceiling"; break; 1.184 + case EOpFract: out << "Fraction"; break; 1.185 + 1.186 + case EOpLength: out << "length"; break; 1.187 + case EOpNormalize: out << "normalize"; break; 1.188 + // case EOpDPdx: out << "dPdx"; break; 1.189 + // case EOpDPdy: out << "dPdy"; break; 1.190 + // case EOpFwidth: out << "fwidth"; break; 1.191 + 1.192 + case EOpAny: out << "any"; break; 1.193 + case EOpAll: out << "all"; break; 1.194 + 1.195 + default: 1.196 + out.prefix(EPrefixError); 1.197 + out << "Bad unary op"; 1.198 + } 1.199 + 1.200 + out << " (" << node->getCompleteString() << ")"; 1.201 + 1.202 + out << "\n"; 1.203 + 1.204 + return true; 1.205 +} 1.206 + 1.207 +bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate* node) 1.208 +{ 1.209 + TInfoSinkBase& out = sink; 1.210 + 1.211 + if (node->getOp() == EOpNull) { 1.212 + out.prefix(EPrefixError); 1.213 + out << "node is still EOpNull!"; 1.214 + return true; 1.215 + } 1.216 + 1.217 + OutputTreeText(out, node, depth); 1.218 + 1.219 + switch (node->getOp()) { 1.220 + case EOpSequence: out << "Sequence\n"; return true; 1.221 + case EOpComma: out << "Comma\n"; return true; 1.222 + case EOpFunction: out << "Function Definition: " << node->getName(); break; 1.223 + case EOpFunctionCall: out << "Function Call: " << node->getName(); break; 1.224 + case EOpParameters: out << "Function Parameters: "; break; 1.225 + 1.226 + case EOpConstructFloat: out << "Construct float"; break; 1.227 + case EOpConstructVec2: out << "Construct vec2"; break; 1.228 + case EOpConstructVec3: out << "Construct vec3"; break; 1.229 + case EOpConstructVec4: out << "Construct vec4"; break; 1.230 + case EOpConstructBool: out << "Construct bool"; break; 1.231 + case EOpConstructBVec2: out << "Construct bvec2"; break; 1.232 + case EOpConstructBVec3: out << "Construct bvec3"; break; 1.233 + case EOpConstructBVec4: out << "Construct bvec4"; break; 1.234 + case EOpConstructInt: out << "Construct int"; break; 1.235 + case EOpConstructIVec2: out << "Construct ivec2"; break; 1.236 + case EOpConstructIVec3: out << "Construct ivec3"; break; 1.237 + case EOpConstructIVec4: out << "Construct ivec4"; break; 1.238 + case EOpConstructMat2: out << "Construct mat2"; break; 1.239 + case EOpConstructMat3: out << "Construct mat3"; break; 1.240 + case EOpConstructMat4: out << "Construct mat4"; break; 1.241 + case EOpConstructStruct: out << "Construct structure"; break; 1.242 + 1.243 + case EOpLessThan: out << "Compare Less Than"; break; 1.244 + case EOpGreaterThan: out << "Compare Greater Than"; break; 1.245 + case EOpLessThanEqual: out << "Compare Less Than or Equal"; break; 1.246 + case EOpGreaterThanEqual: out << "Compare Greater Than or Equal"; break; 1.247 + case EOpVectorEqual: out << "Equal"; break; 1.248 + case EOpVectorNotEqual: out << "NotEqual"; break; 1.249 + 1.250 + case EOpMod: out << "mod"; break; 1.251 + case EOpPow: out << "pow"; break; 1.252 + 1.253 + case EOpAtan: out << "arc tangent"; break; 1.254 + 1.255 + case EOpMin: out << "min"; break; 1.256 + case EOpMax: out << "max"; break; 1.257 + case EOpClamp: out << "clamp"; break; 1.258 + case EOpMix: out << "mix"; break; 1.259 + case EOpStep: out << "step"; break; 1.260 + case EOpSmoothStep: out << "smoothstep"; break; 1.261 + 1.262 + case EOpDistance: out << "distance"; break; 1.263 + case EOpDot: out << "dot-product"; break; 1.264 + case EOpCross: out << "cross-product"; break; 1.265 + case EOpFaceForward: out << "face-forward"; break; 1.266 + case EOpReflect: out << "reflect"; break; 1.267 + case EOpRefract: out << "refract"; break; 1.268 + case EOpMul: out << "component-wise multiply"; break; 1.269 + 1.270 + case EOpDeclaration: out << "Declaration: "; break; 1.271 + 1.272 + default: 1.273 + out.prefix(EPrefixError); 1.274 + out << "Bad aggregation op"; 1.275 + } 1.276 + 1.277 + if (node->getOp() != EOpSequence && node->getOp() != EOpParameters) 1.278 + out << " (" << node->getCompleteString() << ")"; 1.279 + 1.280 + out << "\n"; 1.281 + 1.282 + return true; 1.283 +} 1.284 + 1.285 +bool TOutputTraverser::visitSelection(Visit visit, TIntermSelection* node) 1.286 +{ 1.287 + TInfoSinkBase& out = sink; 1.288 + 1.289 + OutputTreeText(out, node, depth); 1.290 + 1.291 + out << "Test condition and select"; 1.292 + out << " (" << node->getCompleteString() << ")\n"; 1.293 + 1.294 + ++depth; 1.295 + 1.296 + OutputTreeText(sink, node, depth); 1.297 + out << "Condition\n"; 1.298 + node->getCondition()->traverse(this); 1.299 + 1.300 + OutputTreeText(sink, node, depth); 1.301 + if (node->getTrueBlock()) { 1.302 + out << "true case\n"; 1.303 + node->getTrueBlock()->traverse(this); 1.304 + } else 1.305 + out << "true case is null\n"; 1.306 + 1.307 + if (node->getFalseBlock()) { 1.308 + OutputTreeText(sink, node, depth); 1.309 + out << "false case\n"; 1.310 + node->getFalseBlock()->traverse(this); 1.311 + } 1.312 + 1.313 + --depth; 1.314 + 1.315 + return false; 1.316 +} 1.317 + 1.318 +void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node) 1.319 +{ 1.320 + TInfoSinkBase& out = sink; 1.321 + 1.322 + size_t size = node->getType().getObjectSize(); 1.323 + 1.324 + for (size_t i = 0; i < size; i++) { 1.325 + OutputTreeText(out, node, depth); 1.326 + switch (node->getUnionArrayPointer()[i].getType()) { 1.327 + case EbtBool: 1.328 + if (node->getUnionArrayPointer()[i].getBConst()) 1.329 + out << "true"; 1.330 + else 1.331 + out << "false"; 1.332 + 1.333 + out << " (" << "const bool" << ")"; 1.334 + out << "\n"; 1.335 + break; 1.336 + case EbtFloat: 1.337 + out << node->getUnionArrayPointer()[i].getFConst(); 1.338 + out << " (const float)\n"; 1.339 + break; 1.340 + case EbtInt: 1.341 + out << node->getUnionArrayPointer()[i].getIConst(); 1.342 + out << " (const int)\n"; 1.343 + break; 1.344 + default: 1.345 + out.message(EPrefixInternalError, node->getLine(), "Unknown constant"); 1.346 + break; 1.347 + } 1.348 + } 1.349 +} 1.350 + 1.351 +bool TOutputTraverser::visitLoop(Visit visit, TIntermLoop* node) 1.352 +{ 1.353 + TInfoSinkBase& out = sink; 1.354 + 1.355 + OutputTreeText(out, node, depth); 1.356 + 1.357 + out << "Loop with condition "; 1.358 + if (node->getType() == ELoopDoWhile) 1.359 + out << "not "; 1.360 + out << "tested first\n"; 1.361 + 1.362 + ++depth; 1.363 + 1.364 + OutputTreeText(sink, node, depth); 1.365 + if (node->getCondition()) { 1.366 + out << "Loop Condition\n"; 1.367 + node->getCondition()->traverse(this); 1.368 + } else 1.369 + out << "No loop condition\n"; 1.370 + 1.371 + OutputTreeText(sink, node, depth); 1.372 + if (node->getBody()) { 1.373 + out << "Loop Body\n"; 1.374 + node->getBody()->traverse(this); 1.375 + } else 1.376 + out << "No loop body\n"; 1.377 + 1.378 + if (node->getExpression()) { 1.379 + OutputTreeText(sink, node, depth); 1.380 + out << "Loop Terminal Expression\n"; 1.381 + node->getExpression()->traverse(this); 1.382 + } 1.383 + 1.384 + --depth; 1.385 + 1.386 + return false; 1.387 +} 1.388 + 1.389 +bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch* node) 1.390 +{ 1.391 + TInfoSinkBase& out = sink; 1.392 + 1.393 + OutputTreeText(out, node, depth); 1.394 + 1.395 + switch (node->getFlowOp()) { 1.396 + case EOpKill: out << "Branch: Kill"; break; 1.397 + case EOpBreak: out << "Branch: Break"; break; 1.398 + case EOpContinue: out << "Branch: Continue"; break; 1.399 + case EOpReturn: out << "Branch: Return"; break; 1.400 + default: out << "Branch: Unknown Branch"; break; 1.401 + } 1.402 + 1.403 + if (node->getExpression()) { 1.404 + out << " with expression\n"; 1.405 + ++depth; 1.406 + node->getExpression()->traverse(this); 1.407 + --depth; 1.408 + } else 1.409 + out << "\n"; 1.410 + 1.411 + return false; 1.412 +} 1.413 + 1.414 +// 1.415 +// This function is the one to call externally to start the traversal. 1.416 +// Individual functions can be initialized to 0 to skip processing of that 1.417 +// type of node. It's children will still be processed. 1.418 +// 1.419 +void TIntermediate::outputTree(TIntermNode* root) 1.420 +{ 1.421 + if (root == 0) 1.422 + return; 1.423 + 1.424 + TOutputTraverser it(infoSink.info); 1.425 + 1.426 + root->traverse(&it); 1.427 +}