2 //Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
3 //Copyright (C) 2012-2013 LunarG, Inc.
7 //Redistribution and use in source and binary forms, with or without
8 //modification, are permitted provided that the following conditions
11 // Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
14 // Redistributions in binary form must reproduce the above
15 // copyright notice, this list of conditions and the following
16 // disclaimer in the documentation and/or other materials provided
17 // with the distribution.
19 // Neither the name of 3Dlabs Inc. Ltd. nor the names of its
20 // contributors may be used to endorse or promote products derived
21 // from this software without specific prior written permission.
23 //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 //"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 //LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 //FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27 //COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28 //INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 //BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 //LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31 //CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 //LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33 //ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 //POSSIBILITY OF SUCH DAMAGE.
38 // Definition of the in-memory high-level intermediate representation
39 // of shaders. This is a tree that parser creates.
41 // Nodes in the tree are defined as a hierarchy of classes derived from
42 // TIntermNode. Each is a node in a tree. There is no preset branching factor;
43 // each node can have it's own type of list of children.
46 #ifndef __INTERMEDIATE_H
47 #define __INTERMEDIATE_H
49 #include "../Include/Common.h"
50 #include "../Include/Types.h"
51 #include "../Include/ConstantUnion.h"
56 // Operators used by the high-level (parse tree) representation.
59 EOpNull, // if in a node, should only mean a node is still being built
60 EOpSequence, // denotes a list of statements, or parameters, etc.
61 EOpLinkerObjects, // for aggregate node of objects the linker may need, if not reference by the rest of the AST
63 EOpFunction, // For function definition
64 EOpParameters, // an aggregate listing the parameters to a function
125 EOpVectorTimesScalar,
126 EOpVectorTimesMatrix,
127 EOpMatrixTimesVector,
128 EOpMatrixTimesScalar,
136 EOpIndexDirectStruct,
143 // Built-in functions potentially mapped to operators
208 EOpDPdx, // Fragment only
209 EOpDPdy, // Fragment only
210 EOpFwidth, // Fragment only
211 EOpDPdxFine, // Fragment only
212 EOpDPdyFine, // Fragment only
213 EOpFwidthFine, // Fragment only
214 EOpDPdxCoarse, // Fragment only
215 EOpDPdyCoarse, // Fragment only
216 EOpFwidthCoarse, // Fragment only
218 EOpMatrixTimesMatrix,
224 EOpEmitVertex, // geometry only
225 EOpEndPrimitive, // geometry only
226 EOpEmitStreamVertex, // geometry only
227 EOpEndStreamPrimitive, // geometry only
231 EOpMemoryBarrierAtomicCounter,
232 EOpMemoryBarrierBuffer,
233 EOpMemoryBarrierImage,
234 EOpMemoryBarrierShared, // compute only
235 EOpGroupMemoryBarrier, // compute only
237 EOpAtomicAdd, // TODO: AST functionality: hook these up
253 EOpKill, // Fragment only
264 EOpConstructGuardStart,
265 EOpConstructInt, // these first scalar forms also identify what implicit conversion is needed
304 EOpConstructGuardEnd,
314 EOpVectorTimesMatrixAssign,
315 EOpVectorTimesScalarAssign,
316 EOpMatrixTimesScalarAssign,
317 EOpMatrixTimesMatrixAssign,
321 EOpInclusiveOrAssign,
322 EOpExclusiveOrAssign,
330 EOpArrayLength, // "Array" distinguishes from length(v) built-in function, but it applies to vectors and matrices as well.
333 class TIntermTraverser;
334 class TIntermOperator;
335 class TIntermAggregate;
338 class TIntermConstantUnion;
339 class TIntermSelection;
346 } // end namespace glslang
349 // Base class for the tree nodes
351 // (Put outside the glslang namespace, as it's used as part of the external interface.)
355 POOL_ALLOCATOR_NEW_DELETE(glslang::GetThreadPoolAllocator())
357 TIntermNode() { loc.line = 0; loc.string = 0; }
358 virtual glslang::TSourceLoc getLoc() const { return loc; }
359 virtual void setLoc(glslang::TSourceLoc l) { loc = l; }
360 virtual void traverse(glslang::TIntermTraverser*) = 0;
361 virtual glslang::TIntermTyped* getAsTyped() { return 0; }
362 virtual glslang::TIntermOperator* getAsOperator() { return 0; }
363 virtual glslang::TIntermConstantUnion* getAsConstantUnion() { return 0; }
364 virtual glslang::TIntermAggregate* getAsAggregate() { return 0; }
365 virtual glslang::TIntermUnary* getAsUnaryNode() { return 0; }
366 virtual glslang::TIntermBinary* getAsBinaryNode() { return 0; }
367 virtual glslang::TIntermSelection* getAsSelectionNode() { return 0; }
368 virtual glslang::TIntermSwitch* getAsSwitchNode() { return 0; }
369 virtual glslang::TIntermMethod* getAsMethodNode() { return 0; }
370 virtual glslang::TIntermSymbol* getAsSymbolNode() { return 0; }
371 virtual glslang::TIntermBranch* getAsBranchNode() { return 0; }
373 virtual const glslang::TIntermTyped* getAsTyped() const { return 0; }
374 virtual const glslang::TIntermOperator* getAsOperator() const { return 0; }
375 virtual const glslang::TIntermConstantUnion* getAsConstantUnion() const { return 0; }
376 virtual const glslang::TIntermAggregate* getAsAggregate() const { return 0; }
377 virtual const glslang::TIntermUnary* getAsUnaryNode() const { return 0; }
378 virtual const glslang::TIntermBinary* getAsBinaryNode() const { return 0; }
379 virtual const glslang::TIntermSelection* getAsSelectionNode() const { return 0; }
380 virtual const glslang::TIntermSwitch* getAsSwitchNode() const { return 0; }
381 virtual const glslang::TIntermMethod* getAsMethodNode() const { return 0; }
382 virtual const glslang::TIntermSymbol* getAsSymbolNode() const { return 0; }
383 virtual const glslang::TIntermBranch* getAsBranchNode() const { return 0; }
384 virtual ~TIntermNode() { }
386 glslang::TSourceLoc loc;
392 // This is just to help yacc.
394 struct TIntermNodePair {
400 // Intermediate class for nodes that have a type.
402 class TIntermTyped : public TIntermNode {
404 TIntermTyped(const TType& t) { type.shallowCopy(t); }
405 virtual TIntermTyped* getAsTyped() { return this; }
406 virtual const TIntermTyped* getAsTyped() const { return this; }
407 virtual void setType(const TType& t) { type.shallowCopy(t); }
408 virtual const TType& getType() const { return type; }
409 virtual TType& getWritableType() { return type; }
411 virtual TBasicType getBasicType() const { return type.getBasicType(); }
412 virtual TQualifier& getQualifier() { return type.getQualifier(); }
413 virtual const TQualifier& getQualifier() const { return type.getQualifier(); }
414 virtual void propagatePrecision(TPrecisionQualifier);
415 virtual int getVectorSize() const { return type.getVectorSize(); }
416 virtual int getMatrixCols() const { return type.getMatrixCols(); }
417 virtual int getMatrixRows() const { return type.getMatrixRows(); }
418 virtual bool isMatrix() const { return type.isMatrix(); }
419 virtual bool isArray() const { return type.isArray(); }
420 virtual bool isVector() const { return type.isVector(); }
421 virtual bool isScalar() const { return type.isScalar(); }
422 virtual bool isStruct() const { return type.isStruct(); }
423 TString getCompleteString() const { return type.getCompleteString(); }
430 // Handle for, do-while, and while loops.
432 class TIntermLoop : public TIntermNode {
434 TIntermLoop(TIntermNode* aBody, TIntermTyped* aTest, TIntermTyped* aTerminal, bool testFirst) :
439 virtual void traverse(TIntermTraverser*);
440 TIntermNode* getBody() { return body; }
441 TIntermTyped* getTest() { return test; }
442 TIntermTyped* getTerminal() { return terminal; }
443 bool testFirst() { return first; }
445 TIntermNode* body; // code to loop over
446 TIntermTyped* test; // exit condition associated with loop, could be 0 for 'for' loops
447 TIntermTyped* terminal; // exists for for-loops
448 bool first; // true for while and for, not for do-while
452 // Handle case, break, continue, return, and kill.
454 class TIntermBranch : public TIntermNode {
456 TIntermBranch(TOperator op, TIntermTyped* e) :
459 virtual TIntermBranch* getAsBranchNode() { return this; }
460 virtual const TIntermBranch* getAsBranchNode() const { return this; }
461 virtual void traverse(TIntermTraverser*);
462 TOperator getFlowOp() { return flowOp; }
463 TIntermTyped* getExpression() { return expression; }
466 TIntermTyped* expression;
470 // Represent method names before seeing their calling signature
471 // or resolving them to operations. Just an expression as the base object
472 // and a textural name.
474 class TIntermMethod : public TIntermTyped {
476 TIntermMethod(TIntermTyped* o, const TType& t, const TString& m) : TIntermTyped(t), object(o), method(m) { }
477 virtual TIntermMethod* getAsMethodNode() { return this; }
478 virtual const TIntermMethod* getAsMethodNode() const { return this; }
479 virtual const TString& getMethodName() const { return method; }
480 virtual TIntermTyped* getObject() const { return object; }
481 virtual void traverse(TIntermTraverser*);
483 TIntermTyped* object;
488 // Nodes that correspond to symbols or constants in the source code.
490 class TIntermSymbol : public TIntermTyped {
492 // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. If sym comes from
493 // per process threadPoolAllocator, then it causes increased memory usage per compile
494 // it is essential to use "symbol = sym" to assign to symbol
495 TIntermSymbol(int i, const TString& n, const TType& t) :
496 TIntermTyped(t), id(i) { name = n;}
497 virtual int getId() const { return id; }
498 virtual const TString& getName() const { return name; }
499 virtual void traverse(TIntermTraverser*);
500 virtual TIntermSymbol* getAsSymbolNode() { return this; }
501 virtual const TIntermSymbol* getAsSymbolNode() const { return this; }
502 void setConstArray(const TConstUnionArray& c) { unionArray = c; }
503 const TConstUnionArray& getConstArray() const { return unionArray; }
507 TConstUnionArray unionArray;
510 class TIntermConstantUnion : public TIntermTyped {
512 TIntermConstantUnion(const TConstUnionArray& ua, const TType& t) : TIntermTyped(t), unionArray(ua), literal(false) { }
513 const TConstUnionArray& getConstArray() const { return unionArray; }
514 virtual TIntermConstantUnion* getAsConstantUnion() { return this; }
515 virtual const TIntermConstantUnion* getAsConstantUnion() const { return this; }
516 virtual void traverse(TIntermTraverser*);
517 virtual TIntermTyped* fold(TOperator, const TIntermTyped*) const;
518 virtual TIntermTyped* fold(TOperator, const TType&) const;
519 void setLiteral() { literal = true; }
520 void setExpression() { literal = false; }
521 bool isLiteral() const { return literal; }
523 const TConstUnionArray unionArray;
524 bool literal; // true if node represents a literal in the source code
528 // Intermediate class for node types that hold operators.
530 class TIntermOperator : public TIntermTyped {
532 virtual TIntermOperator* getAsOperator() { return this; }
533 virtual const TIntermOperator* getAsOperator() const { return this; }
534 TOperator getOp() { return op; }
535 bool modifiesState() const;
536 bool isConstructor() const;
537 virtual bool promote() { return true; }
539 TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat)), op(o) {}
540 TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o) {}
545 // Nodes for all the basic binary math operators.
547 class TIntermBinary : public TIntermOperator {
549 TIntermBinary(TOperator o) : TIntermOperator(o) {}
550 virtual void traverse(TIntermTraverser*);
551 virtual void setLeft(TIntermTyped* n) { left = n; }
552 virtual void setRight(TIntermTyped* n) { right = n; }
553 virtual TIntermTyped* getLeft() const { return left; }
554 virtual TIntermTyped* getRight() const { return right; }
555 virtual TIntermBinary* getAsBinaryNode() { return this; }
556 virtual const TIntermBinary* getAsBinaryNode() const { return this; }
557 virtual bool promote();
558 virtual void updatePrecision();
565 // Nodes for unary math operators.
567 class TIntermUnary : public TIntermOperator {
569 TIntermUnary(TOperator o, TType& t) : TIntermOperator(o, t), operand(0) {}
570 TIntermUnary(TOperator o) : TIntermOperator(o), operand(0) {}
571 virtual void traverse(TIntermTraverser*);
572 virtual void setOperand(TIntermTyped* o) { operand = o; }
573 virtual TIntermTyped* getOperand() { return operand; }
574 virtual TIntermUnary* getAsUnaryNode() { return this; }
575 virtual const TIntermUnary* getAsUnaryNode() const { return this; }
576 virtual bool promote();
577 virtual void updatePrecision();
579 TIntermTyped* operand;
582 typedef TVector<TIntermNode*> TIntermSequence;
583 typedef TVector<int> TQualifierList;
585 // Nodes that operate on an arbitrary sized set of children.
587 class TIntermAggregate : public TIntermOperator {
589 TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), pragmaTable(0) { }
590 TIntermAggregate(TOperator o) : TIntermOperator(o), pragmaTable(0) { }
591 ~TIntermAggregate() { delete pragmaTable; }
592 virtual TIntermAggregate* getAsAggregate() { return this; }
593 virtual const TIntermAggregate* getAsAggregate() const { return this; }
594 virtual void setOperator(TOperator o) { op = o; }
595 virtual TIntermSequence& getSequence() { return sequence; }
596 virtual const TIntermSequence& getSequence() const { return sequence; }
597 virtual void setName(const TString& n) { name = n; }
598 virtual const TString& getName() const { return name; }
599 virtual void traverse(TIntermTraverser*);
600 virtual void setUserDefined() { userDefined = true; }
601 virtual bool isUserDefined() { return userDefined; }
602 virtual TQualifierList& getQualifierList() { return qualifier; }
603 virtual const TQualifierList& getQualifierList() const { return qualifier; }
604 void setOptimize(bool o) { optimize = o; }
605 void setDebug(bool d) { debug = d; }
606 bool getOptimize() { return optimize; }
607 bool getDebug() { return debug; }
608 void addToPragmaTable(const TPragmaTable& pTable);
609 const TPragmaTable& getPragmaTable() const { return *pragmaTable; }
611 TIntermAggregate(const TIntermAggregate&); // disallow copy constructor
612 TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator
613 TIntermSequence sequence;
614 TQualifierList qualifier;
616 bool userDefined; // used for user defined function names
619 TPragmaTable* pragmaTable;
625 class TIntermSelection : public TIntermTyped {
627 TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) :
628 TIntermTyped(TType(EbtVoid)), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
629 TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) :
630 TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
631 virtual void traverse(TIntermTraverser*);
632 virtual TIntermTyped* getCondition() const { return condition; }
633 virtual TIntermNode* getTrueBlock() const { return trueBlock; }
634 virtual TIntermNode* getFalseBlock() const { return falseBlock; }
635 virtual TIntermSelection* getAsSelectionNode() { return this; }
636 virtual const TIntermSelection* getAsSelectionNode() const { return this; }
638 TIntermTyped* condition;
639 TIntermNode* trueBlock;
640 TIntermNode* falseBlock;
644 // For switch statements. Designed use is that a switch will have sequence of nodes
645 // that are either case/default nodes or a *single* node that represents all the code
646 // in between (if any) consecutive case/defaults. So, a traversal need only deal with
647 // 0 or 1 nodes per case/default statement.
649 class TIntermSwitch : public TIntermNode {
651 TIntermSwitch(TIntermTyped* cond, TIntermAggregate* b) : condition(cond), body(b) { }
652 virtual void traverse(TIntermTraverser*);
653 virtual TIntermNode* getCondition() const { return condition; }
654 virtual TIntermAggregate* getBody() const { return body; }
655 virtual TIntermSwitch* getAsSwitchNode() { return this; }
656 virtual const TIntermSwitch* getAsSwitchNode() const { return this; }
658 TIntermTyped* condition;
659 TIntermAggregate* body;
670 // For traversing the tree. User should derive from this,
671 // put their traversal specific data in it, and then pass
672 // it to a Traverse method.
674 // When using this, just fill in the methods for nodes you want visited.
675 // Return false from a pre-visit to skip visiting that node's subtree.
677 // Explicitly set postVisit to true if you want post visiting, otherwise,
678 // filled in methods will only be called at pre-visit time (before processing
679 // the subtree). Similary for inVisit for in-order visiting of nodes with
680 // multiple children.
682 // If you only want post-visits, explicitly turn off preVisit (and inVisit)
683 // and turn on postVisit.
685 class TIntermTraverser {
687 POOL_ALLOCATOR_NEW_DELETE(glslang::GetThreadPoolAllocator())
688 TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) :
691 postVisit(postVisit),
692 rightToLeft(rightToLeft),
695 virtual ~TIntermTraverser() { }
697 virtual void visitSymbol(TIntermSymbol*) { }
698 virtual void visitConstantUnion(TIntermConstantUnion*) { }
699 virtual bool visitBinary(TVisit, TIntermBinary*) { return true; }
700 virtual bool visitUnary(TVisit, TIntermUnary*) { return true; }
701 virtual bool visitSelection(TVisit, TIntermSelection*) { return true; }
702 virtual bool visitAggregate(TVisit, TIntermAggregate*) { return true; }
703 virtual bool visitLoop(TVisit, TIntermLoop*) { return true; }
704 virtual bool visitBranch(TVisit, TIntermBranch*) { return true; }
705 virtual bool visitSwitch(TVisit, TIntermSwitch*) { return true; }
707 int getMaxDepth() const { return maxDepth; }
709 void incrementDepth(TIntermNode *current)
712 maxDepth = std::max(maxDepth, depth);
713 path.push_back(current);
716 void decrementDepth()
722 TIntermNode *getParentNode()
724 return path.size() == 0 ? NULL : path.back();
729 const bool postVisit;
730 const bool rightToLeft;
733 TIntermTraverser& operator=(TIntermTraverser&);
738 // All the nodes from root to the current node's parent during traversing.
739 TVector<TIntermNode *> path;
742 } // end namespace glslang
744 #endif // __INTERMEDIATE_H