1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/angle/src/compiler/intermediate.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,579 @@ 1.4 +// 1.5 +// Copyright (c) 2002-2013 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 +// 1.11 +// Definition of the in-memory high-level intermediate representation 1.12 +// of shaders. This is a tree that parser creates. 1.13 +// 1.14 +// Nodes in the tree are defined as a hierarchy of classes derived from 1.15 +// TIntermNode. Each is a node in a tree. There is no preset branching factor; 1.16 +// each node can have it's own type of list of children. 1.17 +// 1.18 + 1.19 +#ifndef __INTERMEDIATE_H 1.20 +#define __INTERMEDIATE_H 1.21 + 1.22 +#include "GLSLANG/ShaderLang.h" 1.23 + 1.24 +#include <algorithm> 1.25 +#include "compiler/Common.h" 1.26 +#include "compiler/Types.h" 1.27 +#include "compiler/ConstantUnion.h" 1.28 + 1.29 +// 1.30 +// Operators used by the high-level (parse tree) representation. 1.31 +// 1.32 +enum TOperator { 1.33 + EOpNull, // if in a node, should only mean a node is still being built 1.34 + EOpSequence, // denotes a list of statements, or parameters, etc. 1.35 + EOpFunctionCall, 1.36 + EOpFunction, // For function definition 1.37 + EOpParameters, // an aggregate listing the parameters to a function 1.38 + 1.39 + EOpDeclaration, 1.40 + EOpPrototype, 1.41 + 1.42 + // 1.43 + // Unary operators 1.44 + // 1.45 + 1.46 + EOpNegative, 1.47 + EOpLogicalNot, 1.48 + EOpVectorLogicalNot, 1.49 + 1.50 + EOpPostIncrement, 1.51 + EOpPostDecrement, 1.52 + EOpPreIncrement, 1.53 + EOpPreDecrement, 1.54 + 1.55 + EOpConvIntToBool, 1.56 + EOpConvFloatToBool, 1.57 + EOpConvBoolToFloat, 1.58 + EOpConvIntToFloat, 1.59 + EOpConvFloatToInt, 1.60 + EOpConvBoolToInt, 1.61 + 1.62 + // 1.63 + // binary operations 1.64 + // 1.65 + 1.66 + EOpAdd, 1.67 + EOpSub, 1.68 + EOpMul, 1.69 + EOpDiv, 1.70 + EOpEqual, 1.71 + EOpNotEqual, 1.72 + EOpVectorEqual, 1.73 + EOpVectorNotEqual, 1.74 + EOpLessThan, 1.75 + EOpGreaterThan, 1.76 + EOpLessThanEqual, 1.77 + EOpGreaterThanEqual, 1.78 + EOpComma, 1.79 + 1.80 + EOpVectorTimesScalar, 1.81 + EOpVectorTimesMatrix, 1.82 + EOpMatrixTimesVector, 1.83 + EOpMatrixTimesScalar, 1.84 + 1.85 + EOpLogicalOr, 1.86 + EOpLogicalXor, 1.87 + EOpLogicalAnd, 1.88 + 1.89 + EOpIndexDirect, 1.90 + EOpIndexIndirect, 1.91 + EOpIndexDirectStruct, 1.92 + 1.93 + EOpVectorSwizzle, 1.94 + 1.95 + // 1.96 + // Built-in functions potentially mapped to operators 1.97 + // 1.98 + 1.99 + EOpRadians, 1.100 + EOpDegrees, 1.101 + EOpSin, 1.102 + EOpCos, 1.103 + EOpTan, 1.104 + EOpAsin, 1.105 + EOpAcos, 1.106 + EOpAtan, 1.107 + 1.108 + EOpPow, 1.109 + EOpExp, 1.110 + EOpLog, 1.111 + EOpExp2, 1.112 + EOpLog2, 1.113 + EOpSqrt, 1.114 + EOpInverseSqrt, 1.115 + 1.116 + EOpAbs, 1.117 + EOpSign, 1.118 + EOpFloor, 1.119 + EOpCeil, 1.120 + EOpFract, 1.121 + EOpMod, 1.122 + EOpMin, 1.123 + EOpMax, 1.124 + EOpClamp, 1.125 + EOpMix, 1.126 + EOpStep, 1.127 + EOpSmoothStep, 1.128 + 1.129 + EOpLength, 1.130 + EOpDistance, 1.131 + EOpDot, 1.132 + EOpCross, 1.133 + EOpNormalize, 1.134 + EOpFaceForward, 1.135 + EOpReflect, 1.136 + EOpRefract, 1.137 + 1.138 + EOpDFdx, // Fragment only, OES_standard_derivatives extension 1.139 + EOpDFdy, // Fragment only, OES_standard_derivatives extension 1.140 + EOpFwidth, // Fragment only, OES_standard_derivatives extension 1.141 + 1.142 + EOpMatrixTimesMatrix, 1.143 + 1.144 + EOpAny, 1.145 + EOpAll, 1.146 + 1.147 + // 1.148 + // Branch 1.149 + // 1.150 + 1.151 + EOpKill, // Fragment only 1.152 + EOpReturn, 1.153 + EOpBreak, 1.154 + EOpContinue, 1.155 + 1.156 + // 1.157 + // Constructors 1.158 + // 1.159 + 1.160 + EOpConstructInt, 1.161 + EOpConstructBool, 1.162 + EOpConstructFloat, 1.163 + EOpConstructVec2, 1.164 + EOpConstructVec3, 1.165 + EOpConstructVec4, 1.166 + EOpConstructBVec2, 1.167 + EOpConstructBVec3, 1.168 + EOpConstructBVec4, 1.169 + EOpConstructIVec2, 1.170 + EOpConstructIVec3, 1.171 + EOpConstructIVec4, 1.172 + EOpConstructMat2, 1.173 + EOpConstructMat3, 1.174 + EOpConstructMat4, 1.175 + EOpConstructStruct, 1.176 + 1.177 + // 1.178 + // moves 1.179 + // 1.180 + 1.181 + EOpAssign, 1.182 + EOpInitialize, 1.183 + EOpAddAssign, 1.184 + EOpSubAssign, 1.185 + EOpMulAssign, 1.186 + EOpVectorTimesMatrixAssign, 1.187 + EOpVectorTimesScalarAssign, 1.188 + EOpMatrixTimesScalarAssign, 1.189 + EOpMatrixTimesMatrixAssign, 1.190 + EOpDivAssign 1.191 +}; 1.192 + 1.193 +extern const char* getOperatorString(TOperator op); 1.194 + 1.195 +class TIntermTraverser; 1.196 +class TIntermAggregate; 1.197 +class TIntermBinary; 1.198 +class TIntermUnary; 1.199 +class TIntermConstantUnion; 1.200 +class TIntermSelection; 1.201 +class TIntermTyped; 1.202 +class TIntermSymbol; 1.203 +class TIntermLoop; 1.204 +class TInfoSink; 1.205 + 1.206 +// 1.207 +// Base class for the tree nodes 1.208 +// 1.209 +class TIntermNode { 1.210 +public: 1.211 + POOL_ALLOCATOR_NEW_DELETE(); 1.212 + TIntermNode() { 1.213 + // TODO: Move this to TSourceLoc constructor 1.214 + // after getting rid of TPublicType. 1.215 + line.first_file = line.last_file = 0; 1.216 + line.first_line = line.last_line = 0; 1.217 + } 1.218 + virtual ~TIntermNode() { } 1.219 + 1.220 + const TSourceLoc& getLine() const { return line; } 1.221 + void setLine(const TSourceLoc& l) { line = l; } 1.222 + 1.223 + virtual void traverse(TIntermTraverser*) = 0; 1.224 + virtual TIntermTyped* getAsTyped() { return 0; } 1.225 + virtual TIntermConstantUnion* getAsConstantUnion() { return 0; } 1.226 + virtual TIntermAggregate* getAsAggregate() { return 0; } 1.227 + virtual TIntermBinary* getAsBinaryNode() { return 0; } 1.228 + virtual TIntermUnary* getAsUnaryNode() { return 0; } 1.229 + virtual TIntermSelection* getAsSelectionNode() { return 0; } 1.230 + virtual TIntermSymbol* getAsSymbolNode() { return 0; } 1.231 + virtual TIntermLoop* getAsLoopNode() { return 0; } 1.232 + 1.233 +protected: 1.234 + TSourceLoc line; 1.235 +}; 1.236 + 1.237 +// 1.238 +// This is just to help yacc. 1.239 +// 1.240 +struct TIntermNodePair { 1.241 + TIntermNode* node1; 1.242 + TIntermNode* node2; 1.243 +}; 1.244 + 1.245 +// 1.246 +// Intermediate class for nodes that have a type. 1.247 +// 1.248 +class TIntermTyped : public TIntermNode { 1.249 +public: 1.250 + TIntermTyped(const TType& t) : type(t) { } 1.251 + virtual TIntermTyped* getAsTyped() { return this; } 1.252 + 1.253 + void setType(const TType& t) { type = t; } 1.254 + const TType& getType() const { return type; } 1.255 + TType* getTypePointer() { return &type; } 1.256 + 1.257 + TBasicType getBasicType() const { return type.getBasicType(); } 1.258 + TQualifier getQualifier() const { return type.getQualifier(); } 1.259 + TPrecision getPrecision() const { return type.getPrecision(); } 1.260 + int getNominalSize() const { return type.getNominalSize(); } 1.261 + 1.262 + bool isMatrix() const { return type.isMatrix(); } 1.263 + bool isArray() const { return type.isArray(); } 1.264 + bool isVector() const { return type.isVector(); } 1.265 + bool isScalar() const { return type.isScalar(); } 1.266 + const char* getBasicString() const { return type.getBasicString(); } 1.267 + const char* getQualifierString() const { return type.getQualifierString(); } 1.268 + TString getCompleteString() const { return type.getCompleteString(); } 1.269 + 1.270 + int totalRegisterCount() const { return type.totalRegisterCount(); } 1.271 + int elementRegisterCount() const { return type.elementRegisterCount(); } 1.272 + int getArraySize() const { return type.getArraySize(); } 1.273 + 1.274 +protected: 1.275 + TType type; 1.276 +}; 1.277 + 1.278 +// 1.279 +// Handle for, do-while, and while loops. 1.280 +// 1.281 +enum TLoopType { 1.282 + ELoopFor, 1.283 + ELoopWhile, 1.284 + ELoopDoWhile 1.285 +}; 1.286 + 1.287 +class TIntermLoop : public TIntermNode { 1.288 +public: 1.289 + TIntermLoop(TLoopType aType, 1.290 + TIntermNode *aInit, TIntermTyped* aCond, TIntermTyped* aExpr, 1.291 + TIntermNode* aBody) : 1.292 + type(aType), 1.293 + init(aInit), 1.294 + cond(aCond), 1.295 + expr(aExpr), 1.296 + body(aBody), 1.297 + unrollFlag(false) { } 1.298 + 1.299 + virtual TIntermLoop* getAsLoopNode() { return this; } 1.300 + virtual void traverse(TIntermTraverser*); 1.301 + 1.302 + TLoopType getType() const { return type; } 1.303 + TIntermNode* getInit() { return init; } 1.304 + TIntermTyped* getCondition() { return cond; } 1.305 + TIntermTyped* getExpression() { return expr; } 1.306 + TIntermNode* getBody() { return body; } 1.307 + 1.308 + void setUnrollFlag(bool flag) { unrollFlag = flag; } 1.309 + bool getUnrollFlag() { return unrollFlag; } 1.310 + 1.311 +protected: 1.312 + TLoopType type; 1.313 + TIntermNode* init; // for-loop initialization 1.314 + TIntermTyped* cond; // loop exit condition 1.315 + TIntermTyped* expr; // for-loop expression 1.316 + TIntermNode* body; // loop body 1.317 + 1.318 + bool unrollFlag; // Whether the loop should be unrolled or not. 1.319 +}; 1.320 + 1.321 +// 1.322 +// Handle break, continue, return, and kill. 1.323 +// 1.324 +class TIntermBranch : public TIntermNode { 1.325 +public: 1.326 + TIntermBranch(TOperator op, TIntermTyped* e) : 1.327 + flowOp(op), 1.328 + expression(e) { } 1.329 + 1.330 + virtual void traverse(TIntermTraverser*); 1.331 + 1.332 + TOperator getFlowOp() { return flowOp; } 1.333 + TIntermTyped* getExpression() { return expression; } 1.334 + 1.335 +protected: 1.336 + TOperator flowOp; 1.337 + TIntermTyped* expression; // non-zero except for "return exp;" statements 1.338 +}; 1.339 + 1.340 +// 1.341 +// Nodes that correspond to symbols or constants in the source code. 1.342 +// 1.343 +class TIntermSymbol : public TIntermTyped { 1.344 +public: 1.345 + // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. If sym comes from 1.346 + // per process globalpoolallocator, then it causes increased memory usage per compile 1.347 + // it is essential to use "symbol = sym" to assign to symbol 1.348 + TIntermSymbol(int i, const TString& sym, const TType& t) : 1.349 + TIntermTyped(t), id(i) { symbol = sym; originalSymbol = sym; } 1.350 + 1.351 + int getId() const { return id; } 1.352 + const TString& getSymbol() const { return symbol; } 1.353 + 1.354 + void setId(int newId) { id = newId; } 1.355 + void setSymbol(const TString& sym) { symbol = sym; } 1.356 + 1.357 + const TString& getOriginalSymbol() const { return originalSymbol; } 1.358 + 1.359 + virtual void traverse(TIntermTraverser*); 1.360 + virtual TIntermSymbol* getAsSymbolNode() { return this; } 1.361 + 1.362 +protected: 1.363 + int id; 1.364 + TString symbol; 1.365 + TString originalSymbol; 1.366 +}; 1.367 + 1.368 +class TIntermConstantUnion : public TIntermTyped { 1.369 +public: 1.370 + TIntermConstantUnion(ConstantUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer) { } 1.371 + 1.372 + ConstantUnion* getUnionArrayPointer() const { return unionArrayPointer; } 1.373 + 1.374 + int getIConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getIConst() : 0; } 1.375 + float getFConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getFConst() : 0.0f; } 1.376 + bool getBConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getBConst() : false; } 1.377 + 1.378 + virtual TIntermConstantUnion* getAsConstantUnion() { return this; } 1.379 + virtual void traverse(TIntermTraverser*); 1.380 + 1.381 + TIntermTyped* fold(TOperator, TIntermTyped*, TInfoSink&); 1.382 + 1.383 +protected: 1.384 + ConstantUnion *unionArrayPointer; 1.385 +}; 1.386 + 1.387 +// 1.388 +// Intermediate class for node types that hold operators. 1.389 +// 1.390 +class TIntermOperator : public TIntermTyped { 1.391 +public: 1.392 + TOperator getOp() const { return op; } 1.393 + void setOp(TOperator o) { op = o; } 1.394 + 1.395 + bool modifiesState() const; 1.396 + bool isConstructor() const; 1.397 + 1.398 +protected: 1.399 + TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat, EbpUndefined)), op(o) {} 1.400 + TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o) {} 1.401 + TOperator op; 1.402 +}; 1.403 + 1.404 +// 1.405 +// Nodes for all the basic binary math operators. 1.406 +// 1.407 +class TIntermBinary : public TIntermOperator { 1.408 +public: 1.409 + TIntermBinary(TOperator o) : TIntermOperator(o), addIndexClamp(false) {} 1.410 + 1.411 + virtual TIntermBinary* getAsBinaryNode() { return this; } 1.412 + virtual void traverse(TIntermTraverser*); 1.413 + 1.414 + void setLeft(TIntermTyped* n) { left = n; } 1.415 + void setRight(TIntermTyped* n) { right = n; } 1.416 + TIntermTyped* getLeft() const { return left; } 1.417 + TIntermTyped* getRight() const { return right; } 1.418 + bool promote(TInfoSink&); 1.419 + 1.420 + void setAddIndexClamp() { addIndexClamp = true; } 1.421 + bool getAddIndexClamp() { return addIndexClamp; } 1.422 + 1.423 +protected: 1.424 + TIntermTyped* left; 1.425 + TIntermTyped* right; 1.426 + 1.427 + // If set to true, wrap any EOpIndexIndirect with a clamp to bounds. 1.428 + bool addIndexClamp; 1.429 +}; 1.430 + 1.431 +// 1.432 +// Nodes for unary math operators. 1.433 +// 1.434 +class TIntermUnary : public TIntermOperator { 1.435 +public: 1.436 + TIntermUnary(TOperator o, TType& t) : TIntermOperator(o, t), operand(0), useEmulatedFunction(false) {} 1.437 + TIntermUnary(TOperator o) : TIntermOperator(o), operand(0), useEmulatedFunction(false) {} 1.438 + 1.439 + virtual void traverse(TIntermTraverser*); 1.440 + virtual TIntermUnary* getAsUnaryNode() { return this; } 1.441 + 1.442 + void setOperand(TIntermTyped* o) { operand = o; } 1.443 + TIntermTyped* getOperand() { return operand; } 1.444 + bool promote(TInfoSink&); 1.445 + 1.446 + void setUseEmulatedFunction() { useEmulatedFunction = true; } 1.447 + bool getUseEmulatedFunction() { return useEmulatedFunction; } 1.448 + 1.449 +protected: 1.450 + TIntermTyped* operand; 1.451 + 1.452 + // If set to true, replace the built-in function call with an emulated one 1.453 + // to work around driver bugs. 1.454 + bool useEmulatedFunction; 1.455 +}; 1.456 + 1.457 +typedef TVector<TIntermNode*> TIntermSequence; 1.458 +typedef TVector<int> TQualifierList; 1.459 + 1.460 +// 1.461 +// Nodes that operate on an arbitrary sized set of children. 1.462 +// 1.463 +class TIntermAggregate : public TIntermOperator { 1.464 +public: 1.465 + TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), useEmulatedFunction(false) { } 1.466 + TIntermAggregate(TOperator o) : TIntermOperator(o), useEmulatedFunction(false) { } 1.467 + ~TIntermAggregate() { } 1.468 + 1.469 + virtual TIntermAggregate* getAsAggregate() { return this; } 1.470 + virtual void traverse(TIntermTraverser*); 1.471 + 1.472 + TIntermSequence& getSequence() { return sequence; } 1.473 + 1.474 + void setName(const TString& n) { name = n; } 1.475 + const TString& getName() const { return name; } 1.476 + 1.477 + void setUserDefined() { userDefined = true; } 1.478 + bool isUserDefined() const { return userDefined; } 1.479 + 1.480 + void setOptimize(bool o) { optimize = o; } 1.481 + bool getOptimize() { return optimize; } 1.482 + void setDebug(bool d) { debug = d; } 1.483 + bool getDebug() { return debug; } 1.484 + 1.485 + void setUseEmulatedFunction() { useEmulatedFunction = true; } 1.486 + bool getUseEmulatedFunction() { return useEmulatedFunction; } 1.487 + 1.488 +protected: 1.489 + TIntermAggregate(const TIntermAggregate&); // disallow copy constructor 1.490 + TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator 1.491 + TIntermSequence sequence; 1.492 + TString name; 1.493 + bool userDefined; // used for user defined function names 1.494 + 1.495 + bool optimize; 1.496 + bool debug; 1.497 + 1.498 + // If set to true, replace the built-in function call with an emulated one 1.499 + // to work around driver bugs. 1.500 + bool useEmulatedFunction; 1.501 +}; 1.502 + 1.503 +// 1.504 +// For if tests. Simplified since there is no switch statement. 1.505 +// 1.506 +class TIntermSelection : public TIntermTyped { 1.507 +public: 1.508 + TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) : 1.509 + TIntermTyped(TType(EbtVoid, EbpUndefined)), condition(cond), trueBlock(trueB), falseBlock(falseB) {} 1.510 + TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) : 1.511 + TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB) {} 1.512 + 1.513 + virtual void traverse(TIntermTraverser*); 1.514 + 1.515 + bool usesTernaryOperator() const { return getBasicType() != EbtVoid; } 1.516 + TIntermNode* getCondition() const { return condition; } 1.517 + TIntermNode* getTrueBlock() const { return trueBlock; } 1.518 + TIntermNode* getFalseBlock() const { return falseBlock; } 1.519 + TIntermSelection* getAsSelectionNode() { return this; } 1.520 + 1.521 +protected: 1.522 + TIntermTyped* condition; 1.523 + TIntermNode* trueBlock; 1.524 + TIntermNode* falseBlock; 1.525 +}; 1.526 + 1.527 +enum Visit 1.528 +{ 1.529 + PreVisit, 1.530 + InVisit, 1.531 + PostVisit 1.532 +}; 1.533 + 1.534 +// 1.535 +// For traversing the tree. User should derive from this, 1.536 +// put their traversal specific data in it, and then pass 1.537 +// it to a Traverse method. 1.538 +// 1.539 +// When using this, just fill in the methods for nodes you want visited. 1.540 +// Return false from a pre-visit to skip visiting that node's subtree. 1.541 +// 1.542 +class TIntermTraverser 1.543 +{ 1.544 +public: 1.545 + POOL_ALLOCATOR_NEW_DELETE(); 1.546 + TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) : 1.547 + preVisit(preVisit), 1.548 + inVisit(inVisit), 1.549 + postVisit(postVisit), 1.550 + rightToLeft(rightToLeft), 1.551 + depth(0), 1.552 + maxDepth(0) {} 1.553 + virtual ~TIntermTraverser() {}; 1.554 + 1.555 + virtual void visitSymbol(TIntermSymbol*) {} 1.556 + virtual void visitConstantUnion(TIntermConstantUnion*) {} 1.557 + virtual bool visitBinary(Visit visit, TIntermBinary*) {return true;} 1.558 + virtual bool visitUnary(Visit visit, TIntermUnary*) {return true;} 1.559 + virtual bool visitSelection(Visit visit, TIntermSelection*) {return true;} 1.560 + virtual bool visitAggregate(Visit visit, TIntermAggregate*) {return true;} 1.561 + virtual bool visitLoop(Visit visit, TIntermLoop*) {return true;} 1.562 + virtual bool visitBranch(Visit visit, TIntermBranch*) {return true;} 1.563 + 1.564 + int getMaxDepth() const {return maxDepth;} 1.565 + void incrementDepth() {depth++; maxDepth = std::max(maxDepth, depth); } 1.566 + void decrementDepth() {depth--;} 1.567 + 1.568 + // Return the original name if hash function pointer is NULL; 1.569 + // otherwise return the hashed name. 1.570 + static TString hash(const TString& name, ShHashFunction64 hashFunction); 1.571 + 1.572 + const bool preVisit; 1.573 + const bool inVisit; 1.574 + const bool postVisit; 1.575 + const bool rightToLeft; 1.576 + 1.577 +protected: 1.578 + int depth; 1.579 + int maxDepth; 1.580 +}; 1.581 + 1.582 +#endif // __INTERMEDIATE_H