1 // 2 // Copyright (c) 2002-2010 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 // 8 // Definition of the in-memory high-level intermediate representation 9 // of shaders. This is a tree that parser creates. 10 // 11 // Nodes in the tree are defined as a hierarchy of classes derived from 12 // TIntermNode. Each is a node in a tree. There is no preset branching factor; 13 // each node can have it's own type of list of children. 14 // 15 16 #ifndef __INTERMEDIATE_H 17 #define __INTERMEDIATE_H 18 19 #include "compiler/Common.h" 20 #include "compiler/Types.h" 21 #include "compiler/ConstantUnion.h" 22 23 // 24 // Operators used by the high-level (parse tree) representation. 25 // 26 enum TOperator { 27 EOpNull, // if in a node, should only mean a node is still being built 28 EOpSequence, // denotes a list of statements, or parameters, etc. 29 EOpFunctionCall, 30 EOpFunction, // For function definition 31 EOpParameters, // an aggregate listing the parameters to a function 32 33 EOpDeclaration, 34 EOpPrototype, 35 36 // 37 // Unary operators 38 // 39 40 EOpNegative, 41 EOpLogicalNot, 42 EOpVectorLogicalNot, 43 44 EOpPostIncrement, 45 EOpPostDecrement, 46 EOpPreIncrement, 47 EOpPreDecrement, 48 49 EOpConvIntToBool, 50 EOpConvFloatToBool, 51 EOpConvBoolToFloat, 52 EOpConvIntToFloat, 53 EOpConvFloatToInt, 54 EOpConvBoolToInt, 55 56 // 57 // binary operations 58 // 59 60 EOpAdd, 61 EOpSub, 62 EOpMul, 63 EOpDiv, 64 EOpEqual, 65 EOpNotEqual, 66 EOpVectorEqual, 67 EOpVectorNotEqual, 68 EOpLessThan, 69 EOpGreaterThan, 70 EOpLessThanEqual, 71 EOpGreaterThanEqual, 72 EOpComma, 73 74 EOpVectorTimesScalar, 75 EOpVectorTimesMatrix, 76 EOpMatrixTimesVector, 77 EOpMatrixTimesScalar, 78 79 EOpLogicalOr, 80 EOpLogicalXor, 81 EOpLogicalAnd, 82 83 EOpIndexDirect, 84 EOpIndexIndirect, 85 EOpIndexDirectStruct, 86 87 EOpVectorSwizzle, 88 89 // 90 // Built-in functions potentially mapped to operators 91 // 92 93 EOpRadians, 94 EOpDegrees, 95 EOpSin, 96 EOpCos, 97 EOpTan, 98 EOpAsin, 99 EOpAcos, 100 EOpAtan, 101 102 EOpPow, 103 EOpExp, 104 EOpLog, 105 EOpExp2, 106 EOpLog2, 107 EOpSqrt, 108 EOpInverseSqrt, 109 110 EOpAbs, 111 EOpSign, 112 EOpFloor, 113 EOpCeil, 114 EOpFract, 115 EOpMod, 116 EOpMin, 117 EOpMax, 118 EOpClamp, 119 EOpMix, 120 EOpStep, 121 EOpSmoothStep, 122 123 EOpLength, 124 EOpDistance, 125 EOpDot, 126 EOpCross, 127 EOpNormalize, 128 EOpFaceForward, 129 EOpReflect, 130 EOpRefract, 131 132 EOpDFdx, // Fragment only, OES_standard_derivatives extension 133 EOpDFdy, // Fragment only, OES_standard_derivatives extension 134 EOpFwidth, // Fragment only, OES_standard_derivatives extension 135 136 EOpMatrixTimesMatrix, 137 138 EOpAny, 139 EOpAll, 140 141 // 142 // Branch 143 // 144 145 EOpKill, // Fragment only 146 EOpReturn, 147 EOpBreak, 148 EOpContinue, 149 150 // 151 // Constructors 152 // 153 154 EOpConstructInt, 155 EOpConstructBool, 156 EOpConstructFloat, 157 EOpConstructVec2, 158 EOpConstructVec3, 159 EOpConstructVec4, 160 EOpConstructBVec2, 161 EOpConstructBVec3, 162 EOpConstructBVec4, 163 EOpConstructIVec2, 164 EOpConstructIVec3, 165 EOpConstructIVec4, 166 EOpConstructMat2, 167 EOpConstructMat3, 168 EOpConstructMat4, 169 EOpConstructStruct, 170 171 // 172 // moves 173 // 174 175 EOpAssign, 176 EOpInitialize, 177 EOpAddAssign, 178 EOpSubAssign, 179 EOpMulAssign, 180 EOpVectorTimesMatrixAssign, 181 EOpVectorTimesScalarAssign, 182 EOpMatrixTimesScalarAssign, 183 EOpMatrixTimesMatrixAssign, 184 EOpDivAssign, 185 }; 186 187 extern const char* getOperatorString(TOperator op); 188 189 class TIntermTraverser; 190 class TIntermAggregate; 191 class TIntermBinary; 192 class TIntermUnary; 193 class TIntermConstantUnion; 194 class TIntermSelection; 195 class TIntermTyped; 196 class TIntermSymbol; 197 class TIntermLoop; 198 class TInfoSink; 199 200 // 201 // Base class for the tree nodes 202 // 203 class TIntermNode { 204 public: POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)205 POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) 206 207 TIntermNode() : line(0) {} 208 getLine()209 TSourceLoc getLine() const { return line; } setLine(TSourceLoc l)210 void setLine(TSourceLoc l) { line = l; } 211 212 virtual void traverse(TIntermTraverser*) = 0; getAsTyped()213 virtual TIntermTyped* getAsTyped() { return 0; } getAsConstantUnion()214 virtual TIntermConstantUnion* getAsConstantUnion() { return 0; } getAsAggregate()215 virtual TIntermAggregate* getAsAggregate() { return 0; } getAsBinaryNode()216 virtual TIntermBinary* getAsBinaryNode() { return 0; } getAsUnaryNode()217 virtual TIntermUnary* getAsUnaryNode() { return 0; } getAsSelectionNode()218 virtual TIntermSelection* getAsSelectionNode() { return 0; } getAsSymbolNode()219 virtual TIntermSymbol* getAsSymbolNode() { return 0; } getAsLoopNode()220 virtual TIntermLoop* getAsLoopNode() { return 0; } ~TIntermNode()221 virtual ~TIntermNode() { } 222 223 protected: 224 TSourceLoc line; 225 }; 226 227 // 228 // This is just to help yacc. 229 // 230 struct TIntermNodePair { 231 TIntermNode* node1; 232 TIntermNode* node2; 233 }; 234 235 // 236 // Intermediate class for nodes that have a type. 237 // 238 class TIntermTyped : public TIntermNode { 239 public: TIntermTyped(const TType & t)240 TIntermTyped(const TType& t) : type(t) { } getAsTyped()241 virtual TIntermTyped* getAsTyped() { return this; } 242 setType(const TType & t)243 void setType(const TType& t) { type = t; } getType()244 const TType& getType() const { return type; } getTypePointer()245 TType* getTypePointer() { return &type; } 246 getBasicType()247 TBasicType getBasicType() const { return type.getBasicType(); } getQualifier()248 TQualifier getQualifier() const { return type.getQualifier(); } getPrecision()249 TPrecision getPrecision() const { return type.getPrecision(); } getNominalSize()250 int getNominalSize() const { return type.getNominalSize(); } 251 isMatrix()252 bool isMatrix() const { return type.isMatrix(); } isArray()253 bool isArray() const { return type.isArray(); } isVector()254 bool isVector() const { return type.isVector(); } isScalar()255 bool isScalar() const { return type.isScalar(); } getBasicString()256 const char* getBasicString() const { return type.getBasicString(); } getQualifierString()257 const char* getQualifierString() const { return type.getQualifierString(); } getCompleteString()258 TString getCompleteString() const { return type.getCompleteString(); } 259 260 protected: 261 TType type; 262 }; 263 264 // 265 // Handle for, do-while, and while loops. 266 // 267 enum TLoopType { 268 ELoopFor, 269 ELoopWhile, 270 ELoopDoWhile, 271 }; 272 273 class TIntermLoop : public TIntermNode { 274 public: TIntermLoop(TLoopType aType,TIntermNode * aInit,TIntermTyped * aCond,TIntermTyped * aExpr,TIntermNode * aBody)275 TIntermLoop(TLoopType aType, 276 TIntermNode *aInit, TIntermTyped* aCond, TIntermTyped* aExpr, 277 TIntermNode* aBody) : 278 type(aType), 279 init(aInit), 280 cond(aCond), 281 expr(aExpr), 282 body(aBody) { } 283 getAsLoopNode()284 virtual TIntermLoop* getAsLoopNode() { return this; } 285 virtual void traverse(TIntermTraverser*); 286 getType()287 TLoopType getType() const { return type; } getInit()288 TIntermNode* getInit() { return init; } getCondition()289 TIntermTyped* getCondition() { return cond; } getExpression()290 TIntermTyped* getExpression() { return expr; } getBody()291 TIntermNode* getBody() { return body; } 292 293 protected: 294 TLoopType type; 295 TIntermNode* init; // for-loop initialization 296 TIntermTyped* cond; // loop exit condition 297 TIntermTyped* expr; // for-loop expression 298 TIntermNode* body; // loop body 299 }; 300 301 // 302 // Handle break, continue, return, and kill. 303 // 304 class TIntermBranch : public TIntermNode { 305 public: TIntermBranch(TOperator op,TIntermTyped * e)306 TIntermBranch(TOperator op, TIntermTyped* e) : 307 flowOp(op), 308 expression(e) { } 309 310 virtual void traverse(TIntermTraverser*); 311 getFlowOp()312 TOperator getFlowOp() { return flowOp; } getExpression()313 TIntermTyped* getExpression() { return expression; } 314 315 protected: 316 TOperator flowOp; 317 TIntermTyped* expression; // non-zero except for "return exp;" statements 318 }; 319 320 // 321 // Nodes that correspond to symbols or constants in the source code. 322 // 323 class TIntermSymbol : public TIntermTyped { 324 public: 325 // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. If sym comes from 326 // per process globalpoolallocator, then it causes increased memory usage per compile 327 // it is essential to use "symbol = sym" to assign to symbol TIntermSymbol(int i,const TString & sym,const TType & t)328 TIntermSymbol(int i, const TString& sym, const TType& t) : 329 TIntermTyped(t), id(i) { symbol = sym;} 330 getId()331 int getId() const { return id; } getSymbol()332 const TString& getSymbol() const { return symbol; } 333 334 virtual void traverse(TIntermTraverser*); getAsSymbolNode()335 virtual TIntermSymbol* getAsSymbolNode() { return this; } 336 337 protected: 338 int id; 339 TString symbol; 340 }; 341 342 class TIntermConstantUnion : public TIntermTyped { 343 public: TIntermConstantUnion(ConstantUnion * unionPointer,const TType & t)344 TIntermConstantUnion(ConstantUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer) { } 345 getUnionArrayPointer()346 ConstantUnion* getUnionArrayPointer() const { return unionArrayPointer; } setUnionArrayPointer(ConstantUnion * c)347 void setUnionArrayPointer(ConstantUnion *c) { unionArrayPointer = c; } 348 getAsConstantUnion()349 virtual TIntermConstantUnion* getAsConstantUnion() { return this; } 350 virtual void traverse(TIntermTraverser*); 351 352 TIntermTyped* fold(TOperator, TIntermTyped*, TInfoSink&); 353 354 protected: 355 ConstantUnion *unionArrayPointer; 356 }; 357 358 // 359 // Intermediate class for node types that hold operators. 360 // 361 class TIntermOperator : public TIntermTyped { 362 public: getOp()363 TOperator getOp() const { return op; } setOp(TOperator o)364 void setOp(TOperator o) { op = o; } 365 366 bool modifiesState() const; 367 bool isConstructor() const; 368 369 protected: TIntermOperator(TOperator o)370 TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat, EbpUndefined)), op(o) {} TIntermOperator(TOperator o,TType & t)371 TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o) {} 372 TOperator op; 373 }; 374 375 // 376 // Nodes for all the basic binary math operators. 377 // 378 class TIntermBinary : public TIntermOperator { 379 public: TIntermBinary(TOperator o)380 TIntermBinary(TOperator o) : TIntermOperator(o) {} 381 getAsBinaryNode()382 virtual TIntermBinary* getAsBinaryNode() { return this; } 383 virtual void traverse(TIntermTraverser*); 384 setLeft(TIntermTyped * n)385 void setLeft(TIntermTyped* n) { left = n; } setRight(TIntermTyped * n)386 void setRight(TIntermTyped* n) { right = n; } getLeft()387 TIntermTyped* getLeft() const { return left; } getRight()388 TIntermTyped* getRight() const { return right; } 389 bool promote(TInfoSink&); 390 391 protected: 392 TIntermTyped* left; 393 TIntermTyped* right; 394 }; 395 396 // 397 // Nodes for unary math operators. 398 // 399 class TIntermUnary : public TIntermOperator { 400 public: TIntermUnary(TOperator o,TType & t)401 TIntermUnary(TOperator o, TType& t) : TIntermOperator(o, t), operand(0) {} TIntermUnary(TOperator o)402 TIntermUnary(TOperator o) : TIntermOperator(o), operand(0) {} 403 404 virtual void traverse(TIntermTraverser*); getAsUnaryNode()405 virtual TIntermUnary* getAsUnaryNode() { return this; } 406 setOperand(TIntermTyped * o)407 void setOperand(TIntermTyped* o) { operand = o; } getOperand()408 TIntermTyped* getOperand() { return operand; } 409 bool promote(TInfoSink&); 410 411 protected: 412 TIntermTyped* operand; 413 }; 414 415 typedef TVector<TIntermNode*> TIntermSequence; 416 typedef TVector<int> TQualifierList; 417 typedef TMap<TString, TString> TPragmaTable; 418 // 419 // Nodes that operate on an arbitrary sized set of children. 420 // 421 class TIntermAggregate : public TIntermOperator { 422 public: TIntermAggregate()423 TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), pragmaTable(0) { } TIntermAggregate(TOperator o)424 TIntermAggregate(TOperator o) : TIntermOperator(o), pragmaTable(0) { } ~TIntermAggregate()425 ~TIntermAggregate() { delete pragmaTable; } 426 getAsAggregate()427 virtual TIntermAggregate* getAsAggregate() { return this; } 428 virtual void traverse(TIntermTraverser*); 429 getSequence()430 TIntermSequence& getSequence() { return sequence; } 431 setName(const TString & n)432 void setName(const TString& n) { name = n; } getName()433 const TString& getName() const { return name; } 434 setUserDefined()435 void setUserDefined() { userDefined = true; } isUserDefined()436 bool isUserDefined() { return userDefined; } 437 setOptimize(bool o)438 void setOptimize(bool o) { optimize = o; } getOptimize()439 bool getOptimize() { return optimize; } setDebug(bool d)440 void setDebug(bool d) { debug = d; } getDebug()441 bool getDebug() { return debug; } 442 void addToPragmaTable(const TPragmaTable& pTable); getPragmaTable()443 const TPragmaTable& getPragmaTable() const { return *pragmaTable; } 444 445 protected: 446 TIntermAggregate(const TIntermAggregate&); // disallow copy constructor 447 TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator 448 TIntermSequence sequence; 449 TString name; 450 bool userDefined; // used for user defined function names 451 452 bool optimize; 453 bool debug; 454 TPragmaTable *pragmaTable; 455 }; 456 457 // 458 // For if tests. Simplified since there is no switch statement. 459 // 460 class TIntermSelection : public TIntermTyped { 461 public: TIntermSelection(TIntermTyped * cond,TIntermNode * trueB,TIntermNode * falseB)462 TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) : 463 TIntermTyped(TType(EbtVoid, EbpUndefined)), condition(cond), trueBlock(trueB), falseBlock(falseB) {} TIntermSelection(TIntermTyped * cond,TIntermNode * trueB,TIntermNode * falseB,const TType & type)464 TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) : 465 TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB) {} 466 467 virtual void traverse(TIntermTraverser*); 468 usesTernaryOperator()469 bool usesTernaryOperator() const { return getBasicType() != EbtVoid; } getCondition()470 TIntermNode* getCondition() const { return condition; } getTrueBlock()471 TIntermNode* getTrueBlock() const { return trueBlock; } getFalseBlock()472 TIntermNode* getFalseBlock() const { return falseBlock; } getAsSelectionNode()473 TIntermSelection* getAsSelectionNode() { return this; } 474 475 protected: 476 TIntermTyped* condition; 477 TIntermNode* trueBlock; 478 TIntermNode* falseBlock; 479 }; 480 481 enum Visit 482 { 483 PreVisit, 484 InVisit, 485 PostVisit 486 }; 487 488 // 489 // For traversing the tree. User should derive from this, 490 // put their traversal specific data in it, and then pass 491 // it to a Traverse method. 492 // 493 // When using this, just fill in the methods for nodes you want visited. 494 // Return false from a pre-visit to skip visiting that node's subtree. 495 // 496 class TIntermTraverser 497 { 498 public: POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)499 POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) 500 501 TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) : 502 preVisit(preVisit), 503 inVisit(inVisit), 504 postVisit(postVisit), 505 rightToLeft(rightToLeft), 506 depth(0) {} 507 visitSymbol(TIntermSymbol *)508 virtual void visitSymbol(TIntermSymbol*) {} visitConstantUnion(TIntermConstantUnion *)509 virtual void visitConstantUnion(TIntermConstantUnion*) {} visitBinary(Visit visit,TIntermBinary *)510 virtual bool visitBinary(Visit visit, TIntermBinary*) {return true;} visitUnary(Visit visit,TIntermUnary *)511 virtual bool visitUnary(Visit visit, TIntermUnary*) {return true;} visitSelection(Visit visit,TIntermSelection *)512 virtual bool visitSelection(Visit visit, TIntermSelection*) {return true;} visitAggregate(Visit visit,TIntermAggregate *)513 virtual bool visitAggregate(Visit visit, TIntermAggregate*) {return true;} visitLoop(Visit visit,TIntermLoop *)514 virtual bool visitLoop(Visit visit, TIntermLoop*) {return true;} visitBranch(Visit visit,TIntermBranch *)515 virtual bool visitBranch(Visit visit, TIntermBranch*) {return true;} 516 incrementDepth()517 void incrementDepth() {depth++;} decrementDepth()518 void decrementDepth() {depth--;} 519 520 const bool preVisit; 521 const bool inVisit; 522 const bool postVisit; 523 const bool rightToLeft; 524 525 protected: 526 int depth; 527 }; 528 529 #endif // __INTERMEDIATE_H 530