Commit 03d863c8 by Jamie Madill Committed by Commit Bot

translator: Refactor node replacement APIs.

BUG=angleproject:851 Change-Id: I50c3b3a4f00b27fed85f09509738513a441c7b5b Reviewed-on: https://chromium-review.googlesource.com/363990Reviewed-by: 's avatarOlli Etuaho <oetuaho@nvidia.com> Reviewed-by: 's avatarZhenyao Mo <zmo@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 64ae9952
......@@ -103,7 +103,8 @@ bool ArrayReturnValueToOutParameterTraverser::visitAggregate(Visit visit, TInter
replacementParams->getSequence()->push_back(CreateReturnValueOutSymbol(node->getType()));
replacementParams->setLine(params->getLine());
replaceWithParent(node, params, replacementParams);
queueReplacementWithParent(node, params, replacementParams,
OriginalNode::IS_DROPPED);
node->setType(TType(EbtVoid));
......@@ -122,7 +123,7 @@ bool ArrayReturnValueToOutParameterTraverser::visitAggregate(Visit visit, TInter
replacement->setLine(node->getLine());
replacement->setType(TType(EbtVoid));
replace(node, replacement);
queueReplacement(node, replacement, OriginalNode::IS_DROPPED);
}
else if (node->getOp() == EOpFunctionCall)
{
......@@ -192,7 +193,7 @@ bool ArrayReturnValueToOutParameterTraverser::visitBinary(Visit visit, TIntermBi
if (rightAgg != nullptr && rightAgg->getOp() == EOpFunctionCall && rightAgg->isUserDefined())
{
TIntermAggregate *replacementCall = CreateReplacementCall(rightAgg, node->getLeft());
replace(node, replacementCall);
queueReplacement(node, replacementCall, OriginalNode::IS_DROPPED);
}
}
return false;
......
......@@ -130,7 +130,7 @@ bool DeferGlobalInitializersTraverser::visitBinary(Visit visit, TIntermBinary *n
ASSERT(symbolNode->getQualifier() == EvqGlobal);
}
// Remove the initializer from the global scope and just declare the global instead.
mReplacements.push_back(NodeUpdateEntry(getParentNode(), node, symbolNode, false));
queueReplacement(node, symbolNode, OriginalNode::IS_DROPPED);
}
}
return false;
......
......@@ -495,9 +495,8 @@ void EmulatePrecision::visitSymbol(TIntermSymbol *node)
{
if (canRoundFloat(node->getType()) && !mDeclaringVariables && !isLValueRequiredHere())
{
TIntermNode *parent = getParentNode();
TIntermNode *replacement = createRoundingFunctionCallNode(node);
mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true));
queueReplacement(node, replacement, OriginalNode::BECOMES_CHILD);
}
}
......@@ -543,7 +542,7 @@ bool EmulatePrecision::visitBinary(Visit visit, TIntermBinary *node)
break;
}
TIntermNode *replacement = createRoundingFunctionCallNode(node);
mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true));
queueReplacement(node, replacement, OriginalNode::BECOMES_CHILD);
break;
}
......@@ -553,10 +552,9 @@ bool EmulatePrecision::visitBinary(Visit visit, TIntermBinary *node)
mEmulateCompoundAdd.insert(
TypePair(type.getBuiltInTypeNameString(),
node->getRight()->getType().getBuiltInTypeNameString()));
TIntermNode *parent = getParentNode();
TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(
node->getLeft(), node->getRight(), "add");
mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, false));
queueReplacement(node, replacement, OriginalNode::IS_DROPPED);
break;
}
case EOpSubAssign:
......@@ -564,10 +562,9 @@ bool EmulatePrecision::visitBinary(Visit visit, TIntermBinary *node)
mEmulateCompoundSub.insert(
TypePair(type.getBuiltInTypeNameString(),
node->getRight()->getType().getBuiltInTypeNameString()));
TIntermNode *parent = getParentNode();
TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(
node->getLeft(), node->getRight(), "sub");
mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, false));
queueReplacement(node, replacement, OriginalNode::IS_DROPPED);
break;
}
case EOpMulAssign:
......@@ -579,10 +576,9 @@ bool EmulatePrecision::visitBinary(Visit visit, TIntermBinary *node)
mEmulateCompoundMul.insert(
TypePair(type.getBuiltInTypeNameString(),
node->getRight()->getType().getBuiltInTypeNameString()));
TIntermNode *parent = getParentNode();
TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(
node->getLeft(), node->getRight(), "mul");
mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, false));
queueReplacement(node, replacement, OriginalNode::IS_DROPPED);
break;
}
case EOpDivAssign:
......@@ -590,10 +586,9 @@ bool EmulatePrecision::visitBinary(Visit visit, TIntermBinary *node)
mEmulateCompoundDiv.insert(
TypePair(type.getBuiltInTypeNameString(),
node->getRight()->getType().getBuiltInTypeNameString()));
TIntermNode *parent = getParentNode();
TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(
node->getLeft(), node->getRight(), "div");
mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, false));
queueReplacement(node, replacement, OriginalNode::IS_DROPPED);
break;
}
default:
......@@ -649,7 +644,7 @@ bool EmulatePrecision::visitAggregate(Visit visit, TIntermAggregate *node)
parentUsesResult(parent, node))
{
TIntermNode *replacement = createRoundingFunctionCallNode(node);
mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true));
queueReplacement(node, replacement, OriginalNode::BECOMES_CHILD);
}
}
break;
......@@ -659,7 +654,7 @@ bool EmulatePrecision::visitAggregate(Visit visit, TIntermAggregate *node)
if (canRoundFloat(node->getType()) && visit == PreVisit && parentUsesResult(parent, node))
{
TIntermNode *replacement = createRoundingFunctionCallNode(node);
mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true));
queueReplacement(node, replacement, OriginalNode::BECOMES_CHILD);
}
break;
}
......@@ -681,9 +676,8 @@ bool EmulatePrecision::visitUnary(Visit visit, TIntermUnary *node)
default:
if (canRoundFloat(node->getType()) && visit == PreVisit)
{
TIntermNode *parent = getParentNode();
TIntermNode *replacement = createRoundingFunctionCallNode(node);
mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true));
queueReplacement(node, replacement, OriginalNode::BECOMES_CHILD);
}
break;
}
......
......@@ -122,7 +122,7 @@ bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node)
current = div;
}
replace(node, current);
queueReplacement(node, current, OriginalNode::IS_DROPPED);
return true;
}
......
......@@ -2675,19 +2675,28 @@ void TIntermTraverser::updateTree()
UNUSED_ASSERTION_VARIABLE(replaced);
}
mInsertions.clear();
clearReplacementQueue();
}
void TIntermTraverser::clearReplacementQueue()
{
mReplacements.clear();
mMultiReplacements.clear();
mInsertions.clear();
}
void TIntermTraverser::replace(TIntermNode *original, TIntermNode *replacement)
void TIntermTraverser::queueReplacement(TIntermNode *original,
TIntermNode *replacement,
OriginalNode originalStatus)
{
replaceWithParent(getParentNode(), original, replacement);
queueReplacementWithParent(getParentNode(), original, replacement, originalStatus);
}
void TIntermTraverser::replaceWithParent(TIntermNode *parent,
TIntermNode *original,
TIntermNode *replacement)
void TIntermTraverser::queueReplacementWithParent(TIntermNode *parent,
TIntermNode *original,
TIntermNode *replacement,
OriginalNode originalStatus)
{
mReplacements.push_back(NodeUpdateEntry(parent, original, replacement, false));
bool originalBecomesChild = (originalStatus == OriginalNode::BECOMES_CHILD);
mReplacements.push_back(NodeUpdateEntry(parent, original, replacement, originalBecomesChild));
}
......@@ -672,17 +672,8 @@ class TIntermTraverser : angle::NonCopyable
{
public:
POOL_ALLOCATOR_NEW_DELETE();
TIntermTraverser(bool preVisit, bool inVisit, bool postVisit)
: preVisit(preVisit),
inVisit(inVisit),
postVisit(postVisit),
mDepth(0),
mMaxDepth(0),
mInGlobalScope(true),
mTemporaryIndex(nullptr)
{
}
virtual ~TIntermTraverser() {}
TIntermTraverser(bool preVisit, bool inVisit, bool postVisit);
virtual ~TIntermTraverser();
virtual void visitSymbol(TIntermSymbol *node) {}
virtual void visitRaw(TIntermRaw *node) {}
......@@ -763,24 +754,6 @@ class TIntermTraverser : angle::NonCopyable
return !mParentBlockStack.empty() && getParentNode() == mParentBlockStack.back().node;
}
// 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
{
......@@ -846,8 +819,20 @@ class TIntermTraverser : angle::NonCopyable
// Increment temporary symbol index.
void nextTemporaryIndex();
void replace(TIntermNode *original, TIntermNode *replacement);
void replaceWithParent(TIntermNode *parent, TIntermNode *original, TIntermNode *replacement);
enum class OriginalNode
{
BECOMES_CHILD,
IS_DROPPED
};
void clearReplacementQueue();
void queueReplacement(TIntermNode *original,
TIntermNode *replacement,
OriginalNode originalStatus);
void queueReplacementWithParent(TIntermNode *parent,
TIntermNode *original,
TIntermNode *replacement,
OriginalNode originalStatus);
const bool preVisit;
const bool inVisit;
......@@ -864,11 +849,30 @@ class TIntermTraverser : angle::NonCopyable
// 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;
private:
// 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;
};
struct ParentBlock
{
ParentBlock(TIntermAggregate *nodeIn, TIntermSequence::size_type posIn)
......@@ -880,6 +884,9 @@ class TIntermTraverser : angle::NonCopyable
TIntermAggregate *node;
TIntermSequence::size_type pos;
};
std::vector<NodeUpdateEntry> mReplacements;
// All the code blocks from the root to the current node's parent during traversal.
std::vector<ParentBlock> mParentBlockStack;
......
......@@ -63,6 +63,21 @@ void TIntermBranch::traverse(TIntermTraverser *it)
it->traverseBranch(this);
}
TIntermTraverser::TIntermTraverser(bool preVisit, bool inVisit, bool postVisit)
: preVisit(preVisit),
inVisit(inVisit),
postVisit(postVisit),
mDepth(0),
mMaxDepth(0),
mInGlobalScope(true),
mTemporaryIndex(nullptr)
{
}
TIntermTraverser::~TIntermTraverser()
{
}
void TIntermTraverser::pushParentBlock(TIntermAggregate *node)
{
mParentBlockStack.push_back(ParentBlock(node, 0));
......
......@@ -128,7 +128,7 @@ void RecordConstantPrecisionTraverser::visitConstantUnion(TIntermConstantUnion *
TIntermSequence insertions;
insertions.push_back(createTempInitDeclaration(node, EvqConst));
insertStatementsInParentBlock(insertions);
mReplacements.push_back(NodeUpdateEntry(getParentNode(), node, createTempSymbol(node->getType()), false));
queueReplacement(node, createTempSymbol(node->getType()), OriginalNode::IS_DROPPED);
mFoundHigherPrecisionConstant = true;
}
......
......@@ -404,8 +404,7 @@ bool RemoveDynamicIndexingTraverser::visitBinary(Visit visit, TIntermBinary *nod
// Replace the index with the temp variable
TIntermSymbol *tempIndex = createTempSymbol(node->getRight()->getType());
NodeUpdateEntry replaceIndex(node, node->getRight(), tempIndex, false);
mReplacements.push_back(replaceIndex);
queueReplacementWithParent(node, node->getRight(), tempIndex, OriginalNode::IS_DROPPED);
}
else if (IntermNodePatternMatcher::IsDynamicIndexingOfVectorOrMatrix(node))
{
......@@ -469,9 +468,7 @@ bool RemoveDynamicIndexingTraverser::visitBinary(Visit visit, TIntermBinary *nod
CreateIndexedWriteFunctionCall(node, tempIndex, createTempSymbol(fieldType));
insertionsAfter.push_back(indexedWriteCall);
insertStatementsInParentBlock(insertionsBefore, insertionsAfter);
NodeUpdateEntry replaceIndex(getParentNode(), node, createTempSymbol(fieldType),
false);
mReplacements.push_back(replaceIndex);
queueReplacement(node, createTempSymbol(fieldType), OriginalNode::IS_DROPPED);
mUsedTreeInsertion = true;
}
else
......@@ -484,8 +481,7 @@ bool RemoveDynamicIndexingTraverser::visitBinary(Visit visit, TIntermBinary *nod
ASSERT(!mRemoveIndexSideEffectsInSubtree);
TIntermAggregate *indexingCall = CreateIndexFunctionCall(
node, node->getLeft(), EnsureSignedInt(node->getRight()));
NodeUpdateEntry replaceIndex(getParentNode(), node, indexingCall, false);
mReplacements.push_back(replaceIndex);
queueReplacement(node, indexingCall, OriginalNode::IS_DROPPED);
}
}
}
......
......@@ -75,8 +75,7 @@ bool RemovePowTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
exp->setLine(node->getLine());
exp->setType(node->getType());
NodeUpdateEntry replacePow(getParentNode(), node, exp, false);
mReplacements.push_back(replacePow);
queueReplacement(node, exp, OriginalNode::IS_DROPPED);
// If the x parameter also needs to be replaced, we need to do that in another traversal,
// since it's parent node will change in a way that's not handled correctly by updateTree().
......
......@@ -93,9 +93,7 @@ bool SeparateExpressionsTraverser::visitBinary(Visit visit, TIntermBinary *node)
insertions.push_back(createTempInitDeclaration(node->getLeft()));
insertStatementsInParentBlock(insertions);
NodeUpdateEntry replaceVariable(getParentNode(), node, createTempSymbol(node->getType()),
false);
mReplacements.push_back(replaceVariable);
queueReplacement(node, createTempSymbol(node->getType()), OriginalNode::IS_DROPPED);
return false;
}
......@@ -116,9 +114,7 @@ bool SeparateExpressionsTraverser::visitAggregate(Visit visit, TIntermAggregate
insertions.push_back(createTempInitDeclaration(CopyAggregateNode(node)));
insertStatementsInParentBlock(insertions);
NodeUpdateEntry replaceVariable(getParentNode(), node, createTempSymbol(node->getType()),
false);
mReplacements.push_back(replaceVariable);
queueReplacement(node, createTempSymbol(node->getType()), OriginalNode::IS_DROPPED);
return false;
}
......
......@@ -101,9 +101,7 @@ bool SplitSequenceOperatorTraverser::visitAggregate(Visit visit, TIntermAggregat
}
insertStatementsInParentBlock(insertions);
// Replace the sequence with its last operand
NodeUpdateEntry replaceSequence(getParentNode(), node, node->getSequence()->back(),
false);
mReplacements.push_back(replaceSequence);
queueReplacement(node, node->getSequence()->back(), OriginalNode::IS_DROPPED);
}
mInsideSequenceOperator--;
}
......
......@@ -50,8 +50,7 @@ bool UnfoldShortCircuitAST::visitBinary(Visit visit, TIntermBinary *node)
}
if (replacement)
{
mReplacements.push_back(
NodeUpdateEntry(getParentNode(), node, replacement, false));
queueReplacement(node, replacement, OriginalNode::IS_DROPPED);
}
return true;
}
......@@ -108,8 +108,7 @@ bool UnfoldShortCircuitTraverser::visitBinary(Visit visit, TIntermBinary *node)
insertStatementsInParentBlock(insertions);
NodeUpdateEntry replaceVariable(getParentNode(), node, createTempSymbol(boolType), false);
mReplacements.push_back(replaceVariable);
queueReplacement(node, createTempSymbol(boolType), OriginalNode::IS_DROPPED);
}
return false;
case EOpLogicalAnd:
......@@ -133,8 +132,7 @@ bool UnfoldShortCircuitTraverser::visitBinary(Visit visit, TIntermBinary *node)
insertStatementsInParentBlock(insertions);
NodeUpdateEntry replaceVariable(getParentNode(), node, createTempSymbol(boolType), false);
mReplacements.push_back(replaceVariable);
queueReplacement(node, createTempSymbol(boolType), OriginalNode::IS_DROPPED);
}
return false;
default:
......@@ -183,8 +181,7 @@ bool UnfoldShortCircuitTraverser::visitSelection(Visit visit, TIntermSelection *
insertStatementsInParentBlock(insertions);
TIntermSymbol *ternaryResult = createTempSymbol(node->getType());
NodeUpdateEntry replaceVariable(getParentNode(), node, ternaryResult, false);
mReplacements.push_back(replaceVariable);
queueReplacement(node, ternaryResult, OriginalNode::IS_DROPPED);
}
return false;
......@@ -207,9 +204,7 @@ bool UnfoldShortCircuitTraverser::visitAggregate(Visit visit, TIntermAggregate *
// We need to unfold the sequence (comma) operator, otherwise the evaluation order of
// statements would be messed up by unfolded operations inside.
// Don't do any other unfolding on this round of traversal.
mReplacements.clear();
mMultiReplacements.clear();
mInsertions.clear();
clearReplacementQueue();
if (!copyLoopConditionOrExpression(getParentNode(), node))
{
......@@ -227,8 +222,7 @@ bool UnfoldShortCircuitTraverser::visitAggregate(Visit visit, TIntermAggregate *
insertStatementsInParentBlock(insertions);
NodeUpdateEntry replaceVariable(getParentNode(), node, (*seq)[i], false);
mReplacements.push_back(replaceVariable);
queueReplacement(node, (*seq)[i], OriginalNode::IS_DROPPED);
}
}
}
......@@ -295,8 +289,8 @@ bool UnfoldShortCircuitTraverser::copyLoopConditionOrExpression(TIntermNode *par
{
if (mInLoopCondition)
{
mReplacements.push_back(
NodeUpdateEntry(parent, node, createTempSymbol(node->getType()), false));
queueReplacementWithParent(parent, node, createTempSymbol(node->getType()),
OriginalNode::IS_DROPPED);
TIntermAggregate *body = mParentLoop->getBody();
TIntermSequence empty;
if (mParentLoop->getType() == ELoopDoWhile)
......@@ -323,13 +317,15 @@ bool UnfoldShortCircuitTraverser::copyLoopConditionOrExpression(TIntermNode *par
{
// Move the initializer to the newly created outer scope, so that condition can
// depend on it.
mReplacements.push_back(NodeUpdateEntry(mParentLoop, initializer, nullptr, false));
queueReplacementWithParent(mParentLoop, initializer, nullptr,
OriginalNode::IS_DROPPED);
loopScope->getSequence()->push_back(initializer);
}
loopScope->getSequence()->push_back(createTempInitDeclaration(node));
loopScope->getSequence()->push_back(mParentLoop);
mReplacements.push_back(NodeUpdateEntry(mLoopParent, mParentLoop, loopScope, true));
queueReplacementWithParent(mLoopParent, mParentLoop, loopScope,
OriginalNode::BECOMES_CHILD);
// The second copy of the part of the loop condition is executed inside the loop.
TIntermSequence insertionsInLoop;
......@@ -343,7 +339,7 @@ bool UnfoldShortCircuitTraverser::copyLoopConditionOrExpression(TIntermNode *par
if (mInLoopExpression)
{
TIntermTyped *movedExpression = mParentLoop->getExpression();
mReplacements.push_back(NodeUpdateEntry(mParentLoop, movedExpression, nullptr, false));
queueReplacementWithParent(mParentLoop, movedExpression, nullptr, OriginalNode::IS_DROPPED);
TIntermAggregate *body = mParentLoop->getBody();
TIntermSequence empty;
TIntermSequence insertions;
......
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