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.
8 // Definition of the in-memory high-level intermediate representation
9 // of shaders. This is a tree that parser creates.
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.
16 #ifndef __INTERMEDIATE_H
17 #define __INTERMEDIATE_H
19 #include "compiler/Common.h"
20 #include "compiler/Types.h"
21 #include "compiler/ConstantUnion.h"
24 // Operators used by the high-level (parse tree) representation.
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.
30 EOpFunction, // For function definition
31 EOpParameters, // an aggregate listing the parameters to a function
90 // Built-in functions potentially mapped to operators
132 EOpDFdx, // Fragment only, OES_standard_derivatives extension
133 EOpDFdy, // Fragment only, OES_standard_derivatives extension
134 EOpFwidth, // Fragment only, OES_standard_derivatives extension
136 EOpMatrixTimesMatrix,
145 EOpKill, // Fragment only
180 EOpVectorTimesMatrixAssign,
181 EOpVectorTimesScalarAssign,
182 EOpMatrixTimesScalarAssign,
183 EOpMatrixTimesMatrixAssign,
187 extern const char* getOperatorString(TOperator op);
189 class TIntermTraverser;
190 class TIntermAggregate;
193 class TIntermConstantUnion;
194 class TIntermSelection;
201 // Base class for the tree nodes
205 POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
207 TIntermNode() : line(0) {}
209 TSourceLoc getLine() const { return line; }
210 void setLine(TSourceLoc l) { line = l; }
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() { }
228 // This is just to help yacc.
230 struct TIntermNodePair {
236 // Intermediate class for nodes that have a type.
238 class TIntermTyped : public TIntermNode {
240 TIntermTyped(const TType& t) : type(t) { }
241 virtual TIntermTyped* getAsTyped() { return this; }
243 void setType(const TType& t) { type = t; }
244 const TType& getType() const { return type; }
245 TType* getTypePointer() { return &type; }
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(); }
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(); }
265 // Handle for, do-while, and while loops.
273 class TIntermLoop : public TIntermNode {
275 TIntermLoop(TLoopType aType,
276 TIntermNode *aInit, TIntermTyped* aCond, TIntermTyped* aExpr,
277 TIntermNode* aBody) :
283 unrollFlag(false) { }
285 virtual TIntermLoop* getAsLoopNode() { return this; }
286 virtual void traverse(TIntermTraverser*);
288 TLoopType getType() const { return type; }
289 TIntermNode* getInit() { return init; }
290 TIntermTyped* getCondition() { return cond; }
291 TIntermTyped* getExpression() { return expr; }
292 TIntermNode* getBody() { return body; }
294 void setUnrollFlag(bool flag) { unrollFlag = flag; }
295 bool getUnrollFlag() { return unrollFlag; }
299 TIntermNode* init; // for-loop initialization
300 TIntermTyped* cond; // loop exit condition
301 TIntermTyped* expr; // for-loop expression
302 TIntermNode* body; // loop body
304 bool unrollFlag; // Whether the loop should be unrolled or not.
308 // Handle break, continue, return, and kill.
310 class TIntermBranch : public TIntermNode {
312 TIntermBranch(TOperator op, TIntermTyped* e) :
316 virtual void traverse(TIntermTraverser*);
318 TOperator getFlowOp() { return flowOp; }
319 TIntermTyped* getExpression() { return expression; }
323 TIntermTyped* expression; // non-zero except for "return exp;" statements
327 // Nodes that correspond to symbols or constants in the source code.
329 class TIntermSymbol : public TIntermTyped {
331 // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. If sym comes from
332 // per process globalpoolallocator, then it causes increased memory usage per compile
333 // it is essential to use "symbol = sym" to assign to symbol
334 TIntermSymbol(int i, const TString& sym, const TType& t) :
335 TIntermTyped(t), id(i) { symbol = sym; originalSymbol = sym; }
337 int getId() const { return id; }
338 const TString& getSymbol() const { return symbol; }
340 void setId(int newId) { id = newId; }
341 void setSymbol(const TString& sym) { symbol = sym; }
343 const TString& getOriginalSymbol() const { return originalSymbol; }
345 virtual void traverse(TIntermTraverser*);
346 virtual TIntermSymbol* getAsSymbolNode() { return this; }
351 TString originalSymbol;
354 class TIntermConstantUnion : public TIntermTyped {
356 TIntermConstantUnion(ConstantUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer) { }
358 ConstantUnion* getUnionArrayPointer() const { return unionArrayPointer; }
359 void setUnionArrayPointer(ConstantUnion *c) { unionArrayPointer = c; }
361 virtual TIntermConstantUnion* getAsConstantUnion() { return this; }
362 virtual void traverse(TIntermTraverser*);
364 TIntermTyped* fold(TOperator, TIntermTyped*, TInfoSink&);
367 ConstantUnion *unionArrayPointer;
371 // Intermediate class for node types that hold operators.
373 class TIntermOperator : public TIntermTyped {
375 TOperator getOp() const { return op; }
376 void setOp(TOperator o) { op = o; }
378 bool modifiesState() const;
379 bool isConstructor() const;
382 TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat, EbpUndefined)), op(o) {}
383 TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o) {}
388 // Nodes for all the basic binary math operators.
390 class TIntermBinary : public TIntermOperator {
392 TIntermBinary(TOperator o) : TIntermOperator(o) {}
394 virtual TIntermBinary* getAsBinaryNode() { return this; }
395 virtual void traverse(TIntermTraverser*);
397 void setLeft(TIntermTyped* n) { left = n; }
398 void setRight(TIntermTyped* n) { right = n; }
399 TIntermTyped* getLeft() const { return left; }
400 TIntermTyped* getRight() const { return right; }
401 bool promote(TInfoSink&);
409 // Nodes for unary math operators.
411 class TIntermUnary : public TIntermOperator {
413 TIntermUnary(TOperator o, TType& t) : TIntermOperator(o, t), operand(0) {}
414 TIntermUnary(TOperator o) : TIntermOperator(o), operand(0) {}
416 virtual void traverse(TIntermTraverser*);
417 virtual TIntermUnary* getAsUnaryNode() { return this; }
419 void setOperand(TIntermTyped* o) { operand = o; }
420 TIntermTyped* getOperand() { return operand; }
421 bool promote(TInfoSink&);
424 TIntermTyped* operand;
427 typedef TVector<TIntermNode*> TIntermSequence;
428 typedef TVector<int> TQualifierList;
429 typedef TMap<TString, TString> TPragmaTable;
431 // Nodes that operate on an arbitrary sized set of children.
433 class TIntermAggregate : public TIntermOperator {
435 TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), pragmaTable(0), endLine(0) { }
436 TIntermAggregate(TOperator o) : TIntermOperator(o), pragmaTable(0) { }
437 ~TIntermAggregate() { delete pragmaTable; }
439 virtual TIntermAggregate* getAsAggregate() { return this; }
440 virtual void traverse(TIntermTraverser*);
442 TIntermSequence& getSequence() { return sequence; }
444 void setName(const TString& n) { name = n; }
445 const TString& getName() const { return name; }
447 void setUserDefined() { userDefined = true; }
448 bool isUserDefined() { return userDefined; }
450 void setOptimize(bool o) { optimize = o; }
451 bool getOptimize() { return optimize; }
452 void setDebug(bool d) { debug = d; }
453 bool getDebug() { return debug; }
454 void addToPragmaTable(const TPragmaTable& pTable);
455 const TPragmaTable& getPragmaTable() const { return *pragmaTable; }
456 void setEndLine(TSourceLoc line) { endLine = line; }
457 TSourceLoc getEndLine() const { return endLine; }
460 TIntermAggregate(const TIntermAggregate&); // disallow copy constructor
461 TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator
462 TIntermSequence sequence;
464 bool userDefined; // used for user defined function names
468 TPragmaTable *pragmaTable;
473 // For if tests. Simplified since there is no switch statement.
475 class TIntermSelection : public TIntermTyped {
477 TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) :
478 TIntermTyped(TType(EbtVoid, EbpUndefined)), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
479 TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) :
480 TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
482 virtual void traverse(TIntermTraverser*);
484 bool usesTernaryOperator() const { return getBasicType() != EbtVoid; }
485 TIntermNode* getCondition() const { return condition; }
486 TIntermNode* getTrueBlock() const { return trueBlock; }
487 TIntermNode* getFalseBlock() const { return falseBlock; }
488 TIntermSelection* getAsSelectionNode() { return this; }
491 TIntermTyped* condition;
492 TIntermNode* trueBlock;
493 TIntermNode* falseBlock;
504 // For traversing the tree. User should derive from this,
505 // put their traversal specific data in it, and then pass
506 // it to a Traverse method.
508 // When using this, just fill in the methods for nodes you want visited.
509 // Return false from a pre-visit to skip visiting that node's subtree.
511 class TIntermTraverser
514 POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
516 TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) :
519 postVisit(postVisit),
520 rightToLeft(rightToLeft),
523 virtual void visitSymbol(TIntermSymbol*) {}
524 virtual void visitConstantUnion(TIntermConstantUnion*) {}
525 virtual bool visitBinary(Visit visit, TIntermBinary*) {return true;}
526 virtual bool visitUnary(Visit visit, TIntermUnary*) {return true;}
527 virtual bool visitSelection(Visit visit, TIntermSelection*) {return true;}
528 virtual bool visitAggregate(Visit visit, TIntermAggregate*) {return true;}
529 virtual bool visitLoop(Visit visit, TIntermLoop*) {return true;}
530 virtual bool visitBranch(Visit visit, TIntermBranch*) {return true;}
532 void incrementDepth() {depth++;}
533 void decrementDepth() {depth--;}
537 const bool postVisit;
538 const bool rightToLeft;
544 #endif // __INTERMEDIATE_H