Promote and fold indexing nodes similarly to other binary ops
Indexing nodes now get their type set in TIntermBinary::promote, same
as math and logic ops. They are also constant folded through
TIntermBinary::fold() instead of having special functions for constant
folding them in ParseContext.
Index nodes for struct and interface block member access now always
have integer type, instead of sometimes having the type of the field
they were used to access.
Usage of TIntermBinary constructor is cleaned up so only the
constructor that takes in left and right operands is used. The type
of TIntermBinary nodes is always determined automatically.
Together these changes make the code considerably cleaner.
Note that the code for constant folding for array indexing is actually
never hit because constant folding array constructors is still
intentionally disabled in the code.
BUG=angleproject:1490
TEST=angle_unittests
Change-Id: Ifcec45257476cdb0d495c7d72e3cf2f83388e8c5
Reviewed-on: https://chromium-review.googlesource.com/377961
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/compiler/translator/ArrayReturnValueToOutParameter.cpp b/src/compiler/translator/ArrayReturnValueToOutParameter.cpp
index af5bb9c..562d53d 100644
--- a/src/compiler/translator/ArrayReturnValueToOutParameter.cpp
+++ b/src/compiler/translator/ArrayReturnValueToOutParameter.cpp
@@ -167,12 +167,11 @@
// Instead of returning a value, assign to the out parameter and then return.
TIntermSequence replacements;
- TIntermBinary *replacementAssignment = new TIntermBinary(EOpAssign);
TIntermTyped *expression = node->getExpression();
ASSERT(expression != nullptr);
- replacementAssignment->setLeft(CreateReturnValueSymbol(expression->getType()));
- replacementAssignment->setRight(node->getExpression());
- replacementAssignment->setType(expression->getType());
+ TIntermSymbol *returnValueSymbol = CreateReturnValueSymbol(expression->getType());
+ TIntermBinary *replacementAssignment =
+ new TIntermBinary(EOpAssign, returnValueSymbol, expression);
replacementAssignment->setLine(expression->getLine());
replacements.push_back(replacementAssignment);
diff --git a/src/compiler/translator/BreakVariableAliasingInInnerLoops.cpp b/src/compiler/translator/BreakVariableAliasingInInnerLoops.cpp
index bca9338..aada0fa 100644
--- a/src/compiler/translator/BreakVariableAliasingInInnerLoops.cpp
+++ b/src/compiler/translator/BreakVariableAliasingInInnerLoops.cpp
@@ -68,7 +68,7 @@
TIntermBinary *bPlusZero = new TIntermBinary(EOpAdd, B, TIntermTyped::CreateZero(type));
bPlusZero->setLine(B->getLine());
- binary->setRight(bPlusZero);
+ binary->replaceChildNode(B, bPlusZero);
return true;
}
diff --git a/src/compiler/translator/DeferGlobalInitializers.cpp b/src/compiler/translator/DeferGlobalInitializers.cpp
index 76addf2..285aa18 100644
--- a/src/compiler/translator/DeferGlobalInitializers.cpp
+++ b/src/compiler/translator/DeferGlobalInitializers.cpp
@@ -101,10 +101,8 @@
// Deferral is done also in any cases where the variable has not been constant folded,
// since otherwise there's a chance that HLSL output will generate extra statements
// from the initializer expression.
- TIntermBinary *deferredInit = new TIntermBinary(EOpAssign);
- deferredInit->setLeft(symbolNode->deepCopy());
- deferredInit->setRight(node->getRight());
- deferredInit->setType(node->getType());
+ TIntermBinary *deferredInit =
+ new TIntermBinary(EOpAssign, symbolNode->deepCopy(), node->getRight());
mDeferredInitializers.push_back(deferredInit);
// Change const global to a regular global if its initialization is deferred.
diff --git a/src/compiler/translator/EmulateGLFragColorBroadcast.cpp b/src/compiler/translator/EmulateGLFragColorBroadcast.cpp
index c3aad7b..5655da9 100644
--- a/src/compiler/translator/EmulateGLFragColorBroadcast.cpp
+++ b/src/compiler/translator/EmulateGLFragColorBroadcast.cpp
@@ -47,17 +47,13 @@
TIntermBinary *GLFragColorBroadcastTraverser::constructGLFragDataNode(int index) const
{
- TType gl_FragDataElementType = TType(EbtFloat, 4);
- TType gl_FragDataType = gl_FragDataElementType;
+ TType gl_FragDataType = TType(EbtFloat, EbpMedium, EvqFragData, 4);
gl_FragDataType.setArraySize(mMaxDrawBuffers);
TIntermSymbol *symbol = new TIntermSymbol(0, "gl_FragData", gl_FragDataType);
TIntermTyped *indexNode = TIntermTyped::CreateIndexNode(index);
- TIntermBinary *binary = new TIntermBinary(EOpIndexDirect);
- binary->setLeft(symbol);
- binary->setRight(indexNode);
- binary->setType(gl_FragDataElementType);
+ TIntermBinary *binary = new TIntermBinary(EOpIndexDirect, symbol, indexNode);
return binary;
}
diff --git a/src/compiler/translator/ExpandIntegerPowExpressions.cpp b/src/compiler/translator/ExpandIntegerPowExpressions.cpp
index b78c205..9409c01 100644
--- a/src/compiler/translator/ExpandIntegerPowExpressions.cpp
+++ b/src/compiler/translator/ExpandIntegerPowExpressions.cpp
@@ -124,10 +124,7 @@
// Create a chain of n-1 multiples.
for (int i = 1; i < n; ++i)
{
- TIntermBinary *mul = new TIntermBinary(EOpMul);
- mul->setLeft(current);
- mul->setRight(createTempSymbol(lhs->getType()));
- mul->setType(node->getType());
+ TIntermBinary *mul = new TIntermBinary(EOpMul, current, createTempSymbol(lhs->getType()));
mul->setLine(node->getLine());
current = mul;
}
@@ -138,9 +135,7 @@
TConstantUnion *oneVal = new TConstantUnion();
oneVal->setFConst(1.0f);
TIntermConstantUnion *oneNode = new TIntermConstantUnion(oneVal, node->getType());
- TIntermBinary *div = new TIntermBinary(EOpDiv);
- div->setLeft(oneNode);
- div->setRight(current);
+ TIntermBinary *div = new TIntermBinary(EOpDiv, oneNode, current);
current = div;
}
diff --git a/src/compiler/translator/InitializeVariables.cpp b/src/compiler/translator/InitializeVariables.cpp
index 6b01d62..8332385 100644
--- a/src/compiler/translator/InitializeVariables.cpp
+++ b/src/compiler/translator/InitializeVariables.cpp
@@ -99,10 +99,9 @@
for (unsigned int i = 0; i < var.arraySize; ++i)
{
- TIntermBinary *element = new TIntermBinary(EOpIndexDirect);
- element->setLeft(new TIntermSymbol(0, name, type));
- element->setRight(TIntermTyped::CreateIndexNode(i));
- element->setType(elementType);
+ TIntermSymbol *arraySymbol = new TIntermSymbol(0, name, type);
+ TIntermBinary *element = new TIntermBinary(EOpIndexDirect, arraySymbol,
+ TIntermTyped::CreateIndexNode(i));
TIntermTyped *zero = TIntermTyped::CreateZero(elementType);
TIntermBinary *assignment = new TIntermBinary(EOpAssign, element, zero);
diff --git a/src/compiler/translator/IntermNode.cpp b/src/compiler/translator/IntermNode.cpp
index 195f807..1c0e5e5 100644
--- a/src/compiler/translator/IntermNode.cpp
+++ b/src/compiler/translator/IntermNode.cpp
@@ -93,7 +93,7 @@
return result;
}
-TIntermTyped *CreateFoldedNode(TConstantUnion *constArray,
+TIntermTyped *CreateFoldedNode(const TConstantUnion *constArray,
const TIntermTyped *originalNode,
TQualifier qualifier)
{
@@ -680,8 +680,6 @@
//
void TIntermBinary::promote()
{
- ASSERT(mLeft->isArray() == mRight->isArray());
-
ASSERT(!isMultiplication() ||
mOp == GetMulOpBasedOnOperands(mLeft->getType(), mRight->getType()));
@@ -689,11 +687,6 @@
// operand. Then only deviations from this need be coded.
setType(mLeft->getType());
- // The result gets promoted to the highest precision.
- TPrecision higherPrecision = GetHigherPrecision(
- mLeft->getPrecision(), mRight->getPrecision());
- getTypePointer()->setPrecision(higherPrecision);
-
TQualifier resultQualifier = EvqConst;
// Binary operations results in temporary variables unless both
// operands are const.
@@ -703,6 +696,62 @@
getTypePointer()->setQualifier(EvqTemporary);
}
+ // Handle indexing ops.
+ switch (mOp)
+ {
+ case EOpIndexDirect:
+ case EOpIndexIndirect:
+ if (mLeft->isArray())
+ {
+ mType.clearArrayness();
+ }
+ else if (mLeft->isMatrix())
+ {
+ setType(TType(mLeft->getBasicType(), mLeft->getPrecision(), resultQualifier,
+ static_cast<unsigned char>(mLeft->getRows())));
+ }
+ else if (mLeft->isVector())
+ {
+ setType(TType(mLeft->getBasicType(), mLeft->getPrecision(), resultQualifier));
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+ return;
+ case EOpIndexDirectStruct:
+ {
+ const TFieldList &fields = mLeft->getType().getStruct()->fields();
+ const int i = mRight->getAsConstantUnion()->getIConst(0);
+ setType(*fields[i]->type());
+ getTypePointer()->setQualifier(resultQualifier);
+ return;
+ }
+ case EOpIndexDirectInterfaceBlock:
+ {
+ const TFieldList &fields = mLeft->getType().getInterfaceBlock()->fields();
+ const int i = mRight->getAsConstantUnion()->getIConst(0);
+ setType(*fields[i]->type());
+ getTypePointer()->setQualifier(resultQualifier);
+ return;
+ }
+ case EOpVectorSwizzle:
+ {
+ auto numFields = mRight->getAsAggregate()->getSequence()->size();
+ setType(TType(mLeft->getBasicType(), mLeft->getPrecision(), resultQualifier,
+ static_cast<unsigned char>(numFields)));
+ return;
+ }
+ default:
+ break;
+ }
+
+ ASSERT(mLeft->isArray() == mRight->isArray());
+
+ // The result gets promoted to the highest precision.
+ TPrecision higherPrecision = GetHigherPrecision(mLeft->getPrecision(), mRight->getPrecision());
+ getTypePointer()->setPrecision(higherPrecision);
+
const int nominalSize =
std::max(mLeft->getNominalSize(), mRight->getNominalSize());
@@ -722,8 +771,8 @@
case EOpGreaterThan:
case EOpLessThanEqual:
case EOpGreaterThanEqual:
- setType(TType(EbtBool, EbpUndefined, resultQualifier));
- break;
+ setType(TType(EbtBool, EbpUndefined, resultQualifier));
+ break;
//
// And and Or operate on conditionals
@@ -828,8 +877,8 @@
case EOpIndexIndirect:
case EOpIndexDirectInterfaceBlock:
case EOpIndexDirectStruct:
- // TODO (oetuaho): These ops could be handled here as well (should be done closer to the
- // top of the function).
+ case EOpVectorSwizzle:
+ // These ops should be already fully handled.
UNREACHABLE();
break;
default:
@@ -838,18 +887,103 @@
}
}
-TIntermTyped *TIntermBinary::fold(TDiagnostics *diagnostics)
+const TConstantUnion *TIntermConstantUnion::foldIndexing(int index)
{
- TIntermConstantUnion *leftConstant = mLeft->getAsConstantUnion();
- TIntermConstantUnion *rightConstant = mRight->getAsConstantUnion();
- if (leftConstant == nullptr || rightConstant == nullptr)
+ if (isArray())
{
+ ASSERT(index < static_cast<int>(getType().getArraySize()));
+ TType arrayElementType = getType();
+ arrayElementType.clearArrayness();
+ size_t arrayElementSize = arrayElementType.getObjectSize();
+ return &mUnionArrayPointer[arrayElementSize * index];
+ }
+ else if (isMatrix())
+ {
+ ASSERT(index < getType().getCols());
+ int size = getType().getRows();
+ return &mUnionArrayPointer[size * index];
+ }
+ else if (isVector())
+ {
+ ASSERT(index < getType().getNominalSize());
+ return &mUnionArrayPointer[index];
+ }
+ else
+ {
+ UNREACHABLE();
return nullptr;
}
- TConstantUnion *constArray = leftConstant->foldBinary(mOp, rightConstant, diagnostics);
+}
- // Nodes may be constant folded without being qualified as constant.
- return CreateFoldedNode(constArray, this, mType.getQualifier());
+TIntermTyped *TIntermBinary::fold(TDiagnostics *diagnostics)
+{
+ TIntermConstantUnion *leftConstant = mLeft->getAsConstantUnion();
+ TIntermConstantUnion *rightConstant = mRight->getAsConstantUnion();
+ switch (mOp)
+ {
+ case EOpIndexDirect:
+ {
+ if (leftConstant == nullptr || rightConstant == nullptr)
+ {
+ return nullptr;
+ }
+ int index = rightConstant->getIConst(0);
+
+ const TConstantUnion *constArray = leftConstant->foldIndexing(index);
+ return CreateFoldedNode(constArray, this, mType.getQualifier());
+ }
+ case EOpIndexDirectStruct:
+ {
+ if (leftConstant == nullptr || rightConstant == nullptr)
+ {
+ return nullptr;
+ }
+ const TFieldList &fields = mLeft->getType().getStruct()->fields();
+ size_t index = static_cast<size_t>(rightConstant->getIConst(0));
+
+ size_t previousFieldsSize = 0;
+ for (size_t i = 0; i < index; ++i)
+ {
+ previousFieldsSize += fields[i]->type()->getObjectSize();
+ }
+
+ const TConstantUnion *constArray = leftConstant->getUnionArrayPointer();
+ return CreateFoldedNode(constArray + previousFieldsSize, this, mType.getQualifier());
+ }
+ case EOpIndexIndirect:
+ case EOpIndexDirectInterfaceBlock:
+ // Can never be constant folded.
+ return nullptr;
+ case EOpVectorSwizzle:
+ {
+ if (leftConstant == nullptr)
+ {
+ return nullptr;
+ }
+ TIntermAggregate *fieldsAgg = mRight->getAsAggregate();
+ TIntermSequence *fieldsSequence = fieldsAgg->getSequence();
+ size_t numFields = fieldsSequence->size();
+
+ TConstantUnion *constArray = new TConstantUnion[numFields];
+ for (size_t i = 0; i < numFields; i++)
+ {
+ int fieldOffset = fieldsSequence->at(i)->getAsConstantUnion()->getIConst(0);
+ constArray[i] = *leftConstant->foldIndexing(fieldOffset);
+ }
+ return CreateFoldedNode(constArray, this, mType.getQualifier());
+ }
+ default:
+ {
+ if (leftConstant == nullptr || rightConstant == nullptr)
+ {
+ return nullptr;
+ }
+ TConstantUnion *constArray = leftConstant->foldBinary(mOp, rightConstant, diagnostics);
+
+ // Nodes may be constant folded without being qualified as constant.
+ return CreateFoldedNode(constArray, this, mType.getQualifier());
+ }
+ }
}
TIntermTyped *TIntermUnary::fold(TDiagnostics *diagnostics)
diff --git a/src/compiler/translator/IntermNode.h b/src/compiler/translator/IntermNode.h
index f2cac93..7a2c363 100644
--- a/src/compiler/translator/IntermNode.h
+++ b/src/compiler/translator/IntermNode.h
@@ -359,6 +359,7 @@
TConstantUnion *foldBinary(TOperator op,
TIntermConstantUnion *rightNode,
TDiagnostics *diagnostics);
+ const TConstantUnion *foldIndexing(int index);
TConstantUnion *foldUnaryNonComponentWise(TOperator op);
TConstantUnion *foldUnaryComponentWise(TOperator op, TDiagnostics *diagnostics);
@@ -413,12 +414,7 @@
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.
- // This is only supported for math/logical ops, not indexing.
TIntermBinary(TOperator op, TIntermTyped *left, TIntermTyped *right);
TIntermTyped *deepCopy() const override { return new TIntermBinary(*this); }
@@ -435,8 +431,6 @@
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; }
TIntermTyped *fold(TDiagnostics *diagnostics);
diff --git a/src/compiler/translator/IntermTraverse.cpp b/src/compiler/translator/IntermTraverse.cpp
index 2f66ba7..79cb86d 100644
--- a/src/compiler/translator/IntermTraverse.cpp
+++ b/src/compiler/translator/IntermTraverse.cpp
@@ -147,10 +147,7 @@
ASSERT(initializer != nullptr);
TIntermSymbol *tempSymbol = createTempSymbol(initializer->getType(), qualifier);
TIntermAggregate *tempDeclaration = new TIntermAggregate(EOpDeclaration);
- TIntermBinary *tempInit = new TIntermBinary(EOpInitialize);
- tempInit->setLeft(tempSymbol);
- tempInit->setRight(initializer);
- tempInit->setType(tempSymbol->getType());
+ TIntermBinary *tempInit = new TIntermBinary(EOpInitialize, tempSymbol, initializer);
tempDeclaration->getSequence()->push_back(tempInit);
return tempDeclaration;
}
@@ -164,10 +161,7 @@
{
ASSERT(rightNode != nullptr);
TIntermSymbol *tempSymbol = createTempSymbol(rightNode->getType());
- TIntermBinary *assignment = new TIntermBinary(EOpAssign);
- assignment->setLeft(tempSymbol);
- assignment->setRight(rightNode);
- assignment->setType(tempSymbol->getType());
+ TIntermBinary *assignment = new TIntermBinary(EOpAssign, tempSymbol, rightNode);
return assignment;
}
diff --git a/src/compiler/translator/Intermediate.cpp b/src/compiler/translator/Intermediate.cpp
index b747945..4e2b8b5 100644
--- a/src/compiler/translator/Intermediate.cpp
+++ b/src/compiler/translator/Intermediate.cpp
@@ -44,15 +44,20 @@
// Returns the added node.
// The caller should set the type of the returned node.
//
-TIntermTyped *TIntermediate::addIndex(
- TOperator op, TIntermTyped *base, TIntermTyped *index, const TSourceLoc &line)
+TIntermTyped *TIntermediate::addIndex(TOperator op,
+ TIntermTyped *base,
+ TIntermTyped *index,
+ const TSourceLoc &line,
+ TDiagnostics *diagnostics)
{
- TIntermBinary *node = new TIntermBinary(op);
+ TIntermBinary *node = new TIntermBinary(op, base, index);
node->setLine(line);
- node->setLeft(base);
- node->setRight(index);
- // caller should set the type
+ TIntermTyped *folded = node->fold(diagnostics);
+ if (folded)
+ {
+ return folded;
+ }
return node;
}
@@ -312,6 +317,7 @@
{
TIntermAggregate *node = new TIntermAggregate(EOpSequence);
+ node->getTypePointer()->setQualifier(EvqConst);
node->setLine(line);
TIntermConstantUnion *constIntNode;
diff --git a/src/compiler/translator/Intermediate.h b/src/compiler/translator/Intermediate.h
index 725f74d..c8edb4e 100644
--- a/src/compiler/translator/Intermediate.h
+++ b/src/compiler/translator/Intermediate.h
@@ -26,8 +26,11 @@
TIntermSymbol *addSymbol(
int id, const TString &, const TType &, const TSourceLoc &);
- TIntermTyped *addIndex(
- TOperator op, TIntermTyped *base, TIntermTyped *index, const TSourceLoc &);
+ TIntermTyped *addIndex(TOperator op,
+ TIntermTyped *base,
+ TIntermTyped *index,
+ const TSourceLoc &line,
+ TDiagnostics *diagnostics);
TIntermTyped *addUnaryMath(
TOperator op, TIntermTyped *child, const TSourceLoc &line, const TType *funcReturnType);
TIntermAggregate *growAggregate(
diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp
index ff40e96..36922e2 100644
--- a/src/compiler/translator/ParseContext.cpp
+++ b/src/compiler/translator/ParseContext.cpp
@@ -2385,98 +2385,6 @@
return constructor;
}
-// This function returns vector field(s) being accessed from a constant vector.
-TIntermConstantUnion *TParseContext::foldVectorSwizzle(TVectorFields &fields,
- TIntermConstantUnion *baseNode,
- const TSourceLoc &location)
-{
- const TConstantUnion *unionArray = baseNode->getUnionArrayPointer();
- ASSERT(unionArray);
-
- TConstantUnion *constArray = new TConstantUnion[fields.num];
- const auto &type = baseNode->getType();
-
- for (int i = 0; i < fields.num; i++)
- {
- // Out-of-range indices should already be checked.
- ASSERT(fields.offsets[i] < type.getNominalSize());
- constArray[i] = unionArray[fields.offsets[i]];
- }
- return intermediate.addConstantUnion(constArray, type, location);
-}
-
-// This function returns the column vector being accessed from a constant matrix.
-TIntermConstantUnion *TParseContext::foldMatrixSubscript(int index,
- TIntermConstantUnion *baseNode,
- const TSourceLoc &location)
-{
- ASSERT(index < baseNode->getType().getCols());
-
- const TConstantUnion *unionArray = baseNode->getUnionArrayPointer();
- int size = baseNode->getType().getRows();
- return intermediate.addConstantUnion(&unionArray[size * index], baseNode->getType(), location);
-}
-
-// This function returns an element of an array accessed from a constant array.
-TIntermConstantUnion *TParseContext::foldArraySubscript(int index,
- TIntermConstantUnion *baseNode,
- const TSourceLoc &location)
-{
- ASSERT(index < static_cast<int>(baseNode->getArraySize()));
-
- TType arrayElementType = baseNode->getType();
- arrayElementType.clearArrayness();
- size_t arrayElementSize = arrayElementType.getObjectSize();
- const TConstantUnion *unionArray = baseNode->getUnionArrayPointer();
- return intermediate.addConstantUnion(&unionArray[arrayElementSize * index], baseNode->getType(),
- location);
-}
-
-//
-// This function returns the value of a particular field inside a constant structure from the symbol
-// table.
-// If there is an embedded/nested struct, it appropriately calls addConstStructNested or
-// addConstStructFromAggr function and returns the parse-tree with the values of the embedded/nested
-// struct.
-//
-TIntermTyped *TParseContext::addConstStruct(const TString &identifier,
- TIntermTyped *node,
- const TSourceLoc &line)
-{
- const TFieldList &fields = node->getType().getStruct()->fields();
- size_t instanceSize = 0;
-
- for (size_t index = 0; index < fields.size(); ++index)
- {
- if (fields[index]->name() == identifier)
- {
- break;
- }
- else
- {
- instanceSize += fields[index]->type()->getObjectSize();
- }
- }
-
- TIntermTyped *typedNode;
- TIntermConstantUnion *tempConstantNode = node->getAsConstantUnion();
- if (tempConstantNode)
- {
- const TConstantUnion *constArray = tempConstantNode->getUnionArrayPointer();
-
- // type will be changed in the calling function
- typedNode = intermediate.addConstantUnion(constArray + instanceSize,
- tempConstantNode->getType(), line);
- }
- else
- {
- error(line, "Cannot offset into the structure", "Error");
- return nullptr;
- }
-
- return typedNode;
-}
-
//
// Interface/uniform blocks
//
@@ -2697,8 +2605,6 @@
const TSourceLoc &location,
TIntermTyped *indexExpression)
{
- TIntermTyped *indexedExpression = NULL;
-
if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector())
{
if (baseExpression->getAsSymbolNode())
@@ -2710,6 +2616,11 @@
{
error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
}
+
+ TConstantUnion *unionArray = new TConstantUnion[1];
+ unionArray->setFConst(0.0f);
+ return intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst),
+ location);
}
TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion();
@@ -2739,151 +2650,78 @@
if (indexConstantUnion)
{
- // If the index is not qualified as constant, the behavior in the spec is undefined. This
- // applies even if ANGLE has been able to constant fold it (ANGLE may constant fold
- // expressions that are not constant expressions). The most compatible way to handle this
- // case is to report a warning instead of an error and force the index to be in the
- // correct range.
+ // If an out-of-range index is not qualified as constant, the behavior in the spec is
+ // undefined. This applies even if ANGLE has been able to constant fold it (ANGLE may
+ // constant fold expressions that are not constant expressions). The most compatible way to
+ // handle this case is to report a warning instead of an error and force the index to be in
+ // the correct range.
bool outOfRangeIndexIsError = indexExpression->getQualifier() == EvqConst;
int index = indexConstantUnion->getIConst(0);
- if (!baseExpression->isArray())
+
+ int safeIndex = -1;
+
+ if (baseExpression->isArray())
{
- // Array checks are done later because a different error message might be generated
- // based on the index in some cases.
- if (baseExpression->isVector())
+ if (baseExpression->getQualifier() == EvqFragData && index > 0)
{
- index = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
- baseExpression->getType().getNominalSize(),
- "vector field selection out of range", "[]");
+ if (mShaderSpec == SH_WEBGL2_SPEC)
+ {
+ // Error has been already generated if index is not const.
+ if (indexExpression->getQualifier() == EvqConst)
+ {
+ error(location, "", "[",
+ "array index for gl_FragData must be constant zero");
+ }
+ safeIndex = 0;
+ }
+ else if (!isExtensionEnabled("GL_EXT_draw_buffers"))
+ {
+ outOfRangeError(outOfRangeIndexIsError, location, "", "[",
+ "array index for gl_FragData must be zero when "
+ "GL_EXT_draw_buffers is disabled");
+ safeIndex = 0;
+ }
}
- else if (baseExpression->isMatrix())
+ // Only do generic out-of-range check if similar error hasn't already been reported.
+ if (safeIndex < 0)
{
- index = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
+ safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
+ baseExpression->getArraySize(),
+ "array index out of range", "[]");
+ }
+ }
+ else if (baseExpression->isMatrix())
+ {
+ safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
baseExpression->getType().getCols(),
"matrix field selection out of range", "[]");
- }
}
-
- TIntermConstantUnion *baseConstantUnion = baseExpression->getAsConstantUnion();
- if (baseConstantUnion)
+ else if (baseExpression->isVector())
{
- if (baseExpression->isArray())
- {
- index = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
- baseExpression->getArraySize(),
- "array index out of range", "[]");
- // Constant folding for array indexing.
- indexedExpression = foldArraySubscript(index, baseConstantUnion, location);
- }
- else if (baseExpression->isVector())
- {
- // Constant folding for vector indexing - reusing vector swizzle folding.
- TVectorFields fields;
- fields.num = 1;
- fields.offsets[0] = index;
- indexedExpression = foldVectorSwizzle(fields, baseConstantUnion, location);
- }
- else if (baseExpression->isMatrix())
- {
- // Constant folding for matrix indexing.
- indexedExpression = foldMatrixSubscript(index, baseConstantUnion, location);
- }
+ safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
+ baseExpression->getType().getNominalSize(),
+ "vector field selection out of range", "[]");
}
- else
+
+ ASSERT(safeIndex >= 0);
+ // Data of constant unions can't be changed, because it may be shared with other
+ // constant unions or even builtins, like gl_MaxDrawBuffers. Instead use a new
+ // sanitized object.
+ if (safeIndex != index)
{
- int safeIndex = -1;
-
- if (baseExpression->isArray())
- {
- if (baseExpression->getQualifier() == EvqFragData && index > 0)
- {
- if (mShaderSpec == SH_WEBGL2_SPEC)
- {
- // Error has been already generated if index is not const.
- if (indexExpression->getQualifier() == EvqConst)
- {
- error(location, "", "[",
- "array index for gl_FragData must be constant zero");
- }
- safeIndex = 0;
- }
- else if (!isExtensionEnabled("GL_EXT_draw_buffers"))
- {
- outOfRangeError(outOfRangeIndexIsError, location, "", "[",
- "array index for gl_FragData must be zero when "
- "GL_EXT_draw_buffers is disabled");
- safeIndex = 0;
- }
- }
- // Only do generic out-of-range check if similar error hasn't already been reported.
- if (safeIndex < 0)
- {
- safeIndex = checkIndexOutOfRange(outOfRangeIndexIsError, location, index,
- baseExpression->getArraySize(),
- "array index out of range", "[]");
- }
- }
-
- // Data of constant unions can't be changed, because it may be shared with other
- // constant unions or even builtins, like gl_MaxDrawBuffers. Instead use a new
- // sanitized object.
- if (safeIndex != -1)
- {
- TConstantUnion *safeConstantUnion = new TConstantUnion();
- safeConstantUnion->setIConst(safeIndex);
- indexConstantUnion->replaceConstantUnion(safeConstantUnion);
- }
-
- indexedExpression =
- intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location);
+ TConstantUnion *safeConstantUnion = new TConstantUnion();
+ safeConstantUnion->setIConst(safeIndex);
+ indexConstantUnion->replaceConstantUnion(safeConstantUnion);
}
+
+ return intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location,
+ &mDiagnostics);
}
else
{
- indexedExpression =
- intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location);
+ return intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location,
+ &mDiagnostics);
}
-
- if (indexedExpression == 0)
- {
- TConstantUnion *unionArray = new TConstantUnion[1];
- unionArray->setFConst(0.0f);
- indexedExpression =
- intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), location);
- }
- else if (baseExpression->isArray())
- {
- TType indexedType = baseExpression->getType();
- indexedType.clearArrayness();
- indexedExpression->setType(indexedType);
- }
- else if (baseExpression->isMatrix())
- {
- indexedExpression->setType(TType(baseExpression->getBasicType(),
- baseExpression->getPrecision(), EvqTemporary,
- static_cast<unsigned char>(baseExpression->getRows())));
- }
- else if (baseExpression->isVector())
- {
- indexedExpression->setType(
- TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary));
- }
- else
- {
- indexedExpression->setType(baseExpression->getType());
- }
-
- if (baseExpression->getType().getQualifier() == EvqConst &&
- indexExpression->getType().getQualifier() == EvqConst)
- {
- indexedExpression->getTypePointer()->setQualifier(EvqConst);
- }
- else
- {
- indexedExpression->getTypePointer()->setQualifier(EvqTemporary);
- }
-
- return indexedExpression;
}
int TParseContext::checkIndexOutOfRange(bool outOfRangeIndexIsError,
@@ -2916,11 +2754,10 @@
const TString &fieldString,
const TSourceLoc &fieldLocation)
{
- TIntermTyped *indexedExpression = NULL;
-
if (baseExpression->isArray())
{
error(fieldLocation, "cannot apply dot operator to an array", ".");
+ return baseExpression;
}
if (baseExpression->isVector())
@@ -2933,41 +2770,21 @@
fields.offsets[0] = 0;
}
- if (baseExpression->getAsConstantUnion())
- {
- // constant folding for vector fields
- indexedExpression =
- foldVectorSwizzle(fields, baseExpression->getAsConstantUnion(), fieldLocation);
- }
- else
- {
- TIntermTyped *index = intermediate.addSwizzle(fields, fieldLocation);
- indexedExpression =
- intermediate.addIndex(EOpVectorSwizzle, baseExpression, index, dotLocation);
- }
- if (indexedExpression == nullptr)
- {
- indexedExpression = baseExpression;
- }
- else
- {
- // Note that the qualifier set here will be corrected later.
- indexedExpression->setType(TType(baseExpression->getBasicType(),
- baseExpression->getPrecision(), EvqTemporary,
- static_cast<unsigned char>(fields.num)));
- }
+ TIntermTyped *index = intermediate.addSwizzle(fields, fieldLocation);
+ return intermediate.addIndex(EOpVectorSwizzle, baseExpression, index, dotLocation,
+ &mDiagnostics);
}
else if (baseExpression->getBasicType() == EbtStruct)
{
- bool fieldFound = false;
const TFieldList &fields = baseExpression->getType().getStruct()->fields();
if (fields.empty())
{
error(dotLocation, "structure has no fields", "Internal Error");
- indexedExpression = baseExpression;
+ return baseExpression;
}
else
{
+ bool fieldFound = false;
unsigned int i;
for (i = 0; i < fields.size(); ++i)
{
@@ -2979,47 +2796,29 @@
}
if (fieldFound)
{
- if (baseExpression->getAsConstantUnion())
- {
- indexedExpression = addConstStruct(fieldString, baseExpression, dotLocation);
- if (indexedExpression == 0)
- {
- indexedExpression = baseExpression;
- }
- else
- {
- indexedExpression->setType(*fields[i]->type());
- }
- }
- else
- {
- TConstantUnion *unionArray = new TConstantUnion[1];
- unionArray->setIConst(i);
- TIntermTyped *index = intermediate.addConstantUnion(
- unionArray, *fields[i]->type(), fieldLocation);
- indexedExpression = intermediate.addIndex(EOpIndexDirectStruct, baseExpression,
- index, dotLocation);
- indexedExpression->setType(*fields[i]->type());
- }
+ TIntermTyped *index = TIntermTyped::CreateIndexNode(i);
+ index->setLine(fieldLocation);
+ return intermediate.addIndex(EOpIndexDirectStruct, baseExpression, index,
+ dotLocation, &mDiagnostics);
}
else
{
error(dotLocation, " no such field in structure", fieldString.c_str());
- indexedExpression = baseExpression;
+ return baseExpression;
}
}
}
else if (baseExpression->isInterfaceBlock())
{
- bool fieldFound = false;
const TFieldList &fields = baseExpression->getType().getInterfaceBlock()->fields();
if (fields.empty())
{
error(dotLocation, "interface block has no fields", "Internal Error");
- indexedExpression = baseExpression;
+ return baseExpression;
}
else
{
+ bool fieldFound = false;
unsigned int i;
for (i = 0; i < fields.size(); ++i)
{
@@ -3031,18 +2830,15 @@
}
if (fieldFound)
{
- TConstantUnion *unionArray = new TConstantUnion[1];
- unionArray->setIConst(i);
- TIntermTyped *index =
- intermediate.addConstantUnion(unionArray, *fields[i]->type(), fieldLocation);
- indexedExpression = intermediate.addIndex(EOpIndexDirectInterfaceBlock,
- baseExpression, index, dotLocation);
- indexedExpression->setType(*fields[i]->type());
+ TIntermTyped *index = TIntermTyped::CreateIndexNode(i);
+ index->setLine(fieldLocation);
+ return intermediate.addIndex(EOpIndexDirectInterfaceBlock, baseExpression, index,
+ dotLocation, &mDiagnostics);
}
else
{
error(dotLocation, " no such field in interface block", fieldString.c_str());
- indexedExpression = baseExpression;
+ return baseExpression;
}
}
}
@@ -3060,19 +2856,8 @@
"side",
fieldString.c_str());
}
- indexedExpression = baseExpression;
+ return baseExpression;
}
-
- if (baseExpression->getQualifier() == EvqConst)
- {
- indexedExpression->getTypePointer()->setQualifier(EvqConst);
- }
- else
- {
- indexedExpression->getTypePointer()->setQualifier(EvqTemporary);
- }
-
- return indexedExpression;
}
TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType,
diff --git a/src/compiler/translator/ParseContext.h b/src/compiler/translator/ParseContext.h
index 02f6416..9ce37dc 100644
--- a/src/compiler/translator/ParseContext.h
+++ b/src/compiler/translator/ParseContext.h
@@ -284,8 +284,6 @@
TFunction *fnCall,
const TSourceLoc &line);
- TIntermTyped *addConstStruct(
- const TString &identifier, TIntermTyped *node, const TSourceLoc& line);
TIntermTyped *addIndexExpression(TIntermTyped *baseExpression,
const TSourceLoc& location,
TIntermTyped *indexExpression);
@@ -378,18 +376,6 @@
const char *reason,
const char *token);
- // Constant folding for element access. Note that the returned node does not have the correct
- // type - it is expected to be fixed later.
- TIntermConstantUnion *foldVectorSwizzle(TVectorFields &fields,
- TIntermConstantUnion *baseNode,
- const TSourceLoc &location);
- TIntermConstantUnion *foldMatrixSubscript(int index,
- TIntermConstantUnion *baseNode,
- const TSourceLoc &location);
- TIntermConstantUnion *foldArraySubscript(int index,
- TIntermConstantUnion *baseNode,
- const TSourceLoc &location);
-
bool declareVariable(const TSourceLoc &line, const TString &identifier, const TType &type, TVariable **variable);
void checkCanBeDeclaredWithoutInitializer(const TSourceLoc &line,
diff --git a/src/compiler/translator/RemoveDynamicIndexing.cpp b/src/compiler/translator/RemoveDynamicIndexing.cpp
index 37955e7..e46041d 100644
--- a/src/compiler/translator/RemoveDynamicIndexing.cpp
+++ b/src/compiler/translator/RemoveDynamicIndexing.cpp
@@ -92,21 +92,15 @@
const int index,
TQualifier baseQualifier)
{
- TIntermBinary *indexNode = new TIntermBinary(EOpIndexDirect);
- indexNode->setType(fieldType);
TIntermSymbol *baseSymbol = CreateBaseSymbol(indexedType, baseQualifier);
- indexNode->setLeft(baseSymbol);
- indexNode->setRight(CreateIntConstantNode(index));
+ TIntermBinary *indexNode =
+ new TIntermBinary(EOpIndexDirect, baseSymbol, TIntermTyped::CreateIndexNode(index));
return indexNode;
}
TIntermBinary *CreateAssignValueSymbolNode(TIntermTyped *targetNode, const TType &assignedValueType)
{
- TIntermBinary *assignNode = new TIntermBinary(EOpAssign);
- assignNode->setType(assignedValueType);
- assignNode->setLeft(targetNode);
- assignNode->setRight(CreateValueSymbol(assignedValueType));
- return assignNode;
+ return new TIntermBinary(EOpAssign, targetNode, CreateValueSymbol(assignedValueType));
}
TIntermTyped *EnsureSignedInt(TIntermTyped *node)
@@ -256,10 +250,9 @@
TIntermAggregate *bodyNode = new TIntermAggregate(EOpSequence);
bodyNode->getSequence()->push_back(switchNode);
- TIntermBinary *cond = new TIntermBinary(EOpLessThan);
+ TIntermBinary *cond =
+ new TIntermBinary(EOpLessThan, CreateIndexSymbol(), CreateIntConstantNode(0));
cond->setType(TType(EbtBool, EbpUndefined));
- cond->setLeft(CreateIndexSymbol());
- cond->setRight(CreateIntConstantNode(0));
// Two blocks: one accesses (either reads or writes) the first element and returns,
// the other accesses the last element.
diff --git a/src/compiler/translator/RewriteTexelFetchOffset.cpp b/src/compiler/translator/RewriteTexelFetchOffset.cpp
index 4ceceb2..90613d0 100644
--- a/src/compiler/translator/RewriteTexelFetchOffset.cpp
+++ b/src/compiler/translator/RewriteTexelFetchOffset.cpp
@@ -113,16 +113,11 @@
// sampler
newsequence.push_back(sequence->at(0));
- // Position+offset
- TIntermBinary *add = new TIntermBinary(EOpAdd);
- add->setType(node->getType());
// Position
TIntermTyped *texCoordNode = sequence->at(1)->getAsTyped();
ASSERT(texCoordNode);
- add->setLine(texCoordNode->getLine());
- add->setType(texCoordNode->getType());
- add->setLeft(texCoordNode);
// offset
+ TIntermTyped *offsetNode = nullptr;
ASSERT(sequence->at(3)->getAsTyped());
if (is2DArray)
{
@@ -143,12 +138,16 @@
ivec3Sequence.push_back(zeroNode);
constructIVec3Node->insertChildNodes(0, ivec3Sequence);
- add->setRight(constructIVec3Node);
+ offsetNode = constructIVec3Node;
}
else
{
- add->setRight(sequence->at(3)->getAsTyped());
+ offsetNode = sequence->at(3)->getAsTyped();
}
+
+ // Position+offset
+ TIntermBinary *add = new TIntermBinary(EOpAdd, texCoordNode, offsetNode);
+ add->setLine(texCoordNode->getLine());
newsequence.push_back(add);
// lod
diff --git a/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp b/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp
index 6a70aa5..cb69059 100644
--- a/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp
+++ b/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp
@@ -39,11 +39,7 @@
TIntermBinary *ConstructVectorIndexBinaryNode(TIntermSymbol *symbolNode, int index)
{
- TIntermBinary *binary = new TIntermBinary(EOpIndexDirect);
- binary->setLeft(symbolNode);
- TIntermTyped *indexNode = TIntermTyped::CreateIndexNode(index);
- binary->setRight(indexNode);
- return binary;
+ return new TIntermBinary(EOpIndexDirect, symbolNode, TIntermTyped::CreateIndexNode(index));
}
TIntermBinary *ConstructMatrixIndexBinaryNode(
@@ -52,11 +48,8 @@
TIntermBinary *colVectorNode =
ConstructVectorIndexBinaryNode(symbolNode, colIndex);
- TIntermBinary *binary = new TIntermBinary(EOpIndexDirect);
- binary->setLeft(colVectorNode);
- TIntermTyped *rowIndexNode = TIntermTyped::CreateIndexNode(rowIndex);
- binary->setRight(rowIndexNode);
- return binary;
+ return new TIntermBinary(EOpIndexDirect, colVectorNode,
+ TIntermTyped::CreateIndexNode(rowIndex));
}
} // namespace anonymous
@@ -268,11 +261,8 @@
type.setPrecision(mFragmentPrecisionHigh ? EbpHigh : EbpMedium);
}
- TIntermBinary *init = new TIntermBinary(EOpInitialize);
TIntermSymbol *symbolNode = new TIntermSymbol(-1, tempVarName, type);
- init->setLeft(symbolNode);
- init->setRight(original);
- init->setType(type);
+ TIntermBinary *init = new TIntermBinary(EOpInitialize, symbolNode, original);
TIntermAggregate *decl = new TIntermAggregate(EOpDeclaration);
decl->getSequence()->push_back(init);
diff --git a/src/compiler/translator/SeparateArrayInitialization.cpp b/src/compiler/translator/SeparateArrayInitialization.cpp
index de9050c..e166eac 100644
--- a/src/compiler/translator/SeparateArrayInitialization.cpp
+++ b/src/compiler/translator/SeparateArrayInitialization.cpp
@@ -69,10 +69,8 @@
replacementDeclaration->setLine(symbol->getLine());
replacements.push_back(replacementDeclaration);
- TIntermBinary *replacementAssignment = new TIntermBinary(EOpAssign);
- replacementAssignment->setLeft(symbol);
- replacementAssignment->setRight(initializer);
- replacementAssignment->setType(initializer->getType());
+ TIntermBinary *replacementAssignment =
+ new TIntermBinary(EOpAssign, symbol, initializer);
replacementAssignment->setLine(symbol->getLine());
replacements.push_back(replacementAssignment);
diff --git a/src/compiler/translator/SeparateExpressionsReturningArrays.cpp b/src/compiler/translator/SeparateExpressionsReturningArrays.cpp
index 4041be9..20e4797 100644
--- a/src/compiler/translator/SeparateExpressionsReturningArrays.cpp
+++ b/src/compiler/translator/SeparateExpressionsReturningArrays.cpp
@@ -49,11 +49,7 @@
// and also needs to be replaced in its original location by a different node.
TIntermBinary *CopyAssignmentNode(TIntermBinary *node)
{
- TIntermBinary *copyNode = new TIntermBinary(node->getOp());
- copyNode->setLeft(node->getLeft());
- copyNode->setRight(node->getRight());
- copyNode->setType(node->getType());
- return copyNode;
+ return new TIntermBinary(node->getOp(), node->getLeft(), node->getRight());
}
// Performs a shallow copy of a constructor/function call node.