Add preprocessor support for parsing doubles. Add double support to the flex stage. Put in some of the basic double supported needed in the front end. Add generic support for version numbers in the preprocessor, and the core, compatibility, and es profiles. git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@19949 e7fa87d3-cd2b-0410-9028-fcbf551c1848
534 lines
16 KiB
C++
534 lines
16 KiB
C++
//
|
|
//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
|
//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"
|
|
|
|
//
|
|
// 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.
|
|
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,
|
|
EOpConvFloatToBool,
|
|
EOpConvBoolToFloat,
|
|
EOpConvIntToFloat,
|
|
EOpConvFloatToInt,
|
|
EOpConvBoolToInt,
|
|
|
|
//
|
|
// 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,
|
|
|
|
EOpPow,
|
|
EOpExp,
|
|
EOpLog,
|
|
EOpExp2,
|
|
EOpLog2,
|
|
EOpSqrt,
|
|
EOpInverseSqrt,
|
|
|
|
EOpAbs,
|
|
EOpSign,
|
|
EOpFloor,
|
|
EOpCeil,
|
|
EOpFract,
|
|
EOpMin,
|
|
EOpMax,
|
|
EOpClamp,
|
|
EOpMix,
|
|
EOpStep,
|
|
EOpSmoothStep,
|
|
|
|
EOpLength,
|
|
EOpDistance,
|
|
EOpDot,
|
|
EOpCross,
|
|
EOpNormalize,
|
|
EOpFaceForward,
|
|
EOpReflect,
|
|
EOpRefract,
|
|
|
|
EOpDPdx, // Fragment only
|
|
EOpDPdy, // Fragment only
|
|
EOpFwidth, // Fragment only
|
|
|
|
EOpMatrixTimesMatrix,
|
|
|
|
EOpAny,
|
|
EOpAll,
|
|
|
|
//
|
|
// Branch
|
|
//
|
|
|
|
EOpKill, // Fragment only
|
|
EOpReturn,
|
|
EOpBreak,
|
|
EOpContinue,
|
|
|
|
//
|
|
// Constructors
|
|
//
|
|
|
|
EOpConstructInt,
|
|
EOpConstructBool,
|
|
EOpConstructFloat,
|
|
EOpConstructDouble,
|
|
EOpConstructVec2,
|
|
EOpConstructVec3,
|
|
EOpConstructVec4,
|
|
EOpConstructBVec2,
|
|
EOpConstructBVec3,
|
|
EOpConstructBVec4,
|
|
EOpConstructIVec2,
|
|
EOpConstructIVec3,
|
|
EOpConstructIVec4,
|
|
EOpConstructMat2,
|
|
EOpConstructMat3,
|
|
EOpConstructMat4,
|
|
EOpConstructStruct,
|
|
|
|
//
|
|
// moves
|
|
//
|
|
|
|
EOpAssign,
|
|
EOpAddAssign,
|
|
EOpSubAssign,
|
|
EOpMulAssign,
|
|
EOpVectorTimesMatrixAssign,
|
|
EOpVectorTimesScalarAssign,
|
|
EOpMatrixTimesScalarAssign,
|
|
EOpMatrixTimesMatrixAssign,
|
|
EOpDivAssign,
|
|
EOpModAssign,
|
|
EOpAndAssign,
|
|
EOpInclusiveOrAssign,
|
|
EOpExclusiveOrAssign,
|
|
EOpLeftShiftAssign,
|
|
EOpRightShiftAssign,
|
|
|
|
//
|
|
// Array operators
|
|
//
|
|
|
|
EOpArrayLength,
|
|
};
|
|
|
|
class TIntermTraverser;
|
|
class TIntermAggregate;
|
|
class TIntermBinary;
|
|
class TIntermConstantUnion;
|
|
class TIntermSelection;
|
|
class TIntermTyped;
|
|
class TIntermMethod;
|
|
class TIntermSymbol;
|
|
class TInfoSink;
|
|
|
|
//
|
|
// Base class for the tree nodes
|
|
//
|
|
class TIntermNode {
|
|
public:
|
|
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
|
|
|
|
TIntermNode() : line(0) {}
|
|
virtual TSourceLoc getLine() const { return line; }
|
|
virtual void setLine(TSourceLoc l) { line = l; }
|
|
virtual void traverse(TIntermTraverser*) = 0;
|
|
virtual TIntermTyped* getAsTyped() { return 0; }
|
|
virtual TIntermConstantUnion* getAsConstantUnion() { return 0; }
|
|
virtual TIntermAggregate* getAsAggregate() { return 0; }
|
|
virtual TIntermBinary* getAsBinaryNode() { return 0; }
|
|
virtual TIntermSelection* getAsSelectionNode() { return 0; }
|
|
virtual TIntermMethod* getAsMethodNode() { return 0; }
|
|
virtual TIntermSymbol* getAsSymbolNode() { return 0; }
|
|
virtual ~TIntermNode() { }
|
|
protected:
|
|
TSourceLoc line;
|
|
};
|
|
|
|
//
|
|
// This is just to help yacc.
|
|
//
|
|
struct TIntermNodePair {
|
|
TIntermNode* node1;
|
|
TIntermNode* node2;
|
|
};
|
|
|
|
class TIntermSymbol;
|
|
class TIntermBinary;
|
|
|
|
//
|
|
// Intermediate class for nodes that have a type.
|
|
//
|
|
class TIntermTyped : public TIntermNode {
|
|
public:
|
|
TIntermTyped(const TType& t) : type(t) { }
|
|
virtual TIntermTyped* getAsTyped() { return this; }
|
|
virtual void setType(const TType& t) { type = t; }
|
|
virtual TType getType() const { return type; }
|
|
virtual TType* getTypePointer() { return &type; }
|
|
|
|
virtual TBasicType getBasicType() const { return type.getBasicType(); }
|
|
virtual TQualifier getQualifier() const { return type.getQualifier(); }
|
|
virtual int getNominalSize() const { return type.getNominalSize(); }
|
|
virtual int getSize() const { return type.getInstanceSize(); }
|
|
virtual bool isMatrix() const { return type.isMatrix(); }
|
|
virtual bool isArray() const { return type.isArray(); }
|
|
virtual bool isVector() const { return type.isVector(); }
|
|
const char* getBasicString() const { return type.getBasicString(); }
|
|
const char* getQualifierString() const { return type.getQualifierString(); }
|
|
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 break, continue, return, and kill.
|
|
//
|
|
class TIntermBranch : public TIntermNode {
|
|
public:
|
|
TIntermBranch(TOperator op, TIntermTyped* e) :
|
|
flowOp(op),
|
|
expression(e) { }
|
|
virtual void traverse(TIntermTraverser*);
|
|
TOperator getFlowOp() { return flowOp; }
|
|
TIntermTyped* getExpression() { return expression; }
|
|
protected:
|
|
TOperator flowOp;
|
|
TIntermTyped* expression; // non-zero except for "return exp;" statements
|
|
};
|
|
|
|
//
|
|
// 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 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 globalpoolallocator, then it causes increased memory usage per compile
|
|
// it is essential to use "symbol = sym" to assign to symbol
|
|
TIntermSymbol(int i, const TString& sym, const TType& t) :
|
|
TIntermTyped(t), id(i) { symbol = sym;}
|
|
virtual int getId() const { return id; }
|
|
virtual const TString& getSymbol() const { return symbol; }
|
|
virtual void traverse(TIntermTraverser*);
|
|
virtual TIntermSymbol* getAsSymbolNode() { return this; }
|
|
protected:
|
|
int id;
|
|
TString symbol;
|
|
};
|
|
|
|
class TIntermConstantUnion : public TIntermTyped {
|
|
public:
|
|
TIntermConstantUnion(constUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer) { }
|
|
constUnion* getUnionArrayPointer() const { return unionArrayPointer; }
|
|
void setUnionArrayPointer(constUnion *c) { unionArrayPointer = c; }
|
|
virtual TIntermConstantUnion* getAsConstantUnion() { return this; }
|
|
virtual void traverse(TIntermTraverser* );
|
|
virtual TIntermTyped* fold(TOperator, TIntermTyped*, TInfoSink&);
|
|
protected:
|
|
constUnion *unionArrayPointer;
|
|
};
|
|
|
|
//
|
|
// Intermediate class for node types that hold operators.
|
|
//
|
|
class TIntermOperator : public TIntermTyped {
|
|
public:
|
|
TOperator getOp() { return op; }
|
|
bool modifiesState() const;
|
|
bool isConstructor() const;
|
|
virtual bool promote(TInfoSink&) { 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 bool promote(TInfoSink&);
|
|
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 bool promote(TInfoSink&);
|
|
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 void setOperator(TOperator o) { op = o; }
|
|
virtual TIntermSequence& getSequence() { 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& getQualifier() { 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. Simplified since there is no switch statement.
|
|
//
|
|
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 TIntermNode* getCondition() const { return condition; }
|
|
virtual TIntermNode* getTrueBlock() const { return trueBlock; }
|
|
virtual TIntermNode* getFalseBlock() const { return falseBlock; }
|
|
virtual TIntermSelection* getAsSelectionNode() { return this; }
|
|
protected:
|
|
TIntermTyped* condition;
|
|
TIntermNode* trueBlock;
|
|
TIntermNode* falseBlock;
|
|
};
|
|
|
|
//
|
|
// 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.
|
|
//
|
|
class TIntermTraverser {
|
|
public:
|
|
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
|
|
|
|
TIntermTraverser() :
|
|
visitSymbol(0),
|
|
visitConstantUnion(0),
|
|
visitBinary(0),
|
|
visitUnary(0),
|
|
visitSelection(0),
|
|
visitAggregate(0),
|
|
visitLoop(0),
|
|
visitBranch(0),
|
|
depth(0),
|
|
preVisit(true),
|
|
postVisit(false),
|
|
rightToLeft(false) {}
|
|
|
|
void (*visitSymbol)(TIntermSymbol*, TIntermTraverser*);
|
|
void (*visitConstantUnion)(TIntermConstantUnion*, TIntermTraverser*);
|
|
bool (*visitBinary)(bool preVisit, TIntermBinary*, TIntermTraverser*);
|
|
bool (*visitUnary)(bool preVisit, TIntermUnary*, TIntermTraverser*);
|
|
bool (*visitSelection)(bool preVisit, TIntermSelection*, TIntermTraverser*);
|
|
bool (*visitAggregate)(bool preVisit, TIntermAggregate*, TIntermTraverser*);
|
|
bool (*visitLoop)(bool preVisit, TIntermLoop*, TIntermTraverser*);
|
|
bool (*visitBranch)(bool preVisit, TIntermBranch*, TIntermTraverser*);
|
|
|
|
int depth;
|
|
bool preVisit;
|
|
bool postVisit;
|
|
bool rightToLeft;
|
|
};
|
|
|
|
#endif // __INTERMEDIATE_H
|