Home | History | Annotate | Download | only in compiler
      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:
    205     POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
    206 
    207     TIntermNode() : line(0) {}
    208 
    209     TSourceLoc getLine() const { return line; }
    210     void setLine(TSourceLoc l) { line = l; }
    211 
    212     virtual void traverse(TIntermTraverser*) = 0;
    213     virtual TIntermTyped* getAsTyped() { return 0; }
    214     virtual TIntermConstantUnion* getAsConstantUnion() { return 0; }
    215     virtual TIntermAggregate* getAsAggregate() { return 0; }
    216     virtual TIntermBinary* getAsBinaryNode() { return 0; }
    217     virtual TIntermUnary* getAsUnaryNode() { return 0; }
    218     virtual TIntermSelection* getAsSelectionNode() { return 0; }
    219     virtual TIntermSymbol* getAsSymbolNode() { return 0; }
    220     virtual TIntermLoop* getAsLoopNode() { return 0; }
    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:
    240     TIntermTyped(const TType& t) : type(t)  { }
    241     virtual TIntermTyped* getAsTyped() { return this; }
    242 
    243     void setType(const TType& t) { type = t; }
    244     const TType& getType() const { return type; }
    245     TType* getTypePointer() { return &type; }
    246 
    247     TBasicType getBasicType() const { return type.getBasicType(); }
    248     TQualifier getQualifier() const { return type.getQualifier(); }
    249     TPrecision getPrecision() const { return type.getPrecision(); }
    250     int getNominalSize() const { return type.getNominalSize(); }
    251 
    252     bool isMatrix() const { return type.isMatrix(); }
    253     bool isArray()  const { return type.isArray(); }
    254     bool isVector() const { return type.isVector(); }
    255     bool isScalar() const { return type.isScalar(); }
    256     const char* getBasicString() const { return type.getBasicString(); }
    257     const char* getQualifierString() const { return type.getQualifierString(); }
    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:
    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 
    284     virtual TIntermLoop* getAsLoopNode() { return this; }
    285     virtual void traverse(TIntermTraverser*);
    286 
    287     TLoopType getType() const { return type; }
    288     TIntermNode* getInit() { return init; }
    289     TIntermTyped* getCondition() { return cond; }
    290     TIntermTyped* getExpression() { return expr; }
    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:
    306     TIntermBranch(TOperator op, TIntermTyped* e) :
    307             flowOp(op),
    308             expression(e) { }
    309 
    310     virtual void traverse(TIntermTraverser*);
    311 
    312     TOperator getFlowOp() { return flowOp; }
    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
    328     TIntermSymbol(int i, const TString& sym, const TType& t) :
    329             TIntermTyped(t), id(i)  { symbol = sym;}
    330 
    331     int getId() const { return id; }
    332     const TString& getSymbol() const { return symbol; }
    333 
    334     virtual void traverse(TIntermTraverser*);
    335     virtual TIntermSymbol* getAsSymbolNode() { return this; }
    336 
    337 protected:
    338     int id;
    339     TString symbol;
    340 };
    341 
    342 class TIntermConstantUnion : public TIntermTyped {
    343 public:
    344     TIntermConstantUnion(ConstantUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer) { }
    345 
    346     ConstantUnion* getUnionArrayPointer() const { return unionArrayPointer; }
    347     void setUnionArrayPointer(ConstantUnion *c) { unionArrayPointer = c; }
    348 
    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:
    363     TOperator getOp() const { return op; }
    364     void setOp(TOperator o) { op = o; }
    365 
    366     bool modifiesState() const;
    367     bool isConstructor() const;
    368 
    369 protected:
    370     TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat, EbpUndefined)), op(o) {}
    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:
    380     TIntermBinary(TOperator o) : TIntermOperator(o) {}
    381 
    382     virtual TIntermBinary* getAsBinaryNode() { return this; }
    383     virtual void traverse(TIntermTraverser*);
    384 
    385     void setLeft(TIntermTyped* n) { left = n; }
    386     void setRight(TIntermTyped* n) { right = n; }
    387     TIntermTyped* getLeft() const { return left; }
    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:
    401     TIntermUnary(TOperator o, TType& t) : TIntermOperator(o, t), operand(0) {}
    402     TIntermUnary(TOperator o) : TIntermOperator(o), operand(0) {}
    403 
    404     virtual void traverse(TIntermTraverser*);
    405     virtual TIntermUnary* getAsUnaryNode() { return this; }
    406 
    407     void setOperand(TIntermTyped* o) { operand = o; }
    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:
    423     TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), pragmaTable(0) { }
    424     TIntermAggregate(TOperator o) : TIntermOperator(o), pragmaTable(0) { }
    425     ~TIntermAggregate() { delete pragmaTable; }
    426 
    427     virtual TIntermAggregate* getAsAggregate() { return this; }
    428     virtual void traverse(TIntermTraverser*);
    429 
    430     TIntermSequence& getSequence() { return sequence; }
    431 
    432     void setName(const TString& n) { name = n; }
    433     const TString& getName() const { return name; }
    434 
    435     void setUserDefined() { userDefined = true; }
    436     bool isUserDefined() { return userDefined; }
    437 
    438     void setOptimize(bool o) { optimize = o; }
    439     bool getOptimize() { return optimize; }
    440     void setDebug(bool d) { debug = d; }
    441     bool getDebug() { return debug; }
    442     void addToPragmaTable(const TPragmaTable& pTable);
    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:
    462     TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) :
    463             TIntermTyped(TType(EbtVoid, EbpUndefined)), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
    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 
    469     bool usesTernaryOperator() const { return getBasicType() != EbtVoid; }
    470     TIntermNode* getCondition() const { return condition; }
    471     TIntermNode* getTrueBlock() const { return trueBlock; }
    472     TIntermNode* getFalseBlock() const { return falseBlock; }
    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:
    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 
    508     virtual void visitSymbol(TIntermSymbol*) {}
    509     virtual void visitConstantUnion(TIntermConstantUnion*) {}
    510     virtual bool visitBinary(Visit visit, TIntermBinary*) {return true;}
    511     virtual bool visitUnary(Visit visit, TIntermUnary*) {return true;}
    512     virtual bool visitSelection(Visit visit, TIntermSelection*) {return true;}
    513     virtual bool visitAggregate(Visit visit, TIntermAggregate*) {return true;}
    514     virtual bool visitLoop(Visit visit, TIntermLoop*) {return true;}
    515     virtual bool visitBranch(Visit visit, TIntermBranch*) {return true;}
    516 
    517     void incrementDepth() {depth++;}
    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