summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/compiler/translator/IntermNode.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/angle/src/compiler/translator/IntermNode.h')
-rw-r--r--src/3rdparty/angle/src/compiler/translator/IntermNode.h847
1 files changed, 401 insertions, 446 deletions
diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNode.h b/src/3rdparty/angle/src/compiler/translator/IntermNode.h
index ad500e2b1f..2170916201 100644
--- a/src/3rdparty/angle/src/compiler/translator/IntermNode.h
+++ b/src/3rdparty/angle/src/compiler/translator/IntermNode.h
@@ -25,14 +25,27 @@
#include "compiler/translator/Common.h"
#include "compiler/translator/ConstantUnion.h"
#include "compiler/translator/Operator.h"
+#include "compiler/translator/SymbolUniqueId.h"
#include "compiler/translator/Types.h"
+namespace sh
+{
+
+class TDiagnostics;
+
class TIntermTraverser;
class TIntermAggregate;
+class TIntermBlock;
+class TIntermInvariantDeclaration;
+class TIntermDeclaration;
+class TIntermFunctionPrototype;
+class TIntermFunctionDefinition;
+class TIntermSwizzle;
class TIntermBinary;
class TIntermUnary;
class TIntermConstantUnion;
-class TIntermSelection;
+class TIntermTernary;
+class TIntermIfElse;
class TIntermSwitch;
class TIntermCase;
class TIntermTyped;
@@ -41,8 +54,10 @@ class TIntermLoop;
class TInfoSink;
class TInfoSinkBase;
class TIntermRaw;
+class TIntermBranch;
class TSymbolTable;
+class TFunction;
// Encapsulate an identifier string and track whether it is coming from the original shader code
// (not internal) or from ANGLE (internal). Usually internal names shouldn't be decorated or hashed.
@@ -79,7 +94,7 @@ class TIntermNode : angle::NonCopyable
mLine.first_file = mLine.last_file = 0;
mLine.first_line = mLine.last_line = 0;
}
- virtual ~TIntermNode() { }
+ virtual ~TIntermNode() {}
const TSourceLoc &getLine() const { return mLine; }
void setLine(const TSourceLoc &l) { mLine = l; }
@@ -87,20 +102,27 @@ class TIntermNode : angle::NonCopyable
virtual void traverse(TIntermTraverser *) = 0;
virtual TIntermTyped *getAsTyped() { return 0; }
virtual TIntermConstantUnion *getAsConstantUnion() { return 0; }
+ virtual TIntermFunctionDefinition *getAsFunctionDefinition() { return nullptr; }
virtual TIntermAggregate *getAsAggregate() { return 0; }
+ virtual TIntermBlock *getAsBlock() { return nullptr; }
+ virtual TIntermFunctionPrototype *getAsFunctionPrototypeNode() { return nullptr; }
+ virtual TIntermInvariantDeclaration *getAsInvariantDeclarationNode() { return nullptr; }
+ virtual TIntermDeclaration *getAsDeclarationNode() { return nullptr; }
+ virtual TIntermSwizzle *getAsSwizzleNode() { return nullptr; }
virtual TIntermBinary *getAsBinaryNode() { return 0; }
virtual TIntermUnary *getAsUnaryNode() { return 0; }
- virtual TIntermSelection *getAsSelectionNode() { return 0; }
+ virtual TIntermTernary *getAsTernaryNode() { return nullptr; }
+ virtual TIntermIfElse *getAsIfElseNode() { return nullptr; }
virtual TIntermSwitch *getAsSwitchNode() { return 0; }
virtual TIntermCase *getAsCaseNode() { return 0; }
virtual TIntermSymbol *getAsSymbolNode() { return 0; }
virtual TIntermLoop *getAsLoopNode() { return 0; }
virtual TIntermRaw *getAsRawNode() { return 0; }
+ virtual TIntermBranch *getAsBranchNode() { return 0; }
// Replace a child node. Return true if |original| is a child
// node and it is replaced; otherwise, return false.
- virtual bool replaceChildNode(
- TIntermNode *original, TIntermNode *replacement) = 0;
+ virtual bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) = 0;
protected:
TSourceLoc mLine;
@@ -121,12 +143,15 @@ struct TIntermNodePair
class TIntermTyped : public TIntermNode
{
public:
- TIntermTyped(const TType &t) : mType(t) { }
+ TIntermTyped(const TType &t) : mType(t) {}
virtual TIntermTyped *deepCopy() const = 0;
TIntermTyped *getAsTyped() override { return this; }
+ // True if executing the expression represented by this node affects state, like values of
+ // variables. False if the executing the expression only computes its return value without
+ // affecting state. May return true conservatively.
virtual bool hasSideEffects() const = 0;
void setType(const TType &t) { mType = t; }
@@ -137,6 +162,7 @@ class TIntermTyped : public TIntermNode
TBasicType getBasicType() const { return mType.getBasicType(); }
TQualifier getQualifier() const { return mType.getQualifier(); }
TPrecision getPrecision() const { return mType.getPrecision(); }
+ TMemoryQualifier getMemoryQualifier() const { return mType.getMemoryQualifier(); }
int getCols() const { return mType.getCols(); }
int getRows() const { return mType.getRows(); }
int getNominalSize() const { return mType.getNominalSize(); }
@@ -144,14 +170,16 @@ class TIntermTyped : public TIntermNode
bool isInterfaceBlock() const { return mType.isInterfaceBlock(); }
bool isMatrix() const { return mType.isMatrix(); }
- bool isArray() const { return mType.isArray(); }
+ bool isArray() const { return mType.isArray(); }
bool isVector() const { return mType.isVector(); }
bool isScalar() const { return mType.isScalar(); }
bool isScalarInt() const { return mType.isScalarInt(); }
const char *getBasicString() const { return mType.getBasicString(); }
TString getCompleteString() const { return mType.getCompleteString(); }
- int getArraySize() const { return mType.getArraySize(); }
+ unsigned int getOutermostArraySize() const { return mType.getOutermostArraySize(); }
+
+ bool isConstructorWithOnlyConstantUnionParameters();
protected:
TType mType;
@@ -176,10 +204,7 @@ class TIntermLoop : public TIntermNode
TIntermNode *init,
TIntermTyped *cond,
TIntermTyped *expr,
- TIntermAggregate *body)
- : mType(type), mInit(init), mCond(cond), mExpr(expr), mBody(body), mUnrollFlag(false)
- {
- }
+ TIntermBlock *body);
TIntermLoop *getAsLoopNode() override { return this; }
void traverse(TIntermTraverser *it) override;
@@ -189,19 +214,19 @@ class TIntermLoop : public TIntermNode
TIntermNode *getInit() { return mInit; }
TIntermTyped *getCondition() { return mCond; }
TIntermTyped *getExpression() { return mExpr; }
- TIntermAggregate *getBody() { return mBody; }
+ TIntermBlock *getBody() { return mBody; }
- void setUnrollFlag(bool flag) { mUnrollFlag = flag; }
- bool getUnrollFlag() const { return mUnrollFlag; }
+ void setInit(TIntermNode *init) { mInit = init; }
+ void setCondition(TIntermTyped *condition) { mCond = condition; }
+ void setExpression(TIntermTyped *expression) { mExpr = expression; }
+ void setBody(TIntermBlock *body) { mBody = body; }
protected:
TLoopType mType;
- TIntermNode *mInit; // for-loop initialization
- TIntermTyped *mCond; // loop exit condition
- TIntermTyped *mExpr; // for-loop expression
- TIntermAggregate *mBody; // loop body
-
- bool mUnrollFlag; // Whether the loop should be unrolled or not.
+ TIntermNode *mInit; // for-loop initialization
+ TIntermTyped *mCond; // loop exit condition
+ TIntermTyped *mExpr; // for-loop expression
+ TIntermBlock *mBody; // loop body
};
//
@@ -210,17 +235,16 @@ class TIntermLoop : public TIntermNode
class TIntermBranch : public TIntermNode
{
public:
- TIntermBranch(TOperator op, TIntermTyped *e)
- : mFlowOp(op),
- mExpression(e) { }
+ TIntermBranch(TOperator op, TIntermTyped *e) : mFlowOp(op), mExpression(e) {}
void traverse(TIntermTraverser *it) override;
+ TIntermBranch *getAsBranchNode() override { return this; }
bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
TOperator getFlowOp() { return mFlowOp; }
- TIntermTyped* getExpression() { return mExpression; }
+ TIntermTyped *getExpression() { return mExpression; }
-protected:
+ protected:
TOperator mFlowOp;
TIntermTyped *mExpression; // non-zero except for "return exp;" statements
};
@@ -234,7 +258,7 @@ class TIntermSymbol : public TIntermTyped
// 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 id, const TString &symbol, const TType &type)
+ TIntermSymbol(const TSymbolUniqueId &id, const TString &symbol, const TType &type)
: TIntermTyped(type), mId(id), mSymbol(symbol)
{
}
@@ -243,11 +267,10 @@ class TIntermSymbol : public TIntermTyped
bool hasSideEffects() const override { return false; }
- int getId() const { return mId; }
+ int getId() const { return mId.get(); }
const TString &getSymbol() const { return mSymbol.getString(); }
const TName &getName() const { return mSymbol; }
-
- void setId(int newId) { mId = newId; }
+ TName &getName() { return mSymbol; }
void setInternal(bool internal) { mSymbol.setInternal(internal); }
@@ -256,7 +279,7 @@ class TIntermSymbol : public TIntermTyped
bool replaceChildNode(TIntermNode *, TIntermNode *) override { return false; }
protected:
- int mId;
+ const TSymbolUniqueId mId;
TName mSymbol;
private:
@@ -269,9 +292,7 @@ class TIntermSymbol : public TIntermTyped
class TIntermRaw : public TIntermTyped
{
public:
- TIntermRaw(const TType &type, const TString &rawText)
- : TIntermTyped(type),
- mRawText(rawText) { }
+ TIntermRaw(const TType &type, const TString &rawText) : TIntermTyped(type), mRawText(rawText) {}
TIntermRaw(const TIntermRaw &) = delete;
TIntermTyped *deepCopy() const override
@@ -305,6 +326,7 @@ class TIntermConstantUnion : public TIntermTyped
TIntermConstantUnion(const TConstantUnion *unionPointer, const TType &type)
: TIntermTyped(type), mUnionArrayPointer(unionPointer)
{
+ ASSERT(unionPointer);
}
TIntermTyped *deepCopy() const override { return new TIntermConstantUnion(*this); }
@@ -332,6 +354,7 @@ class TIntermConstantUnion : public TIntermTyped
void replaceConstantUnion(const TConstantUnion *safeConstantUnion)
{
+ ASSERT(safeConstantUnion);
// Previous union pointer freed on pool deallocation.
mUnionArrayPointer = safeConstantUnion;
}
@@ -340,21 +363,27 @@ class TIntermConstantUnion : public TIntermTyped
void traverse(TIntermTraverser *it) override;
bool replaceChildNode(TIntermNode *, TIntermNode *) override { return false; }
- TConstantUnion *foldBinary(TOperator op, TIntermConstantUnion *rightNode, TInfoSink &infoSink);
- TConstantUnion *foldUnaryWithDifferentReturnType(TOperator op, TInfoSink &infoSink);
- TConstantUnion *foldUnaryWithSameReturnType(TOperator op, TInfoSink &infoSink);
+ TConstantUnion *foldBinary(TOperator op,
+ TIntermConstantUnion *rightNode,
+ TDiagnostics *diagnostics,
+ const TSourceLoc &line);
+ const TConstantUnion *foldIndexing(int index);
+ TConstantUnion *foldUnaryNonComponentWise(TOperator op);
+ TConstantUnion *foldUnaryComponentWise(TOperator op, TDiagnostics *diagnostics);
- static TConstantUnion *FoldAggregateConstructor(TIntermAggregate *aggregate,
- TInfoSink &infoSink);
- static TConstantUnion *FoldAggregateBuiltIn(TIntermAggregate *aggregate, TInfoSink &infoSink);
+ static TConstantUnion *FoldAggregateConstructor(TIntermAggregate *aggregate);
+ static TConstantUnion *FoldAggregateBuiltIn(TIntermAggregate *aggregate,
+ TDiagnostics *diagnostics);
protected:
// Same data may be shared between multiple constant unions, so it can't be modified.
const TConstantUnion *mUnionArrayPointer;
private:
- typedef float(*FloatTypeUnaryFunc) (float);
- bool foldFloatTypeUnary(const TConstantUnion &parameter, FloatTypeUnaryFunc builtinFunc, TInfoSink &infoSink, TConstantUnion *result) const;
+ typedef float (*FloatTypeUnaryFunc)(float);
+ void foldFloatTypeUnary(const TConstantUnion &parameter,
+ FloatTypeUnaryFunc builtinFunc,
+ TConstantUnion *result) const;
TIntermConstantUnion(const TIntermConstantUnion &node); // Note: not deleted, just private!
};
@@ -366,25 +395,57 @@ class TIntermOperator : public TIntermTyped
{
public:
TOperator getOp() const { return mOp; }
- void setOp(TOperator op) { mOp = op; }
bool isAssignment() const;
bool isMultiplication() const;
bool isConstructor() const;
+ // Returns true for calls mapped to EOpCall*, false for built-ins that have their own specific
+ // ops.
+ bool isFunctionCall() const;
+
bool hasSideEffects() const override { return isAssignment(); }
protected:
- TIntermOperator(TOperator op)
- : TIntermTyped(TType(EbtFloat, EbpUndefined)),
- mOp(op) {}
- TIntermOperator(TOperator op, const TType &type)
- : TIntermTyped(type),
- mOp(op) {}
+ TIntermOperator(TOperator op) : TIntermTyped(TType(EbtFloat, EbpUndefined)), mOp(op) {}
+ TIntermOperator(TOperator op, const TType &type) : TIntermTyped(type), mOp(op) {}
TIntermOperator(const TIntermOperator &) = default;
- TOperator mOp;
+ const TOperator mOp;
+};
+
+// Node for vector swizzles.
+class TIntermSwizzle : public TIntermTyped
+{
+ public:
+ // This constructor determines the type of the node based on the operand.
+ TIntermSwizzle(TIntermTyped *operand, const TVector<int> &swizzleOffsets);
+
+ TIntermTyped *deepCopy() const override { return new TIntermSwizzle(*this); }
+
+ TIntermSwizzle *getAsSwizzleNode() override { return this; };
+ void traverse(TIntermTraverser *it) override;
+ bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
+
+ bool hasSideEffects() const override { return mOperand->hasSideEffects(); }
+
+ TIntermTyped *getOperand() { return mOperand; }
+ void writeOffsetsAsXYZW(TInfoSinkBase *out) const;
+
+ bool hasDuplicateOffsets() const;
+ bool offsetsMatch(int offset) const;
+
+ TIntermTyped *fold();
+
+ protected:
+ TIntermTyped *mOperand;
+ TVector<int> mSwizzleOffsets;
+
+ private:
+ void promote();
+
+ TIntermSwizzle(const TIntermSwizzle &node); // Note: not deleted, just private!
};
//
@@ -393,12 +454,17 @@ class TIntermOperator : public TIntermTyped
class TIntermBinary : public TIntermOperator
{
public:
- TIntermBinary(TOperator op)
- : TIntermOperator(op),
- mAddIndexClamp(false) {}
+ // This constructor determines the type of the binary node based on the operands and op.
+ TIntermBinary(TOperator op, TIntermTyped *left, TIntermTyped *right);
TIntermTyped *deepCopy() const override { return new TIntermBinary(*this); }
+ static TOperator GetMulOpBasedOnOperands(const TType &left, const TType &right);
+ static TOperator GetMulAssignOpBasedOnOperands(const TType &left, const TType &right);
+ static TQualifier GetCommaQualifier(int shaderVersion,
+ const TIntermTyped *left,
+ const TIntermTyped *right);
+
TIntermBinary *getAsBinaryNode() override { return this; };
void traverse(TIntermTraverser *it) override;
bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
@@ -408,24 +474,23 @@ class TIntermBinary : public TIntermOperator
return isAssignment() || mLeft->hasSideEffects() || mRight->hasSideEffects();
}
- void setLeft(TIntermTyped *node) { mLeft = node; }
- void setRight(TIntermTyped *node) { mRight = node; }
TIntermTyped *getLeft() const { return mLeft; }
TIntermTyped *getRight() const { return mRight; }
- bool promote(TInfoSink &);
- TIntermTyped *fold(TInfoSink &infoSink);
+ TIntermTyped *fold(TDiagnostics *diagnostics);
void setAddIndexClamp() { mAddIndexClamp = true; }
bool getAddIndexClamp() { return mAddIndexClamp; }
protected:
- TIntermTyped* mLeft;
- TIntermTyped* mRight;
+ TIntermTyped *mLeft;
+ TIntermTyped *mRight;
// If set to true, wrap any EOpIndexIndirect with a clamp to bounds.
bool mAddIndexClamp;
private:
+ void promote();
+
TIntermBinary(const TIntermBinary &node); // Note: not deleted, just private!
};
@@ -435,14 +500,7 @@ class TIntermBinary : public TIntermOperator
class TIntermUnary : public TIntermOperator
{
public:
- TIntermUnary(TOperator op, const TType &type)
- : TIntermOperator(op, type),
- mOperand(NULL),
- mUseEmulatedFunction(false) {}
- TIntermUnary(TOperator op)
- : TIntermOperator(op),
- mOperand(NULL),
- mUseEmulatedFunction(false) {}
+ TIntermUnary(TOperator op, TIntermTyped *operand);
TIntermTyped *deepCopy() const override { return new TIntermUnary(*this); }
@@ -452,10 +510,8 @@ class TIntermUnary : public TIntermOperator
bool hasSideEffects() const override { return isAssignment() || mOperand->hasSideEffects(); }
- void setOperand(TIntermTyped *operand) { mOperand = operand; }
TIntermTyped *getOperand() { return mOperand; }
- void promote(const TType *funcReturnType);
- TIntermTyped *fold(TInfoSink &infoSink);
+ TIntermTyped *fold(TDiagnostics *diagnostics);
void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
@@ -468,495 +524,394 @@ class TIntermUnary : public TIntermOperator
bool mUseEmulatedFunction;
private:
+ void promote();
+
TIntermUnary(const TIntermUnary &node); // note: not deleted, just private!
};
+class TFunctionSymbolInfo
+{
+ public:
+ POOL_ALLOCATOR_NEW_DELETE();
+ TFunctionSymbolInfo(const TSymbolUniqueId &id);
+ TFunctionSymbolInfo() : mId(nullptr), mKnownToNotHaveSideEffects(false) {}
+
+ TFunctionSymbolInfo(const TFunctionSymbolInfo &info);
+ TFunctionSymbolInfo &operator=(const TFunctionSymbolInfo &info);
+
+ void setFromFunction(const TFunction &function);
+
+ void setNameObj(const TName &name) { mName = name; }
+ const TName &getNameObj() const { return mName; }
+
+ const TString &getName() const { return mName.getString(); }
+ void setName(const TString &name) { mName.setString(name); }
+ bool isMain() const { return mName.getString() == "main"; }
+
+ void setKnownToNotHaveSideEffects(bool knownToNotHaveSideEffects)
+ {
+ mKnownToNotHaveSideEffects = knownToNotHaveSideEffects;
+ }
+ bool isKnownToNotHaveSideEffects() const { return mKnownToNotHaveSideEffects; }
+
+ void setId(const TSymbolUniqueId &functionId);
+ const TSymbolUniqueId &getId() const;
+
+ bool isImageFunction() const
+ {
+ return getName() == "imageSize" || getName() == "imageLoad" || getName() == "imageStore";
+ }
+
+ private:
+ TName mName;
+ TSymbolUniqueId *mId;
+ bool mKnownToNotHaveSideEffects;
+};
+
typedef TVector<TIntermNode *> TIntermSequence;
typedef TVector<int> TQualifierList;
//
+// This is just to help yacc.
+//
+struct TIntermFunctionCallOrMethod
+{
+ TIntermSequence *arguments;
+ TIntermNode *thisNode;
+};
+
+// Interface for node classes that have an arbitrarily sized set of children.
+class TIntermAggregateBase
+{
+ public:
+ virtual ~TIntermAggregateBase() {}
+
+ virtual TIntermSequence *getSequence() = 0;
+ virtual const TIntermSequence *getSequence() const = 0;
+
+ bool replaceChildNodeWithMultiple(TIntermNode *original, const TIntermSequence &replacements);
+ bool insertChildNodes(TIntermSequence::size_type position, const TIntermSequence &insertions);
+
+ protected:
+ TIntermAggregateBase() {}
+
+ bool replaceChildNodeInternal(TIntermNode *original, TIntermNode *replacement);
+};
+
+//
// Nodes that operate on an arbitrary sized set of children.
//
-class TIntermAggregate : public TIntermOperator
+class TIntermAggregate : public TIntermOperator, public TIntermAggregateBase
{
public:
- TIntermAggregate()
- : TIntermOperator(EOpNull),
- mUserDefined(false),
- mUseEmulatedFunction(false),
- mGotPrecisionFromChildren(false)
- {
- }
- TIntermAggregate(TOperator op)
- : TIntermOperator(op),
- mUseEmulatedFunction(false),
- mGotPrecisionFromChildren(false)
- {
- }
- ~TIntermAggregate() { }
+ static TIntermAggregate *CreateFunctionCall(const TFunction &func, TIntermSequence *arguments);
+
+ // If using this, ensure that there's a consistent function definition with the same symbol id
+ // added to the AST.
+ static TIntermAggregate *CreateFunctionCall(const TType &type,
+ const TSymbolUniqueId &id,
+ const TName &name,
+ TIntermSequence *arguments);
+
+ static TIntermAggregate *CreateBuiltInFunctionCall(const TFunction &func,
+ TIntermSequence *arguments);
+ static TIntermAggregate *CreateConstructor(const TType &type,
+ TIntermSequence *arguments);
+ static TIntermAggregate *Create(const TType &type, TOperator op, TIntermSequence *arguments);
+ ~TIntermAggregate() {}
// Note: only supported for nodes that can be a part of an expression.
TIntermTyped *deepCopy() const override { return new TIntermAggregate(*this); }
+ TIntermAggregate *shallowCopy() const;
+
TIntermAggregate *getAsAggregate() override { return this; }
void traverse(TIntermTraverser *it) override;
bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
- bool replaceChildNodeWithMultiple(TIntermNode *original, TIntermSequence replacements);
- bool insertChildNodes(TIntermSequence::size_type position, TIntermSequence insertions);
- // Conservatively assume function calls and other aggregate operators have side-effects
- bool hasSideEffects() const override { return true; }
- TIntermTyped *fold(TInfoSink &infoSink);
- TIntermSequence *getSequence() { return &mSequence; }
+ bool hasSideEffects() const override;
- void setNameObj(const TName &name) { mName = name; }
- const TName &getNameObj() const { return mName; }
-
- void setName(const TString &name) { mName.setString(name); }
- const TString &getName() const { return mName.getString(); }
+ static bool CanFoldAggregateBuiltInOp(TOperator op);
+ TIntermTyped *fold(TDiagnostics *diagnostics);
- void setUserDefined() { mUserDefined = true; }
- bool isUserDefined() const { return mUserDefined; }
+ TIntermSequence *getSequence() override { return &mArguments; }
+ const TIntermSequence *getSequence() const override { return &mArguments; }
- void setFunctionId(int functionId) { mFunctionId = functionId; }
- int getFunctionId() const { return mFunctionId; }
+ TString getSymbolTableMangledName() const;
void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
- bool areChildrenConstQualified();
- void setPrecisionFromChildren();
- void setBuiltInFunctionPrecision();
-
// Returns true if changing parameter precision may affect the return value.
bool gotPrecisionFromChildren() const { return mGotPrecisionFromChildren; }
+ TFunctionSymbolInfo *getFunctionSymbolInfo() { return &mFunctionInfo; }
+ const TFunctionSymbolInfo *getFunctionSymbolInfo() const { return &mFunctionInfo; }
+
protected:
- TIntermSequence mSequence;
- TName mName;
- bool mUserDefined; // used for user defined function names
- int mFunctionId;
+ TIntermSequence mArguments;
// If set to true, replace the built-in function call with an emulated one
- // to work around driver bugs.
+ // to work around driver bugs. Only for calls mapped to ops other than EOpCall*.
bool mUseEmulatedFunction;
bool mGotPrecisionFromChildren;
+ TFunctionSymbolInfo mFunctionInfo;
+
private:
+ TIntermAggregate(const TType &type, TOperator op, TIntermSequence *arguments);
+
TIntermAggregate(const TIntermAggregate &node); // note: not deleted, just private!
+
+ void setTypePrecisionAndQualifier(const TType &type);
+
+ bool areChildrenConstQualified();
+
+ void setPrecisionFromChildren();
+
+ void setPrecisionForBuiltInOp();
+
+ // Returns true if precision was set according to special rules for this built-in.
+ bool setPrecisionForSpecialBuiltInOp();
+
+ // Used for built-in functions under EOpCallBuiltInFunction. The function name in the symbol
+ // info needs to be set before calling this.
+ void setBuiltInFunctionPrecision();
};
-//
-// For if tests.
-//
-class TIntermSelection : public TIntermTyped
+// A list of statements. Either the root node which contains declarations and function definitions,
+// or a block that can be marked with curly braces {}.
+class TIntermBlock : public TIntermNode, public TIntermAggregateBase
{
public:
- TIntermSelection(TIntermTyped *cond, TIntermNode *trueB, TIntermNode *falseB)
- : TIntermTyped(TType(EbtVoid, EbpUndefined)),
- mCondition(cond),
- mTrueBlock(trueB),
- mFalseBlock(falseB) {}
- TIntermSelection(TIntermTyped *cond, TIntermNode *trueB, TIntermNode *falseB,
- const TType &type)
- : TIntermTyped(type),
- mCondition(cond),
- mTrueBlock(trueB),
- mFalseBlock(falseB) {}
-
- // Note: only supported for ternary operator nodes.
- TIntermTyped *deepCopy() const override { return new TIntermSelection(*this); }
+ TIntermBlock() : TIntermNode() {}
+ ~TIntermBlock() {}
+ TIntermBlock *getAsBlock() override { return this; }
void traverse(TIntermTraverser *it) override;
bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
- // Conservatively assume selections have side-effects
- bool hasSideEffects() const override { return true; }
+ // Only intended for initially building the block.
+ void appendStatement(TIntermNode *statement);
- bool usesTernaryOperator() const { return getBasicType() != EbtVoid; }
- TIntermNode *getCondition() const { return mCondition; }
- TIntermNode *getTrueBlock() const { return mTrueBlock; }
- TIntermNode *getFalseBlock() const { return mFalseBlock; }
- TIntermSelection *getAsSelectionNode() override { return this; }
+ TIntermSequence *getSequence() override { return &mStatements; }
+ const TIntermSequence *getSequence() const override { return &mStatements; }
protected:
- TIntermTyped *mCondition;
- TIntermNode *mTrueBlock;
- TIntermNode *mFalseBlock;
-
- private:
- TIntermSelection(const TIntermSelection &node); // Note: not deleted, just private!
+ TIntermSequence mStatements;
};
-//
-// Switch statement.
-//
-class TIntermSwitch : public TIntermNode
+// Function prototype. May be in the AST either as a function prototype declaration or as a part of
+// a function definition. The type of the node is the function return type.
+class TIntermFunctionPrototype : public TIntermTyped, public TIntermAggregateBase
{
public:
- TIntermSwitch(TIntermTyped *init, TIntermAggregate *statementList)
- : TIntermNode(),
- mInit(init),
- mStatementList(statementList)
+ // TODO(oetuaho@nvidia.com): See if TFunctionSymbolInfo could be added to constructor
+ // parameters.
+ TIntermFunctionPrototype(const TType &type, const TSymbolUniqueId &id)
+ : TIntermTyped(type), mFunctionInfo(id)
{
}
+ ~TIntermFunctionPrototype() {}
+ TIntermFunctionPrototype *getAsFunctionPrototypeNode() override { return this; }
void traverse(TIntermTraverser *it) override;
- bool replaceChildNode(
- TIntermNode *original, TIntermNode *replacement) override;
+ bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
- TIntermSwitch *getAsSwitchNode() override { return this; }
+ TIntermTyped *deepCopy() const override
+ {
+ UNREACHABLE();
+ return nullptr;
+ }
+ bool hasSideEffects() const override
+ {
+ UNREACHABLE();
+ return true;
+ }
- TIntermTyped *getInit() { return mInit; }
- TIntermAggregate *getStatementList() { return mStatementList; }
- void setStatementList(TIntermAggregate *statementList) { mStatementList = statementList; }
+ // Only intended for initially building the declaration.
+ void appendParameter(TIntermSymbol *parameter);
+
+ TIntermSequence *getSequence() override { return &mParameters; }
+ const TIntermSequence *getSequence() const override { return &mParameters; }
+
+ TFunctionSymbolInfo *getFunctionSymbolInfo() { return &mFunctionInfo; }
+ const TFunctionSymbolInfo *getFunctionSymbolInfo() const { return &mFunctionInfo; }
protected:
- TIntermTyped *mInit;
- TIntermAggregate *mStatementList;
+ TIntermSequence mParameters;
+
+ TFunctionSymbolInfo mFunctionInfo;
};
-//
-// Case label.
-//
-class TIntermCase : public TIntermNode
+// Node for function definitions. The prototype child node stores the function header including
+// parameters, and the body child node stores the function body.
+class TIntermFunctionDefinition : public TIntermNode
{
public:
- TIntermCase(TIntermTyped *condition)
- : TIntermNode(),
- mCondition(condition)
+ TIntermFunctionDefinition(TIntermFunctionPrototype *prototype, TIntermBlock *body)
+ : TIntermNode(), mPrototype(prototype), mBody(body)
{
+ ASSERT(prototype != nullptr);
+ ASSERT(body != nullptr);
}
+ TIntermFunctionDefinition *getAsFunctionDefinition() override { return this; }
void traverse(TIntermTraverser *it) override;
- bool replaceChildNode(
- TIntermNode *original, TIntermNode *replacement) override;
+ bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
- TIntermCase *getAsCaseNode() override { return this; }
+ TIntermFunctionPrototype *getFunctionPrototype() const { return mPrototype; }
+ TIntermBlock *getBody() const { return mBody; }
- bool hasCondition() const { return mCondition != nullptr; }
- TIntermTyped *getCondition() const { return mCondition; }
+ const TFunctionSymbolInfo *getFunctionSymbolInfo() const
+ {
+ return mPrototype->getFunctionSymbolInfo();
+ }
- protected:
- TIntermTyped *mCondition;
+ private:
+ TIntermFunctionPrototype *mPrototype;
+ TIntermBlock *mBody;
};
-enum Visit
+// Struct, interface block or variable declaration. Can contain multiple variable declarators.
+class TIntermDeclaration : public TIntermNode, public TIntermAggregateBase
{
- PreVisit,
- InVisit,
- PostVisit
+ public:
+ TIntermDeclaration() : TIntermNode() {}
+ ~TIntermDeclaration() {}
+
+ TIntermDeclaration *getAsDeclarationNode() override { return this; }
+ void traverse(TIntermTraverser *it) override;
+ bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
+
+ // Only intended for initially building the declaration.
+ // The declarator node should be either TIntermSymbol or TIntermBinary with op set to
+ // EOpInitialize.
+ void appendDeclarator(TIntermTyped *declarator);
+
+ TIntermSequence *getSequence() override { return &mDeclarators; }
+ const TIntermSequence *getSequence() const override { return &mDeclarators; }
+ protected:
+ TIntermSequence mDeclarators;
};
-//
-// For traversing the tree. User should derive from this class overriding the visit functions,
-// and then pass an object of the subclass to a traverse method of a node.
-//
-// The traverse*() functions may also be overridden do other bookkeeping on the tree to provide
-// contextual information to the visit functions, such as whether the node is the target of an
-// assignment.
-//
-// 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 : angle::NonCopyable
+// Specialized declarations for attributing invariance.
+class TIntermInvariantDeclaration : public TIntermNode
{
public:
- POOL_ALLOCATOR_NEW_DELETE();
- TIntermTraverser(bool preVisit, bool inVisit, bool postVisit)
- : preVisit(preVisit),
- inVisit(inVisit),
- postVisit(postVisit),
- mDepth(0),
- mMaxDepth(0),
- mTemporaryIndex(nullptr)
- {
- }
- virtual ~TIntermTraverser() {}
-
- virtual void visitSymbol(TIntermSymbol *node) {}
- virtual void visitRaw(TIntermRaw *node) {}
- virtual void visitConstantUnion(TIntermConstantUnion *node) {}
- virtual bool visitBinary(Visit visit, TIntermBinary *node) { return true; }
- virtual bool visitUnary(Visit visit, TIntermUnary *node) { return true; }
- virtual bool visitSelection(Visit visit, TIntermSelection *node) { return true; }
- virtual bool visitSwitch(Visit visit, TIntermSwitch *node) { return true; }
- virtual bool visitCase(Visit visit, TIntermCase *node) { return true; }
- virtual bool visitAggregate(Visit visit, TIntermAggregate *node) { return true; }
- virtual bool visitLoop(Visit visit, TIntermLoop *node) { return true; }
- virtual bool visitBranch(Visit visit, TIntermBranch *node) { return true; }
-
- // The traverse functions contain logic for iterating over the children of the node
- // and calling the visit functions in the appropriate places. They also track some
- // context that may be used by the visit functions.
- virtual void traverseSymbol(TIntermSymbol *node);
- virtual void traverseRaw(TIntermRaw *node);
- virtual void traverseConstantUnion(TIntermConstantUnion *node);
- virtual void traverseBinary(TIntermBinary *node);
- virtual void traverseUnary(TIntermUnary *node);
- virtual void traverseSelection(TIntermSelection *node);
- virtual void traverseSwitch(TIntermSwitch *node);
- virtual void traverseCase(TIntermCase *node);
- virtual void traverseAggregate(TIntermAggregate *node);
- virtual void traverseLoop(TIntermLoop *node);
- virtual void traverseBranch(TIntermBranch *node);
-
- int getMaxDepth() const { return mMaxDepth; }
-
- // Return the original name if hash function pointer is NULL;
- // otherwise return the hashed name.
- static TString hash(const TString &name, ShHashFunction64 hashFunction);
-
- // If traversers need to replace nodes, they can add the replacements in
- // mReplacements/mMultiReplacements during traversal and the user of the traverser should call
- // this function after traversal to perform them.
- void updateTree();
-
- // Start creating temporary symbols from the given temporary symbol index + 1.
- void useTemporaryIndex(unsigned int *temporaryIndex);
+ TIntermInvariantDeclaration(TIntermSymbol *symbol, const TSourceLoc &line);
- protected:
- void incrementDepth(TIntermNode *current)
- {
- mDepth++;
- mMaxDepth = std::max(mMaxDepth, mDepth);
- mPath.push_back(current);
- }
+ virtual TIntermInvariantDeclaration *getAsInvariantDeclarationNode() override { return this; }
- void decrementDepth()
- {
- mDepth--;
- mPath.pop_back();
- }
+ TIntermSymbol *getSymbol() { return mSymbol; }
- TIntermNode *getParentNode()
- {
- return mPath.size() == 0 ? NULL : mPath.back();
- }
+ void traverse(TIntermTraverser *it) override;
+ bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
- void pushParentBlock(TIntermAggregate *node);
- void incrementParentBlockPos();
- void popParentBlock();
+ private:
+ TIntermSymbol *mSymbol;
+};
- bool parentNodeIsBlock()
- {
- return !mParentBlockStack.empty() && getParentNode() == mParentBlockStack.back().node;
- }
+// For ternary operators like a ? b : c.
+class TIntermTernary : public TIntermTyped
+{
+ public:
+ TIntermTernary(TIntermTyped *cond, TIntermTyped *trueExpression, TIntermTyped *falseExpression);
- const bool preVisit;
- const bool inVisit;
- const bool postVisit;
+ void traverse(TIntermTraverser *it) override;
+ bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
- int mDepth;
- int mMaxDepth;
+ TIntermTyped *getCondition() const { return mCondition; }
+ TIntermTyped *getTrueExpression() const { return mTrueExpression; }
+ TIntermTyped *getFalseExpression() const { return mFalseExpression; }
+ TIntermTernary *getAsTernaryNode() override { return this; }
- // All the nodes from root to the current node's parent during traversing.
- TVector<TIntermNode *> mPath;
+ TIntermTyped *deepCopy() const override { return new TIntermTernary(*this); }
- // To replace a single node with another on the parent node
- struct NodeUpdateEntry
- {
- NodeUpdateEntry(TIntermNode *_parent,
- TIntermNode *_original,
- TIntermNode *_replacement,
- bool _originalBecomesChildOfReplacement)
- : parent(_parent),
- original(_original),
- replacement(_replacement),
- originalBecomesChildOfReplacement(_originalBecomesChildOfReplacement) {}
-
- TIntermNode *parent;
- TIntermNode *original;
- TIntermNode *replacement;
- bool originalBecomesChildOfReplacement;
- };
-
- // To replace a single node with multiple nodes on the parent aggregate node
- struct NodeReplaceWithMultipleEntry
- {
- NodeReplaceWithMultipleEntry(TIntermAggregate *_parent, TIntermNode *_original, TIntermSequence _replacements)
- : parent(_parent),
- original(_original),
- replacements(_replacements)
- {
- }
-
- TIntermAggregate *parent;
- TIntermNode *original;
- TIntermSequence replacements;
- };
-
- // To insert multiple nodes on the parent aggregate node
- struct NodeInsertMultipleEntry
+ bool hasSideEffects() const override
{
- NodeInsertMultipleEntry(TIntermAggregate *_parent,
- TIntermSequence::size_type _position,
- TIntermSequence _insertionsBefore,
- TIntermSequence _insertionsAfter)
- : parent(_parent),
- position(_position),
- insertionsBefore(_insertionsBefore),
- insertionsAfter(_insertionsAfter)
- {
- }
-
- TIntermAggregate *parent;
- TIntermSequence::size_type position;
- TIntermSequence insertionsBefore;
- TIntermSequence insertionsAfter;
- };
-
- // During traversing, save all the changes that need to happen into
- // mReplacements/mMultiReplacements, then do them by calling updateTree().
- // Multi replacements are processed after single replacements.
- std::vector<NodeUpdateEntry> mReplacements;
- std::vector<NodeReplaceWithMultipleEntry> mMultiReplacements;
- std::vector<NodeInsertMultipleEntry> mInsertions;
-
- // Helper to insert statements in the parent block (sequence) of the node currently being traversed.
- // The statements will be inserted before the node being traversed once updateTree is called.
- // Should only be called during PreVisit or PostVisit from sequence nodes.
- // Note that inserting more than one set of nodes to the same parent node on a single updateTree call is not
- // supported.
- void insertStatementsInParentBlock(const TIntermSequence &insertions);
-
- // Same as above, but supports simultaneous insertion of statements before and after the node
- // currently being traversed.
- void insertStatementsInParentBlock(const TIntermSequence &insertionsBefore,
- const TIntermSequence &insertionsAfter);
-
- // Helper to create a temporary symbol node with the given qualifier.
- TIntermSymbol *createTempSymbol(const TType &type, TQualifier qualifier);
- // Helper to create a temporary symbol node.
- TIntermSymbol *createTempSymbol(const TType &type);
- // Create a node that declares but doesn't initialize a temporary symbol.
- TIntermAggregate *createTempDeclaration(const TType &type);
- // Create a node that initializes the current temporary symbol with initializer having the given qualifier.
- TIntermAggregate *createTempInitDeclaration(TIntermTyped *initializer, TQualifier qualifier);
- // Create a node that initializes the current temporary symbol with initializer.
- TIntermAggregate *createTempInitDeclaration(TIntermTyped *initializer);
- // Create a node that assigns rightNode to the current temporary symbol.
- TIntermBinary *createTempAssignment(TIntermTyped *rightNode);
- // Increment temporary symbol index.
- void nextTemporaryIndex();
+ return mCondition->hasSideEffects() || mTrueExpression->hasSideEffects() ||
+ mFalseExpression->hasSideEffects();
+ }
+
+ TIntermTyped *fold();
private:
- struct ParentBlock
- {
- ParentBlock(TIntermAggregate *nodeIn, TIntermSequence::size_type posIn)
- : node(nodeIn),
- pos(posIn)
- {
- }
-
- TIntermAggregate *node;
- TIntermSequence::size_type pos;
- };
- // All the code blocks from the root to the current node's parent during traversal.
- std::vector<ParentBlock> mParentBlockStack;
-
- unsigned int *mTemporaryIndex;
+ TIntermTernary(const TIntermTernary &node); // Note: not deleted, just private!
+
+ static TQualifier DetermineQualifier(TIntermTyped *cond,
+ TIntermTyped *trueExpression,
+ TIntermTyped *falseExpression);
+
+ TIntermTyped *mCondition;
+ TIntermTyped *mTrueExpression;
+ TIntermTyped *mFalseExpression;
};
-// Traverser parent class that tracks where a node is a destination of a write operation and so is
-// required to be an l-value.
-class TLValueTrackingTraverser : public TIntermTraverser
+class TIntermIfElse : public TIntermNode
{
public:
- TLValueTrackingTraverser(bool preVisit,
- bool inVisit,
- bool postVisit,
- const TSymbolTable &symbolTable,
- int shaderVersion)
- : TIntermTraverser(preVisit, inVisit, postVisit),
- mOperatorRequiresLValue(false),
- mInFunctionCallOutParameter(false),
- mSymbolTable(symbolTable),
- mShaderVersion(shaderVersion)
- {
- }
- virtual ~TLValueTrackingTraverser() {}
+ TIntermIfElse(TIntermTyped *cond, TIntermBlock *trueB, TIntermBlock *falseB);
- void traverseBinary(TIntermBinary *node) override;
- void traverseUnary(TIntermUnary *node) override;
- void traverseAggregate(TIntermAggregate *node) override;
+ void traverse(TIntermTraverser *it) override;
+ bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
- protected:
- bool isLValueRequiredHere() const
- {
- return mOperatorRequiresLValue || mInFunctionCallOutParameter;
- }
+ TIntermTyped *getCondition() const { return mCondition; }
+ TIntermBlock *getTrueBlock() const { return mTrueBlock; }
+ TIntermBlock *getFalseBlock() const { return mFalseBlock; }
+ TIntermIfElse *getAsIfElseNode() override { return this; }
- // Return true if the prototype or definition of the function being called has been encountered
- // during traversal.
- bool isInFunctionMap(const TIntermAggregate *callNode) const;
+ protected:
+ TIntermTyped *mCondition;
+ TIntermBlock *mTrueBlock;
+ TIntermBlock *mFalseBlock;
+};
- private:
- // Track whether an l-value is required in the node that is currently being traversed by the
- // surrounding operator.
- // Use isLValueRequiredHere to check all conditions which require an l-value.
- void setOperatorRequiresLValue(bool lValueRequired)
- {
- mOperatorRequiresLValue = lValueRequired;
- }
- bool operatorRequiresLValue() const { return mOperatorRequiresLValue; }
+//
+// Switch statement.
+//
+class TIntermSwitch : public TIntermNode
+{
+ public:
+ TIntermSwitch(TIntermTyped *init, TIntermBlock *statementList);
- // Add a function encountered during traversal to the function map.
- void addToFunctionMap(const TName &name, TIntermSequence *paramSequence);
+ void traverse(TIntermTraverser *it) override;
+ bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
- // Return the parameters sequence from the function definition or prototype.
- TIntermSequence *getFunctionParameters(const TIntermAggregate *callNode);
+ TIntermSwitch *getAsSwitchNode() override { return this; }
- // Track whether an l-value is required inside a function call.
- void setInFunctionCallOutParameter(bool inOutParameter);
- bool isInFunctionCallOutParameter() const;
+ TIntermTyped *getInit() { return mInit; }
+ TIntermBlock *getStatementList() { return mStatementList; }
- bool mOperatorRequiresLValue;
- bool mInFunctionCallOutParameter;
+ // Must be called with a non-null statementList.
+ void setStatementList(TIntermBlock *statementList);
- struct TNameComparator
- {
- bool operator()(const TName &a, const TName &b) const
- {
- int compareResult = a.getString().compare(b.getString());
- if (compareResult != 0)
- return compareResult < 0;
- // Internal functions may have same names as non-internal functions.
- return !a.isInternal() && b.isInternal();
- }
- };
-
- // Map from mangled function names to their parameter sequences
- TMap<TName, TIntermSequence *, TNameComparator> mFunctionMap;
-
- const TSymbolTable &mSymbolTable;
- const int mShaderVersion;
+ protected:
+ TIntermTyped *mInit;
+ TIntermBlock *mStatementList;
};
//
-// For traversing the tree, and computing max depth.
-// Takes a maximum depth limit to prevent stack overflow.
+// Case label.
//
-class TMaxDepthTraverser : public TIntermTraverser
+class TIntermCase : public TIntermNode
{
public:
- POOL_ALLOCATOR_NEW_DELETE();
- TMaxDepthTraverser(int depthLimit)
- : TIntermTraverser(true, true, false),
- mDepthLimit(depthLimit) { }
+ TIntermCase(TIntermTyped *condition) : TIntermNode(), mCondition(condition) {}
- bool visitBinary(Visit, TIntermBinary *) override { return depthCheck(); }
- bool visitUnary(Visit, TIntermUnary *) override { return depthCheck(); }
- bool visitSelection(Visit, TIntermSelection *) override { return depthCheck(); }
- bool visitAggregate(Visit, TIntermAggregate *) override { return depthCheck(); }
- bool visitLoop(Visit, TIntermLoop *) override { return depthCheck(); }
- bool visitBranch(Visit, TIntermBranch *) override { return depthCheck(); }
+ void traverse(TIntermTraverser *it) override;
+ bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
- protected:
- bool depthCheck() const { return mMaxDepth < mDepthLimit; }
+ TIntermCase *getAsCaseNode() override { return this; }
- int mDepthLimit;
+ bool hasCondition() const { return mCondition != nullptr; }
+ TIntermTyped *getCondition() const { return mCondition; }
+
+ protected:
+ TIntermTyped *mCondition;
};
+} // namespace sh
+
#endif // COMPILER_TRANSLATOR_INTERMNODE_H_