git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@27715 e7fa87d3-cd2b-0410-9028-fcbf551c1848
743 lines
24 KiB
C++
743 lines
24 KiB
C++
//
|
|
//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
|
//Copyright (C) 2012-2013 LunarG, Inc.
|
|
//
|
|
//All rights reserved.
|
|
//
|
|
//Redistribution and use in source and binary forms, with or without
|
|
//modification, are permitted provided that the following conditions
|
|
//are met:
|
|
//
|
|
// Redistributions of source code must retain the above copyright
|
|
// notice, this list of conditions and the following disclaimer.
|
|
//
|
|
// Redistributions in binary form must reproduce the above
|
|
// copyright notice, this list of conditions and the following
|
|
// disclaimer in the documentation and/or other materials provided
|
|
// with the distribution.
|
|
//
|
|
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
// contributors may be used to endorse or promote products derived
|
|
// from this software without specific prior written permission.
|
|
//
|
|
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
//POSSIBILITY OF SUCH DAMAGE.
|
|
//
|
|
|
|
//
|
|
// Definition of the in-memory high-level intermediate representation
|
|
// of shaders. This is a tree that parser creates.
|
|
//
|
|
// Nodes in the tree are defined as a hierarchy of classes derived from
|
|
// TIntermNode. Each is a node in a tree. There is no preset branching factor;
|
|
// each node can have it's own type of list of children.
|
|
//
|
|
|
|
#ifndef __INTERMEDIATE_H
|
|
#define __INTERMEDIATE_H
|
|
|
|
#include "../Include/Common.h"
|
|
#include "../Include/Types.h"
|
|
#include "../Include/ConstantUnion.h"
|
|
|
|
namespace glslang {
|
|
|
|
//
|
|
// Operators used by the high-level (parse tree) representation.
|
|
//
|
|
enum TOperator {
|
|
EOpNull, // if in a node, should only mean a node is still being built
|
|
EOpSequence, // denotes a list of statements, or parameters, etc.
|
|
EOpLinkerObjects, // for aggregate node of objects the linker may need, if not reference by the rest of the AST
|
|
EOpFunctionCall,
|
|
EOpFunction, // For function definition
|
|
EOpParameters, // an aggregate listing the parameters to a function
|
|
|
|
//
|
|
// Unary operators
|
|
//
|
|
|
|
EOpNegative,
|
|
EOpLogicalNot,
|
|
EOpVectorLogicalNot,
|
|
EOpBitwiseNot,
|
|
|
|
EOpPostIncrement,
|
|
EOpPostDecrement,
|
|
EOpPreIncrement,
|
|
EOpPreDecrement,
|
|
|
|
EOpConvIntToBool,
|
|
EOpConvUintToBool,
|
|
EOpConvFloatToBool,
|
|
EOpConvDoubleToBool,
|
|
EOpConvBoolToFloat,
|
|
EOpConvIntToFloat,
|
|
EOpConvUintToFloat,
|
|
EOpConvDoubleToFloat,
|
|
EOpConvUintToInt,
|
|
EOpConvFloatToInt,
|
|
EOpConvBoolToInt,
|
|
EOpConvDoubleToInt,
|
|
EOpConvIntToUint,
|
|
EOpConvFloatToUint,
|
|
EOpConvBoolToUint,
|
|
EOpConvDoubleToUint,
|
|
EOpConvIntToDouble,
|
|
EOpConvUintToDouble,
|
|
EOpConvFloatToDouble,
|
|
EOpConvBoolToDouble,
|
|
|
|
//
|
|
// binary operations
|
|
//
|
|
|
|
EOpAdd,
|
|
EOpSub,
|
|
EOpMul,
|
|
EOpDiv,
|
|
EOpMod,
|
|
EOpRightShift,
|
|
EOpLeftShift,
|
|
EOpAnd,
|
|
EOpInclusiveOr,
|
|
EOpExclusiveOr,
|
|
EOpEqual,
|
|
EOpNotEqual,
|
|
EOpVectorEqual,
|
|
EOpVectorNotEqual,
|
|
EOpLessThan,
|
|
EOpGreaterThan,
|
|
EOpLessThanEqual,
|
|
EOpGreaterThanEqual,
|
|
EOpComma,
|
|
|
|
EOpVectorTimesScalar,
|
|
EOpVectorTimesMatrix,
|
|
EOpMatrixTimesVector,
|
|
EOpMatrixTimesScalar,
|
|
|
|
EOpLogicalOr,
|
|
EOpLogicalXor,
|
|
EOpLogicalAnd,
|
|
|
|
EOpIndexDirect,
|
|
EOpIndexIndirect,
|
|
EOpIndexDirectStruct,
|
|
|
|
EOpVectorSwizzle,
|
|
|
|
EOpMethod,
|
|
|
|
//
|
|
// Built-in functions potentially mapped to operators
|
|
//
|
|
|
|
EOpRadians,
|
|
EOpDegrees,
|
|
EOpSin,
|
|
EOpCos,
|
|
EOpTan,
|
|
EOpAsin,
|
|
EOpAcos,
|
|
EOpAtan,
|
|
EOpSinh,
|
|
EOpCosh,
|
|
EOpTanh,
|
|
EOpAsinh,
|
|
EOpAcosh,
|
|
EOpAtanh,
|
|
|
|
EOpPow,
|
|
EOpExp,
|
|
EOpLog,
|
|
EOpExp2,
|
|
EOpLog2,
|
|
EOpSqrt,
|
|
EOpInverseSqrt,
|
|
|
|
EOpAbs,
|
|
EOpSign,
|
|
EOpFloor,
|
|
EOpTrunc,
|
|
EOpRound,
|
|
EOpRoundEven,
|
|
EOpCeil,
|
|
EOpFract,
|
|
EOpModf,
|
|
EOpMin,
|
|
EOpMax,
|
|
EOpClamp,
|
|
EOpMix,
|
|
EOpStep,
|
|
EOpSmoothStep,
|
|
|
|
EOpIsNan,
|
|
EOpIsInf,
|
|
|
|
EOpFloatBitsToInt,
|
|
EOpFloatBitsToUint,
|
|
EOpIntBitsToFloat,
|
|
EOpUintBitsToFloat,
|
|
EOpPackSnorm2x16,
|
|
EOpUnpackSnorm2x16,
|
|
EOpPackUnorm2x16,
|
|
EOpUnpackUnorm2x16,
|
|
EOpPackHalf2x16,
|
|
EOpUnpackHalf2x16,
|
|
|
|
EOpLength,
|
|
EOpDistance,
|
|
EOpDot,
|
|
EOpCross,
|
|
EOpNormalize,
|
|
EOpFaceForward,
|
|
EOpReflect,
|
|
EOpRefract,
|
|
|
|
EOpDPdx, // Fragment only
|
|
EOpDPdy, // Fragment only
|
|
EOpFwidth, // Fragment only
|
|
EOpDPdxFine, // Fragment only
|
|
EOpDPdyFine, // Fragment only
|
|
EOpFwidthFine, // Fragment only
|
|
EOpDPdxCoarse, // Fragment only
|
|
EOpDPdyCoarse, // Fragment only
|
|
EOpFwidthCoarse, // Fragment only
|
|
|
|
EOpMatrixTimesMatrix,
|
|
EOpOuterProduct,
|
|
EOpDeterminant,
|
|
EOpMatrixInverse,
|
|
EOpTranspose,
|
|
|
|
EOpEmitVertex, // geometry only
|
|
EOpEndPrimitive, // geometry only
|
|
EOpEmitStreamVertex, // geometry only
|
|
EOpEndStreamPrimitive, // geometry only
|
|
|
|
EOpBarrier,
|
|
EOpMemoryBarrier,
|
|
EOpMemoryBarrierAtomicCounter,
|
|
EOpMemoryBarrierBuffer,
|
|
EOpMemoryBarrierImage,
|
|
EOpMemoryBarrierShared, // compute only
|
|
EOpGroupMemoryBarrier, // compute only
|
|
|
|
EOpAtomicAdd, // TODO: AST functionality: hook these up
|
|
EOpAtomicMin,
|
|
EOpAtomicMax,
|
|
EOpAtomicAnd,
|
|
EOpAtomicOr,
|
|
EOpAtomicXor,
|
|
EOpAtomicExchange,
|
|
EOpAtomicCompSwap,
|
|
|
|
EOpAny,
|
|
EOpAll,
|
|
|
|
//
|
|
// Branch
|
|
//
|
|
|
|
EOpKill, // Fragment only
|
|
EOpReturn,
|
|
EOpBreak,
|
|
EOpContinue,
|
|
EOpCase,
|
|
EOpDefault,
|
|
|
|
//
|
|
// Constructors
|
|
//
|
|
|
|
EOpConstructGuardStart,
|
|
EOpConstructInt, // these first scalar forms also identify what implicit conversion is needed
|
|
EOpConstructUint,
|
|
EOpConstructBool,
|
|
EOpConstructFloat,
|
|
EOpConstructDouble,
|
|
EOpConstructVec2,
|
|
EOpConstructVec3,
|
|
EOpConstructVec4,
|
|
EOpConstructDVec2,
|
|
EOpConstructDVec3,
|
|
EOpConstructDVec4,
|
|
EOpConstructBVec2,
|
|
EOpConstructBVec3,
|
|
EOpConstructBVec4,
|
|
EOpConstructIVec2,
|
|
EOpConstructIVec3,
|
|
EOpConstructIVec4,
|
|
EOpConstructUVec2,
|
|
EOpConstructUVec3,
|
|
EOpConstructUVec4,
|
|
EOpConstructMat2x2,
|
|
EOpConstructMat2x3,
|
|
EOpConstructMat2x4,
|
|
EOpConstructMat3x2,
|
|
EOpConstructMat3x3,
|
|
EOpConstructMat3x4,
|
|
EOpConstructMat4x2,
|
|
EOpConstructMat4x3,
|
|
EOpConstructMat4x4,
|
|
EOpConstructDMat2x2,
|
|
EOpConstructDMat2x3,
|
|
EOpConstructDMat2x4,
|
|
EOpConstructDMat3x2,
|
|
EOpConstructDMat3x3,
|
|
EOpConstructDMat3x4,
|
|
EOpConstructDMat4x2,
|
|
EOpConstructDMat4x3,
|
|
EOpConstructDMat4x4,
|
|
EOpConstructStruct,
|
|
EOpConstructGuardEnd,
|
|
|
|
//
|
|
// moves
|
|
//
|
|
|
|
EOpAssign,
|
|
EOpAddAssign,
|
|
EOpSubAssign,
|
|
EOpMulAssign,
|
|
EOpVectorTimesMatrixAssign,
|
|
EOpVectorTimesScalarAssign,
|
|
EOpMatrixTimesScalarAssign,
|
|
EOpMatrixTimesMatrixAssign,
|
|
EOpDivAssign,
|
|
EOpModAssign,
|
|
EOpAndAssign,
|
|
EOpInclusiveOrAssign,
|
|
EOpExclusiveOrAssign,
|
|
EOpLeftShiftAssign,
|
|
EOpRightShiftAssign,
|
|
|
|
//
|
|
// Array operators
|
|
//
|
|
|
|
EOpArrayLength, // "Array" distinguishes from length(v) built-in function, but it applies to vectors and matrices as well.
|
|
};
|
|
|
|
class TIntermTraverser;
|
|
class TIntermOperator;
|
|
class TIntermAggregate;
|
|
class TIntermUnary;
|
|
class TIntermBinary;
|
|
class TIntermConstantUnion;
|
|
class TIntermSelection;
|
|
class TIntermSwitch;
|
|
class TIntermBranch;
|
|
class TIntermTyped;
|
|
class TIntermMethod;
|
|
class TIntermSymbol;
|
|
|
|
} // end namespace glslang
|
|
|
|
//
|
|
// Base class for the tree nodes
|
|
//
|
|
// (Put outside the glslang namespace, as it's used as part of the external interface.)
|
|
//
|
|
class TIntermNode {
|
|
public:
|
|
POOL_ALLOCATOR_NEW_DELETE(glslang::GetThreadPoolAllocator())
|
|
|
|
TIntermNode() { loc.line = 0; loc.string = 0; }
|
|
virtual glslang::TSourceLoc getLoc() const { return loc; }
|
|
virtual void setLoc(glslang::TSourceLoc l) { loc = l; }
|
|
virtual void traverse(glslang::TIntermTraverser*) = 0;
|
|
virtual glslang::TIntermTyped* getAsTyped() { return 0; }
|
|
virtual glslang::TIntermOperator* getAsOperator() { return 0; }
|
|
virtual glslang::TIntermConstantUnion* getAsConstantUnion() { return 0; }
|
|
virtual glslang::TIntermAggregate* getAsAggregate() { return 0; }
|
|
virtual glslang::TIntermUnary* getAsUnaryNode() { return 0; }
|
|
virtual glslang::TIntermBinary* getAsBinaryNode() { return 0; }
|
|
virtual glslang::TIntermSelection* getAsSelectionNode() { return 0; }
|
|
virtual glslang::TIntermSwitch* getAsSwitchNode() { return 0; }
|
|
virtual glslang::TIntermMethod* getAsMethodNode() { return 0; }
|
|
virtual glslang::TIntermSymbol* getAsSymbolNode() { return 0; }
|
|
virtual glslang::TIntermBranch* getAsBranchNode() { return 0; }
|
|
|
|
virtual const glslang::TIntermTyped* getAsTyped() const { return 0; }
|
|
virtual const glslang::TIntermOperator* getAsOperator() const { return 0; }
|
|
virtual const glslang::TIntermConstantUnion* getAsConstantUnion() const { return 0; }
|
|
virtual const glslang::TIntermAggregate* getAsAggregate() const { return 0; }
|
|
virtual const glslang::TIntermUnary* getAsUnaryNode() const { return 0; }
|
|
virtual const glslang::TIntermBinary* getAsBinaryNode() const { return 0; }
|
|
virtual const glslang::TIntermSelection* getAsSelectionNode() const { return 0; }
|
|
virtual const glslang::TIntermSwitch* getAsSwitchNode() const { return 0; }
|
|
virtual const glslang::TIntermMethod* getAsMethodNode() const { return 0; }
|
|
virtual const glslang::TIntermSymbol* getAsSymbolNode() const { return 0; }
|
|
virtual const glslang::TIntermBranch* getAsBranchNode() const { return 0; }
|
|
virtual ~TIntermNode() { }
|
|
protected:
|
|
glslang::TSourceLoc loc;
|
|
};
|
|
|
|
namespace glslang {
|
|
|
|
//
|
|
// This is just to help yacc.
|
|
//
|
|
struct TIntermNodePair {
|
|
TIntermNode* node1;
|
|
TIntermNode* node2;
|
|
};
|
|
|
|
//
|
|
// Intermediate class for nodes that have a type.
|
|
//
|
|
class TIntermTyped : public TIntermNode {
|
|
public:
|
|
TIntermTyped(const TType& t) { type.shallowCopy(t); }
|
|
virtual TIntermTyped* getAsTyped() { return this; }
|
|
virtual const TIntermTyped* getAsTyped() const { return this; }
|
|
virtual void setType(const TType& t) { type.shallowCopy(t); }
|
|
virtual const TType& getType() const { return type; }
|
|
virtual TType& getWritableType() { return type; }
|
|
|
|
virtual TBasicType getBasicType() const { return type.getBasicType(); }
|
|
virtual TQualifier& getQualifier() { return type.getQualifier(); }
|
|
virtual const TQualifier& getQualifier() const { return type.getQualifier(); }
|
|
virtual void propagatePrecision(TPrecisionQualifier);
|
|
virtual int getVectorSize() const { return type.getVectorSize(); }
|
|
virtual int getMatrixCols() const { return type.getMatrixCols(); }
|
|
virtual int getMatrixRows() const { return type.getMatrixRows(); }
|
|
virtual bool isMatrix() const { return type.isMatrix(); }
|
|
virtual bool isArray() const { return type.isArray(); }
|
|
virtual bool isVector() const { return type.isVector(); }
|
|
virtual bool isScalar() const { return type.isScalar(); }
|
|
virtual bool isStruct() const { return type.isStruct(); }
|
|
TString getCompleteString() const { return type.getCompleteString(); }
|
|
|
|
protected:
|
|
TType type;
|
|
};
|
|
|
|
//
|
|
// Handle for, do-while, and while loops.
|
|
//
|
|
class TIntermLoop : public TIntermNode {
|
|
public:
|
|
TIntermLoop(TIntermNode* aBody, TIntermTyped* aTest, TIntermTyped* aTerminal, bool testFirst) :
|
|
body(aBody),
|
|
test(aTest),
|
|
terminal(aTerminal),
|
|
first(testFirst) { }
|
|
virtual void traverse(TIntermTraverser*);
|
|
TIntermNode* getBody() { return body; }
|
|
TIntermTyped* getTest() { return test; }
|
|
TIntermTyped* getTerminal() { return terminal; }
|
|
bool testFirst() { return first; }
|
|
protected:
|
|
TIntermNode* body; // code to loop over
|
|
TIntermTyped* test; // exit condition associated with loop, could be 0 for 'for' loops
|
|
TIntermTyped* terminal; // exists for for-loops
|
|
bool first; // true for while and for, not for do-while
|
|
};
|
|
|
|
//
|
|
// Handle case, break, continue, return, and kill.
|
|
//
|
|
class TIntermBranch : public TIntermNode {
|
|
public:
|
|
TIntermBranch(TOperator op, TIntermTyped* e) :
|
|
flowOp(op),
|
|
expression(e) { }
|
|
virtual TIntermBranch* getAsBranchNode() { return this; }
|
|
virtual const TIntermBranch* getAsBranchNode() const { return this; }
|
|
virtual void traverse(TIntermTraverser*);
|
|
TOperator getFlowOp() { return flowOp; }
|
|
TIntermTyped* getExpression() { return expression; }
|
|
protected:
|
|
TOperator flowOp;
|
|
TIntermTyped* expression;
|
|
};
|
|
|
|
//
|
|
// Represent method names before seeing their calling signature
|
|
// or resolving them to operations. Just an expression as the base object
|
|
// and a textural name.
|
|
//
|
|
class TIntermMethod : public TIntermTyped {
|
|
public:
|
|
TIntermMethod(TIntermTyped* o, const TType& t, const TString& m) : TIntermTyped(t), object(o), method(m) { }
|
|
virtual TIntermMethod* getAsMethodNode() { return this; }
|
|
virtual const TIntermMethod* getAsMethodNode() const { return this; }
|
|
virtual const TString& getMethodName() const { return method; }
|
|
virtual TIntermTyped* getObject() const { return object; }
|
|
virtual void traverse(TIntermTraverser*);
|
|
protected:
|
|
TIntermTyped* object;
|
|
TString method;
|
|
};
|
|
|
|
//
|
|
// Nodes that correspond to symbols or constants in the source code.
|
|
//
|
|
class TIntermSymbol : public TIntermTyped {
|
|
public:
|
|
// if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. If sym comes from
|
|
// per process threadPoolAllocator, then it causes increased memory usage per compile
|
|
// it is essential to use "symbol = sym" to assign to symbol
|
|
TIntermSymbol(int i, const TString& n, const TType& t) :
|
|
TIntermTyped(t), id(i) { name = n;}
|
|
virtual int getId() const { return id; }
|
|
virtual const TString& getName() const { return name; }
|
|
virtual void traverse(TIntermTraverser*);
|
|
virtual TIntermSymbol* getAsSymbolNode() { return this; }
|
|
virtual const TIntermSymbol* getAsSymbolNode() const { return this; }
|
|
void setConstArray(const TConstUnionArray& c) { unionArray = c; }
|
|
const TConstUnionArray& getConstArray() const { return unionArray; }
|
|
protected:
|
|
int id;
|
|
TString name;
|
|
TConstUnionArray unionArray;
|
|
};
|
|
|
|
class TIntermConstantUnion : public TIntermTyped {
|
|
public:
|
|
TIntermConstantUnion(const TConstUnionArray& ua, const TType& t) : TIntermTyped(t), unionArray(ua), literal(false) { }
|
|
const TConstUnionArray& getConstArray() const { return unionArray; }
|
|
virtual TIntermConstantUnion* getAsConstantUnion() { return this; }
|
|
virtual const TIntermConstantUnion* getAsConstantUnion() const { return this; }
|
|
virtual void traverse(TIntermTraverser*);
|
|
virtual TIntermTyped* fold(TOperator, const TIntermTyped*) const;
|
|
virtual TIntermTyped* fold(TOperator, const TType&) const;
|
|
void setLiteral() { literal = true; }
|
|
void setExpression() { literal = false; }
|
|
bool isLiteral() const { return literal; }
|
|
protected:
|
|
const TConstUnionArray unionArray;
|
|
bool literal; // true if node represents a literal in the source code
|
|
};
|
|
|
|
//
|
|
// Intermediate class for node types that hold operators.
|
|
//
|
|
class TIntermOperator : public TIntermTyped {
|
|
public:
|
|
virtual TIntermOperator* getAsOperator() { return this; }
|
|
virtual const TIntermOperator* getAsOperator() const { return this; }
|
|
TOperator getOp() { return op; }
|
|
bool modifiesState() const;
|
|
bool isConstructor() const;
|
|
virtual bool promote() { return true; }
|
|
protected:
|
|
TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat)), op(o) {}
|
|
TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o) {}
|
|
TOperator op;
|
|
};
|
|
|
|
//
|
|
// Nodes for all the basic binary math operators.
|
|
//
|
|
class TIntermBinary : public TIntermOperator {
|
|
public:
|
|
TIntermBinary(TOperator o) : TIntermOperator(o) {}
|
|
virtual void traverse(TIntermTraverser*);
|
|
virtual void setLeft(TIntermTyped* n) { left = n; }
|
|
virtual void setRight(TIntermTyped* n) { right = n; }
|
|
virtual TIntermTyped* getLeft() const { return left; }
|
|
virtual TIntermTyped* getRight() const { return right; }
|
|
virtual TIntermBinary* getAsBinaryNode() { return this; }
|
|
virtual const TIntermBinary* getAsBinaryNode() const { return this; }
|
|
virtual bool promote();
|
|
virtual void updatePrecision();
|
|
protected:
|
|
TIntermTyped* left;
|
|
TIntermTyped* right;
|
|
};
|
|
|
|
//
|
|
// Nodes for unary math operators.
|
|
//
|
|
class TIntermUnary : public TIntermOperator {
|
|
public:
|
|
TIntermUnary(TOperator o, TType& t) : TIntermOperator(o, t), operand(0) {}
|
|
TIntermUnary(TOperator o) : TIntermOperator(o), operand(0) {}
|
|
virtual void traverse(TIntermTraverser*);
|
|
virtual void setOperand(TIntermTyped* o) { operand = o; }
|
|
virtual TIntermTyped* getOperand() { return operand; }
|
|
virtual TIntermUnary* getAsUnaryNode() { return this; }
|
|
virtual const TIntermUnary* getAsUnaryNode() const { return this; }
|
|
virtual bool promote();
|
|
virtual void updatePrecision();
|
|
protected:
|
|
TIntermTyped* operand;
|
|
};
|
|
|
|
typedef TVector<TIntermNode*> TIntermSequence;
|
|
typedef TVector<int> TQualifierList;
|
|
//
|
|
// Nodes that operate on an arbitrary sized set of children.
|
|
//
|
|
class TIntermAggregate : public TIntermOperator {
|
|
public:
|
|
TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), pragmaTable(0) { }
|
|
TIntermAggregate(TOperator o) : TIntermOperator(o), pragmaTable(0) { }
|
|
~TIntermAggregate() { delete pragmaTable; }
|
|
virtual TIntermAggregate* getAsAggregate() { return this; }
|
|
virtual const TIntermAggregate* getAsAggregate() const { return this; }
|
|
virtual void setOperator(TOperator o) { op = o; }
|
|
virtual TIntermSequence& getSequence() { return sequence; }
|
|
virtual const TIntermSequence& getSequence() const { return sequence; }
|
|
virtual void setName(const TString& n) { name = n; }
|
|
virtual const TString& getName() const { return name; }
|
|
virtual void traverse(TIntermTraverser*);
|
|
virtual void setUserDefined() { userDefined = true; }
|
|
virtual bool isUserDefined() { return userDefined; }
|
|
virtual TQualifierList& getQualifierList() { return qualifier; }
|
|
virtual const TQualifierList& getQualifierList() const { return qualifier; }
|
|
void setOptimize(bool o) { optimize = o; }
|
|
void setDebug(bool d) { debug = d; }
|
|
bool getOptimize() { return optimize; }
|
|
bool getDebug() { return debug; }
|
|
void addToPragmaTable(const TPragmaTable& pTable);
|
|
const TPragmaTable& getPragmaTable() const { return *pragmaTable; }
|
|
protected:
|
|
TIntermAggregate(const TIntermAggregate&); // disallow copy constructor
|
|
TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator
|
|
TIntermSequence sequence;
|
|
TQualifierList qualifier;
|
|
TString name;
|
|
bool userDefined; // used for user defined function names
|
|
bool optimize;
|
|
bool debug;
|
|
TPragmaTable* pragmaTable;
|
|
};
|
|
|
|
//
|
|
// For if tests.
|
|
//
|
|
class TIntermSelection : public TIntermTyped {
|
|
public:
|
|
TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) :
|
|
TIntermTyped(TType(EbtVoid)), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
|
|
TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) :
|
|
TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
|
|
virtual void traverse(TIntermTraverser*);
|
|
virtual TIntermTyped* getCondition() const { return condition; }
|
|
virtual TIntermNode* getTrueBlock() const { return trueBlock; }
|
|
virtual TIntermNode* getFalseBlock() const { return falseBlock; }
|
|
virtual TIntermSelection* getAsSelectionNode() { return this; }
|
|
virtual const TIntermSelection* getAsSelectionNode() const { return this; }
|
|
protected:
|
|
TIntermTyped* condition;
|
|
TIntermNode* trueBlock;
|
|
TIntermNode* falseBlock;
|
|
};
|
|
|
|
//
|
|
// For switch statements. Designed use is that a switch will have sequence of nodes
|
|
// that are either case/default nodes or a *single* node that represents all the code
|
|
// in between (if any) consecutive case/defaults. So, a traversal need only deal with
|
|
// 0 or 1 nodes per case/default statement.
|
|
//
|
|
class TIntermSwitch : public TIntermNode {
|
|
public:
|
|
TIntermSwitch(TIntermTyped* cond, TIntermAggregate* b) : condition(cond), body(b) { }
|
|
virtual void traverse(TIntermTraverser*);
|
|
virtual TIntermNode* getCondition() const { return condition; }
|
|
virtual TIntermAggregate* getBody() const { return body; }
|
|
virtual TIntermSwitch* getAsSwitchNode() { return this; }
|
|
virtual const TIntermSwitch* getAsSwitchNode() const { return this; }
|
|
protected:
|
|
TIntermTyped* condition;
|
|
TIntermAggregate* body;
|
|
};
|
|
|
|
enum TVisit
|
|
{
|
|
EvPreVisit,
|
|
EvInVisit,
|
|
EvPostVisit
|
|
};
|
|
|
|
//
|
|
// For traversing the tree. User should derive from this,
|
|
// put their traversal specific data in it, and then pass
|
|
// it to a Traverse method.
|
|
//
|
|
// When using this, just fill in the methods for nodes you want visited.
|
|
// Return false from a pre-visit to skip visiting that node's subtree.
|
|
//
|
|
// Explicitly set postVisit to true if you want post visiting, otherwise,
|
|
// filled in methods will only be called at pre-visit time (before processing
|
|
// the subtree). Similary for inVisit for in-order visiting of nodes with
|
|
// multiple children.
|
|
//
|
|
// If you only want post-visits, explicitly turn off preVisit (and inVisit)
|
|
// and turn on postVisit.
|
|
//
|
|
class TIntermTraverser {
|
|
public:
|
|
POOL_ALLOCATOR_NEW_DELETE(glslang::GetThreadPoolAllocator())
|
|
TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) :
|
|
preVisit(preVisit),
|
|
inVisit(inVisit),
|
|
postVisit(postVisit),
|
|
rightToLeft(rightToLeft),
|
|
depth(0),
|
|
maxDepth(0) { }
|
|
virtual ~TIntermTraverser() { }
|
|
|
|
virtual void visitSymbol(TIntermSymbol*) { }
|
|
virtual void visitConstantUnion(TIntermConstantUnion*) { }
|
|
virtual bool visitBinary(TVisit visit, TIntermBinary*) { return true; }
|
|
virtual bool visitUnary(TVisit visit, TIntermUnary*) { return true; }
|
|
virtual bool visitSelection(TVisit visit, TIntermSelection*) { return true; }
|
|
virtual bool visitAggregate(TVisit visit, TIntermAggregate*) { return true; }
|
|
virtual bool visitLoop(TVisit visit, TIntermLoop*) { return true; }
|
|
virtual bool visitBranch(TVisit visit, TIntermBranch*) { return true; }
|
|
virtual bool visitSwitch(TVisit, TIntermSwitch* node) { return true; }
|
|
|
|
int getMaxDepth() const { return maxDepth; }
|
|
|
|
void incrementDepth(TIntermNode *current)
|
|
{
|
|
depth++;
|
|
maxDepth = std::max(maxDepth, depth);
|
|
path.push_back(current);
|
|
}
|
|
|
|
void decrementDepth()
|
|
{
|
|
depth--;
|
|
path.pop_back();
|
|
}
|
|
|
|
TIntermNode *getParentNode()
|
|
{
|
|
return path.size() == 0 ? NULL : path.back();
|
|
}
|
|
|
|
const bool preVisit;
|
|
const bool inVisit;
|
|
const bool postVisit;
|
|
const bool rightToLeft;
|
|
|
|
protected:
|
|
int depth;
|
|
int maxDepth;
|
|
|
|
// All the nodes from root to the current node's parent during traversing.
|
|
TVector<TIntermNode *> path;
|
|
};
|
|
|
|
} // end namespace glslang
|
|
|
|
#endif // __INTERMEDIATE_H
|