Commit 4db7ded5 by Olli Etuaho Committed by Commit Bot

Change comma nodes to TIntermBinary

Comma nodes always have just two parameters. If there's an expression with several commas in the middle, it's parsed as a tree of comma operations. It makes more sense to represent it as a binary node rather than an aggregate node. After this patch, TIntermAggregate is still used for function prototypes, function parameter lists, function calls, and variable and invariant declarations. BUG=angleproject:1490 TEST=angle_unittests, angle_end2end_tests Change-Id: I66be10624bf27bcf25987b4d93958d4a07600771 Reviewed-on: https://chromium-review.googlesource.com/397320Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent 13e4d21b
...@@ -475,8 +475,8 @@ bool parentUsesResult(TIntermNode* parent, TIntermNode* node) ...@@ -475,8 +475,8 @@ bool parentUsesResult(TIntermNode* parent, TIntermNode* node)
{ {
return false; return false;
} }
TIntermAggregate *aggParent = parent->getAsAggregate(); TIntermBinary *binaryParent = parent->getAsBinaryNode();
if (aggParent && aggParent->getOp() == EOpComma && (aggParent->getSequence()->back() != node)) if (binaryParent && binaryParent->getOp() == EOpComma && (binaryParent->getRight() != node))
{ {
return false; return false;
} }
......
...@@ -823,6 +823,18 @@ void TIntermSwizzle::writeOffsetsAsXYZW(TInfoSinkBase *out) const ...@@ -823,6 +823,18 @@ void TIntermSwizzle::writeOffsetsAsXYZW(TInfoSinkBase *out) const
} }
} }
TQualifier TIntermBinary::GetCommaQualifier(int shaderVersion,
const TIntermTyped *left,
const TIntermTyped *right)
{
// ESSL3.00 section 12.43: The result of a sequence operator is not a constant-expression.
if (shaderVersion >= 300 || left->getQualifier() != EvqConst ||
right->getQualifier() != EvqConst)
{
return EvqTemporary;
}
return EvqConst;
}
// Establishes the type of the result of the binary operation. // Establishes the type of the result of the binary operation.
void TIntermBinary::promote() void TIntermBinary::promote()
...@@ -830,6 +842,13 @@ void TIntermBinary::promote() ...@@ -830,6 +842,13 @@ void TIntermBinary::promote()
ASSERT(!isMultiplication() || ASSERT(!isMultiplication() ||
mOp == GetMulOpBasedOnOperands(mLeft->getType(), mRight->getType())); mOp == GetMulOpBasedOnOperands(mLeft->getType(), mRight->getType()));
// Comma is handled as a special case.
if (mOp == EOpComma)
{
setType(mRight->getType());
return;
}
// Base assumption: just make the type the same as the left // Base assumption: just make the type the same as the left
// operand. Then only deviations from this need be coded. // operand. Then only deviations from this need be coded.
setType(mLeft->getType()); setType(mLeft->getType());
......
...@@ -462,6 +462,9 @@ class TIntermBinary : public TIntermOperator ...@@ -462,6 +462,9 @@ class TIntermBinary : public TIntermOperator
static TOperator GetMulOpBasedOnOperands(const TType &left, const TType &right); static TOperator GetMulOpBasedOnOperands(const TType &left, const TType &right);
static TOperator GetMulAssignOpBasedOnOperands(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; }; TIntermBinary *getAsBinaryNode() override { return this; };
void traverse(TIntermTraverser *it) override; void traverse(TIntermTraverser *it) override;
......
...@@ -198,19 +198,11 @@ TIntermNode *TIntermediate::addIfElse(TIntermTyped *cond, ...@@ -198,19 +198,11 @@ TIntermNode *TIntermediate::addIfElse(TIntermTyped *cond,
return node; return node;
} }
TIntermTyped *TIntermediate::addComma(TIntermTyped *left, TIntermTyped *TIntermediate::AddComma(TIntermTyped *left,
TIntermTyped *right, TIntermTyped *right,
const TSourceLoc &line, const TSourceLoc &line,
int shaderVersion) int shaderVersion)
{ {
TQualifier resultQualifier = EvqConst;
// ESSL3.00 section 12.43: The result of a sequence operator is not a constant-expression.
if (shaderVersion >= 300 || left->getQualifier() != EvqConst ||
right->getQualifier() != EvqConst)
{
resultQualifier = EvqTemporary;
}
TIntermTyped *commaNode = nullptr; TIntermTyped *commaNode = nullptr;
if (!left->hasSideEffects()) if (!left->hasSideEffects())
{ {
...@@ -218,10 +210,10 @@ TIntermTyped *TIntermediate::addComma(TIntermTyped *left, ...@@ -218,10 +210,10 @@ TIntermTyped *TIntermediate::addComma(TIntermTyped *left,
} }
else else
{ {
commaNode = growAggregate(left, right, line); commaNode = new TIntermBinary(EOpComma, left, right);
commaNode->getAsAggregate()->setOp(EOpComma); commaNode->setLine(line);
commaNode->setType(right->getType());
} }
TQualifier resultQualifier = TIntermBinary::GetCommaQualifier(shaderVersion, left, right);
commaNode->getTypePointer()->setQualifier(resultQualifier); commaNode->getTypePointer()->setQualifier(resultQualifier);
return commaNode; return commaNode;
} }
......
...@@ -48,7 +48,7 @@ class TIntermediate ...@@ -48,7 +48,7 @@ class TIntermediate
const TSourceLoc &line); const TSourceLoc &line);
TIntermCase *addCase( TIntermCase *addCase(
TIntermTyped *condition, const TSourceLoc &line); TIntermTyped *condition, const TSourceLoc &line);
TIntermTyped *addComma(TIntermTyped *left, static TIntermTyped *AddComma(TIntermTyped *left,
TIntermTyped *right, TIntermTyped *right,
const TSourceLoc &line, const TSourceLoc &line,
int shaderVersion); int shaderVersion);
......
...@@ -300,6 +300,9 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node) ...@@ -300,6 +300,9 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node)
TInfoSinkBase &out = objSink(); TInfoSinkBase &out = objSink();
switch (node->getOp()) switch (node->getOp())
{ {
case EOpComma:
writeTriplet(visit, "(", ", ", ")");
break;
case EOpInitialize: case EOpInitialize:
if (visit == InVisit) if (visit == InVisit)
{ {
...@@ -412,7 +415,8 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node) ...@@ -412,7 +415,8 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node)
if (visit == InVisit) if (visit == InVisit)
{ {
out << "."; out << ".";
const TInterfaceBlock *interfaceBlock = node->getLeft()->getType().getInterfaceBlock(); const TInterfaceBlock *interfaceBlock =
node->getLeft()->getType().getInterfaceBlock();
const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion(); const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion();
const TField *field = interfaceBlock->fields()[index->getIConst(0)]; const TField *field = interfaceBlock->fields()[index->getIConst(0)];
...@@ -941,9 +945,6 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) ...@@ -941,9 +945,6 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
case EOpVectorNotEqual: case EOpVectorNotEqual:
writeBuiltInFunctionTriplet(visit, "notEqual(", useEmulatedFunction); writeBuiltInFunctionTriplet(visit, "notEqual(", useEmulatedFunction);
break; break;
case EOpComma:
writeTriplet(visit, "(", ", ", ")");
break;
case EOpMod: case EOpMod:
writeBuiltInFunctionTriplet(visit, "mod(", useEmulatedFunction); writeBuiltInFunctionTriplet(visit, "mod(", useEmulatedFunction);
......
...@@ -867,6 +867,9 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) ...@@ -867,6 +867,9 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
switch (node->getOp()) switch (node->getOp())
{ {
case EOpComma:
outputTriplet(out, visit, "(", ", ", ")");
break;
case EOpAssign: case EOpAssign:
if (node->getLeft()->isArray()) if (node->getLeft()->isArray())
{ {
...@@ -885,7 +888,8 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) ...@@ -885,7 +888,8 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
out << ")"; out << ")";
return false; return false;
} }
// ArrayReturnValueToOutParameter should have eliminated expressions where a function call is assigned. // ArrayReturnValueToOutParameter should have eliminated expressions where a
// function call is assigned.
ASSERT(rightAgg == nullptr || rightAgg->getOp() != EOpFunctionCall); ASSERT(rightAgg == nullptr || rightAgg->getOp() != EOpFunctionCall);
const TString &functionName = addArrayAssignmentFunction(node->getType()); const TString &functionName = addArrayAssignmentFunction(node->getType());
...@@ -904,11 +908,13 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) ...@@ -904,11 +908,13 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
TIntermTyped *expression = node->getRight(); TIntermTyped *expression = node->getRight();
// Global initializers must be constant at this point. // Global initializers must be constant at this point.
ASSERT(symbolNode->getQualifier() != EvqGlobal || canWriteAsHLSLLiteral(expression)); ASSERT(symbolNode->getQualifier() != EvqGlobal ||
canWriteAsHLSLLiteral(expression));
// GLSL allows to write things like "float x = x;" where a new variable x is defined // GLSL allows to write things like "float x = x;" where a new variable x is defined
// and the value of an existing variable x is assigned. HLSL uses C semantics (the // and the value of an existing variable x is assigned. HLSL uses C semantics (the
// new variable is created before the assignment is evaluated), so we need to convert // new variable is created before the assignment is evaluated), so we need to
// convert
// this to "float t = x, x = t;". // this to "float t = x, x = t;".
if (writeSameSymbolInitializer(out, symbolNode, expression)) if (writeSameSymbolInitializer(out, symbolNode, expression))
{ {
...@@ -1642,9 +1648,6 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) ...@@ -1642,9 +1648,6 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
return false; return false;
} }
break; break;
case EOpComma:
outputTriplet(out, visit, "(", ", ", ")");
break;
case EOpFunctionCall: case EOpFunctionCall:
{ {
TIntermSequence *arguments = node->getSequence(); TIntermSequence *arguments = node->getSequence();
......
...@@ -3630,7 +3630,7 @@ TIntermTyped *TParseContext::addComma(TIntermTyped *left, ...@@ -3630,7 +3630,7 @@ TIntermTyped *TParseContext::addComma(TIntermTyped *left,
","); ",");
} }
return intermediate.addComma(left, right, loc, mShaderVersion); return TIntermediate::AddComma(left, right, loc, mShaderVersion);
} }
TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc) TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc)
......
...@@ -57,7 +57,7 @@ void SplitSequenceOperatorTraverser::nextIteration() ...@@ -57,7 +57,7 @@ void SplitSequenceOperatorTraverser::nextIteration()
nextTemporaryIndex(); nextTemporaryIndex();
} }
bool SplitSequenceOperatorTraverser::visitBinary(Visit visit, TIntermBinary *node) bool SplitSequenceOperatorTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
{ {
if (mFoundExpressionToSplit) if (mFoundExpressionToSplit)
return false; return false;
...@@ -65,15 +65,14 @@ bool SplitSequenceOperatorTraverser::visitBinary(Visit visit, TIntermBinary *nod ...@@ -65,15 +65,14 @@ bool SplitSequenceOperatorTraverser::visitBinary(Visit visit, TIntermBinary *nod
if (mInsideSequenceOperator > 0 && visit == PreVisit) if (mInsideSequenceOperator > 0 && visit == PreVisit)
{ {
// Detect expressions that need to be simplified // Detect expressions that need to be simplified
mFoundExpressionToSplit = mFoundExpressionToSplit = mPatternToSplitMatcher.match(node, getParentNode());
mPatternToSplitMatcher.match(node, getParentNode(), isLValueRequiredHere());
return !mFoundExpressionToSplit; return !mFoundExpressionToSplit;
} }
return true; return true;
} }
bool SplitSequenceOperatorTraverser::visitAggregate(Visit visit, TIntermAggregate *node) bool SplitSequenceOperatorTraverser::visitBinary(Visit visit, TIntermBinary *node)
{ {
if (node->getOp() == EOpComma) if (node->getOp() == EOpComma)
{ {
...@@ -91,19 +90,12 @@ bool SplitSequenceOperatorTraverser::visitAggregate(Visit visit, TIntermAggregat ...@@ -91,19 +90,12 @@ bool SplitSequenceOperatorTraverser::visitAggregate(Visit visit, TIntermAggregat
// execution order. // execution order.
if (mFoundExpressionToSplit && mInsideSequenceOperator == 1) if (mFoundExpressionToSplit && mInsideSequenceOperator == 1)
{ {
// Move all operands of the sequence operation except the last one into separate // Move the left side operand into a separate statement in the parent block.
// statements in the parent block.
TIntermSequence insertions; TIntermSequence insertions;
for (auto *sequenceChild : *node->getSequence()) insertions.push_back(node->getLeft());
{
if (sequenceChild != node->getSequence()->back())
{
insertions.push_back(sequenceChild);
}
}
insertStatementsInParentBlock(insertions); insertStatementsInParentBlock(insertions);
// Replace the sequence with its last operand // Replace the comma node with its right side operand.
queueReplacement(node, node->getSequence()->back(), OriginalNode::IS_DROPPED); queueReplacement(node, node->getRight(), OriginalNode::IS_DROPPED);
} }
mInsideSequenceOperator--; mInsideSequenceOperator--;
} }
...@@ -116,7 +108,8 @@ bool SplitSequenceOperatorTraverser::visitAggregate(Visit visit, TIntermAggregat ...@@ -116,7 +108,8 @@ bool SplitSequenceOperatorTraverser::visitAggregate(Visit visit, TIntermAggregat
if (mInsideSequenceOperator > 0 && visit == PreVisit) if (mInsideSequenceOperator > 0 && visit == PreVisit)
{ {
// Detect expressions that need to be simplified // Detect expressions that need to be simplified
mFoundExpressionToSplit = mPatternToSplitMatcher.match(node, getParentNode()); mFoundExpressionToSplit =
mPatternToSplitMatcher.match(node, getParentNode(), isLValueRequiredHere());
return !mFoundExpressionToSplit; return !mFoundExpressionToSplit;
} }
......
...@@ -105,6 +105,9 @@ bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node) ...@@ -105,6 +105,9 @@ bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node)
switch (node->getOp()) switch (node->getOp())
{ {
case EOpComma:
out << "comma";
break;
case EOpAssign: case EOpAssign:
out << "move second child to first child"; out << "move second child to first child";
break; break;
...@@ -399,7 +402,6 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node) ...@@ -399,7 +402,6 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
switch (node->getOp()) switch (node->getOp())
{ {
case EOpComma: out << "Comma\n"; return true;
case EOpFunctionCall: case EOpFunctionCall:
OutputFunction(out, "Function Call", node->getFunctionSymbolInfo()); OutputFunction(out, "Function Call", node->getFunctionSymbolInfo());
break; break;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment