summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp')
-rw-r--r--src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp630
1 files changed, 472 insertions, 158 deletions
diff --git a/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp b/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp
index 7b588ca5a3..6c25c6c35a 100644
--- a/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp
@@ -4,10 +4,15 @@
// found in the LICENSE file.
//
-#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/IntermTraverse.h"
+
#include "compiler/translator/InfoSink.h"
+#include "compiler/translator/IntermNode_util.h"
#include "compiler/translator/SymbolTable.h"
+namespace sh
+{
+
void TIntermSymbol::traverse(TIntermTraverser *it)
{
it->traverseSymbol(this);
@@ -23,6 +28,11 @@ void TIntermConstantUnion::traverse(TIntermTraverser *it)
it->traverseConstantUnion(this);
}
+void TIntermSwizzle::traverse(TIntermTraverser *it)
+{
+ it->traverseSwizzle(this);
+}
+
void TIntermBinary::traverse(TIntermTraverser *it)
{
it->traverseBinary(this);
@@ -33,9 +43,14 @@ void TIntermUnary::traverse(TIntermTraverser *it)
it->traverseUnary(this);
}
-void TIntermSelection::traverse(TIntermTraverser *it)
+void TIntermTernary::traverse(TIntermTraverser *it)
+{
+ it->traverseTernary(this);
+}
+
+void TIntermIfElse::traverse(TIntermTraverser *it)
{
- it->traverseSelection(this);
+ it->traverseIfElse(this);
}
void TIntermSwitch::traverse(TIntermTraverser *it)
@@ -48,6 +63,31 @@ void TIntermCase::traverse(TIntermTraverser *it)
it->traverseCase(this);
}
+void TIntermFunctionDefinition::traverse(TIntermTraverser *it)
+{
+ it->traverseFunctionDefinition(this);
+}
+
+void TIntermBlock::traverse(TIntermTraverser *it)
+{
+ it->traverseBlock(this);
+}
+
+void TIntermInvariantDeclaration::traverse(TIntermTraverser *it)
+{
+ it->traverseInvariantDeclaration(this);
+}
+
+void TIntermDeclaration::traverse(TIntermTraverser *it)
+{
+ it->traverseDeclaration(this);
+}
+
+void TIntermFunctionPrototype::traverse(TIntermTraverser *it)
+{
+ it->traverseFunctionPrototype(this);
+}
+
void TIntermAggregate::traverse(TIntermTraverser *it)
{
it->traverseAggregate(this);
@@ -63,7 +103,35 @@ void TIntermBranch::traverse(TIntermTraverser *it)
it->traverseBranch(this);
}
-void TIntermTraverser::pushParentBlock(TIntermAggregate *node)
+TIntermTraverser::TIntermTraverser(bool preVisit,
+ bool inVisit,
+ bool postVisit,
+ TSymbolTable *symbolTable)
+ : preVisit(preVisit),
+ inVisit(inVisit),
+ postVisit(postVisit),
+ mDepth(-1),
+ mMaxDepth(0),
+ mInGlobalScope(true),
+ mSymbolTable(symbolTable),
+ mTemporaryId(nullptr)
+{
+}
+
+TIntermTraverser::~TIntermTraverser()
+{
+}
+
+const TIntermBlock *TIntermTraverser::getParentBlock() const
+{
+ if (!mParentBlockStack.empty())
+ {
+ return mParentBlockStack.back().node;
+ }
+ return nullptr;
+}
+
+void TIntermTraverser::pushParentBlock(TIntermBlock *node)
{
mParentBlockStack.push_back(ParentBlock(node, 0));
}
@@ -89,23 +157,32 @@ void TIntermTraverser::insertStatementsInParentBlock(const TIntermSequence &inse
const TIntermSequence &insertionsAfter)
{
ASSERT(!mParentBlockStack.empty());
- NodeInsertMultipleEntry insert(mParentBlockStack.back().node, mParentBlockStack.back().pos,
- insertionsBefore, insertionsAfter);
+ ParentBlock &parentBlock = mParentBlockStack.back();
+ if (mPath.back() == parentBlock.node)
+ {
+ ASSERT(mParentBlockStack.size() >= 2u);
+ // The current node is a block node, so the parent block is not the topmost one in the block
+ // stack, but the one below that.
+ parentBlock = mParentBlockStack.at(mParentBlockStack.size() - 2u);
+ }
+ NodeInsertMultipleEntry insert(parentBlock.node, parentBlock.pos, insertionsBefore,
+ insertionsAfter);
mInsertions.push_back(insert);
}
-TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type, TQualifier qualifier)
+void TIntermTraverser::insertStatementInParentBlock(TIntermNode *statement)
{
- // Each traversal uses at most one temporary variable, so the index stays the same within a single traversal.
- TInfoSinkBase symbolNameOut;
- ASSERT(mTemporaryIndex != nullptr);
- symbolNameOut << "s" << (*mTemporaryIndex);
- TString symbolName = symbolNameOut.c_str();
+ TIntermSequence insertions;
+ insertions.push_back(statement);
+ insertStatementsInParentBlock(insertions);
+}
- TIntermSymbol *node = new TIntermSymbol(0, symbolName, type);
- node->setInternal(true);
- node->getTypePointer()->setQualifier(qualifier);
- return node;
+TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type, TQualifier qualifier)
+{
+ ASSERT(mTemporaryId != nullptr);
+ // nextTemporaryId() needs to be called when the code wants to start using another temporary
+ // symbol.
+ return CreateTempSymbolNode(*mTemporaryId, type, qualifier);
}
TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type)
@@ -113,27 +190,22 @@ TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type)
return createTempSymbol(type, EvqTemporary);
}
-TIntermAggregate *TIntermTraverser::createTempDeclaration(const TType &type)
+TIntermDeclaration *TIntermTraverser::createTempDeclaration(const TType &type)
{
- TIntermAggregate *tempDeclaration = new TIntermAggregate(EOpDeclaration);
- tempDeclaration->getSequence()->push_back(createTempSymbol(type));
+ ASSERT(mTemporaryId != nullptr);
+ TIntermDeclaration *tempDeclaration = new TIntermDeclaration();
+ tempDeclaration->appendDeclarator(CreateTempSymbolNode(*mTemporaryId, type, EvqTemporary));
return tempDeclaration;
}
-TIntermAggregate *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer, TQualifier qualifier)
+TIntermDeclaration *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer,
+ TQualifier qualifier)
{
- 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());
- tempDeclaration->getSequence()->push_back(tempInit);
- return tempDeclaration;
+ ASSERT(mTemporaryId != nullptr);
+ return CreateTempInitDeclarationNode(*mTemporaryId, initializer, qualifier);
}
-TIntermAggregate *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer)
+TIntermDeclaration *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer)
{
return createTempInitDeclaration(initializer, EvqTemporary);
}
@@ -142,39 +214,38 @@ TIntermBinary *TIntermTraverser::createTempAssignment(TIntermTyped *rightNode)
{
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;
}
-void TIntermTraverser::useTemporaryIndex(unsigned int *temporaryIndex)
+void TIntermTraverser::nextTemporaryId()
{
- mTemporaryIndex = temporaryIndex;
-}
-
-void TIntermTraverser::nextTemporaryIndex()
-{
- ASSERT(mTemporaryIndex != nullptr);
- ++(*mTemporaryIndex);
+ ASSERT(mSymbolTable);
+ if (!mTemporaryId)
+ {
+ mTemporaryId = new TSymbolUniqueId(mSymbolTable);
+ return;
+ }
+ *mTemporaryId = TSymbolUniqueId(mSymbolTable);
}
-void TLValueTrackingTraverser::addToFunctionMap(const TName &name, TIntermSequence *paramSequence)
+void TLValueTrackingTraverser::addToFunctionMap(const TSymbolUniqueId &id,
+ TIntermSequence *paramSequence)
{
- mFunctionMap[name] = paramSequence;
+ mFunctionMap[id.get()] = paramSequence;
}
bool TLValueTrackingTraverser::isInFunctionMap(const TIntermAggregate *callNode) const
{
- ASSERT(callNode->getOp() == EOpFunctionCall);
- return (mFunctionMap.find(callNode->getNameObj()) != mFunctionMap.end());
+ ASSERT(callNode->getOp() == EOpCallFunctionInAST);
+ return (mFunctionMap.find(callNode->getFunctionSymbolInfo()->getId().get()) !=
+ mFunctionMap.end());
}
TIntermSequence *TLValueTrackingTraverser::getFunctionParameters(const TIntermAggregate *callNode)
{
ASSERT(isInFunctionMap(callNode));
- return mFunctionMap[callNode->getNameObj()];
+ return mFunctionMap[callNode->getFunctionSymbolInfo()->getId().get()];
}
void TLValueTrackingTraverser::setInFunctionCallOutParameter(bool inOutParameter)
@@ -203,19 +274,41 @@ bool TLValueTrackingTraverser::isInFunctionCallOutParameter() const
//
void TIntermTraverser::traverseSymbol(TIntermSymbol *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
visitSymbol(node);
}
void TIntermTraverser::traverseConstantUnion(TIntermConstantUnion *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
visitConstantUnion(node);
}
+void TIntermTraverser::traverseSwizzle(TIntermSwizzle *node)
+{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
+ bool visit = true;
+
+ if (preVisit)
+ visit = visitSwizzle(PreVisit, node);
+
+ if (visit)
+ {
+ node->getOperand()->traverse(this);
+ }
+
+ if (visit && postVisit)
+ visitSwizzle(PostVisit, node);
+}
+
//
// Traverse a binary node.
//
void TIntermTraverser::traverseBinary(TIntermBinary *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
bool visit = true;
//
@@ -229,8 +322,6 @@ void TIntermTraverser::traverseBinary(TIntermBinary *node)
//
if (visit)
{
- incrementDepth(node);
-
if (node->getLeft())
node->getLeft()->traverse(this);
@@ -239,8 +330,6 @@ void TIntermTraverser::traverseBinary(TIntermBinary *node)
if (visit && node->getRight())
node->getRight()->traverse(this);
-
- decrementDepth();
}
//
@@ -253,6 +342,8 @@ void TIntermTraverser::traverseBinary(TIntermBinary *node)
void TLValueTrackingTraverser::traverseBinary(TIntermBinary *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
bool visit = true;
//
@@ -266,8 +357,6 @@ void TLValueTrackingTraverser::traverseBinary(TIntermBinary *node)
//
if (visit)
{
- incrementDepth(node);
-
// Some binary operations like indexing can be inside an expression which must be an
// l-value.
bool parentOperatorRequiresLValue = operatorRequiresLValue();
@@ -302,8 +391,6 @@ void TLValueTrackingTraverser::traverseBinary(TIntermBinary *node)
setOperatorRequiresLValue(parentOperatorRequiresLValue);
setInFunctionCallOutParameter(parentInFunctionCallOutParameter);
-
- decrementDepth();
}
//
@@ -319,6 +406,8 @@ void TLValueTrackingTraverser::traverseBinary(TIntermBinary *node)
//
void TIntermTraverser::traverseUnary(TIntermUnary *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
bool visit = true;
if (preVisit)
@@ -326,11 +415,7 @@ void TIntermTraverser::traverseUnary(TIntermUnary *node)
if (visit)
{
- incrementDepth(node);
-
node->getOperand()->traverse(this);
-
- decrementDepth();
}
if (visit && postVisit)
@@ -339,6 +424,8 @@ void TIntermTraverser::traverseUnary(TIntermUnary *node)
void TLValueTrackingTraverser::traverseUnary(TIntermUnary *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
bool visit = true;
if (preVisit)
@@ -346,8 +433,6 @@ void TLValueTrackingTraverser::traverseUnary(TIntermUnary *node)
if (visit)
{
- incrementDepth(node);
-
ASSERT(!operatorRequiresLValue());
switch (node->getOp())
{
@@ -364,153 +449,362 @@ void TLValueTrackingTraverser::traverseUnary(TIntermUnary *node)
node->getOperand()->traverse(this);
setOperatorRequiresLValue(false);
-
- decrementDepth();
}
if (visit && postVisit)
visitUnary(PostVisit, node);
}
-//
-// Traverse an aggregate node. Same comments in binary node apply here.
-//
-void TIntermTraverser::traverseAggregate(TIntermAggregate *node)
+// Traverse a function definition node.
+void TIntermTraverser::traverseFunctionDefinition(TIntermFunctionDefinition *node)
{
- bool visit = true;
+ ScopedNodeInTraversalPath addToPath(this, node);
- TIntermSequence *sequence = node->getSequence();
+ bool visit = true;
if (preVisit)
- visit = visitAggregate(PreVisit, node);
+ visit = visitFunctionDefinition(PreVisit, node);
if (visit)
{
- incrementDepth(node);
+ mInGlobalScope = false;
+
+ node->getFunctionPrototype()->traverse(this);
+ if (inVisit)
+ visit = visitFunctionDefinition(InVisit, node);
+ node->getBody()->traverse(this);
+
+ mInGlobalScope = true;
+ }
- if (node->getOp() == EOpSequence)
- pushParentBlock(node);
+ if (visit && postVisit)
+ visitFunctionDefinition(PostVisit, node);
+}
+// Traverse a block node.
+void TIntermTraverser::traverseBlock(TIntermBlock *node)
+{
+ ScopedNodeInTraversalPath addToPath(this, node);
+ pushParentBlock(node);
+
+ bool visit = true;
+
+ TIntermSequence *sequence = node->getSequence();
+
+ if (preVisit)
+ visit = visitBlock(PreVisit, node);
+
+ if (visit)
+ {
for (auto *child : *sequence)
{
child->traverse(this);
if (visit && inVisit)
{
if (child != sequence->back())
- visit = visitAggregate(InVisit, node);
+ visit = visitBlock(InVisit, node);
}
- if (node->getOp() == EOpSequence)
- incrementParentBlockPos();
+ incrementParentBlockPos();
}
+ }
+
+ if (visit && postVisit)
+ visitBlock(PostVisit, node);
- if (node->getOp() == EOpSequence)
- popParentBlock();
+ popParentBlock();
+}
- decrementDepth();
+void TIntermTraverser::traverseInvariantDeclaration(TIntermInvariantDeclaration *node)
+{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
+ bool visit = true;
+
+ if (preVisit)
+ {
+ visit = visitInvariantDeclaration(PreVisit, node);
+ }
+
+ if (visit)
+ {
+ node->getSymbol()->traverse(this);
+ if (postVisit)
+ {
+ visitInvariantDeclaration(PostVisit, node);
+ }
+ }
+}
+
+// Traverse a declaration node.
+void TIntermTraverser::traverseDeclaration(TIntermDeclaration *node)
+{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
+ bool visit = true;
+
+ TIntermSequence *sequence = node->getSequence();
+
+ if (preVisit)
+ visit = visitDeclaration(PreVisit, node);
+
+ if (visit)
+ {
+ for (auto *child : *sequence)
+ {
+ child->traverse(this);
+ if (visit && inVisit)
+ {
+ if (child != sequence->back())
+ visit = visitDeclaration(InVisit, node);
+ }
+ }
}
if (visit && postVisit)
- visitAggregate(PostVisit, node);
+ visitDeclaration(PostVisit, node);
}
-void TLValueTrackingTraverser::traverseAggregate(TIntermAggregate *node)
+void TIntermTraverser::traverseFunctionPrototype(TIntermFunctionPrototype *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
bool visit = true;
TIntermSequence *sequence = node->getSequence();
- switch (node->getOp())
+
+ if (preVisit)
+ visit = visitFunctionPrototype(PreVisit, node);
+
+ if (visit)
{
- case EOpFunction:
+ for (auto *child : *sequence)
{
- TIntermAggregate *params = sequence->front()->getAsAggregate();
- ASSERT(params != nullptr);
- ASSERT(params->getOp() == EOpParameters);
- addToFunctionMap(node->getNameObj(), params->getSequence());
- break;
+ child->traverse(this);
+ if (visit && inVisit)
+ {
+ if (child != sequence->back())
+ visit = visitFunctionPrototype(InVisit, node);
+ }
}
- case EOpPrototype:
- addToFunctionMap(node->getNameObj(), sequence);
- break;
- default:
- break;
}
+ if (visit && postVisit)
+ visitFunctionPrototype(PostVisit, node);
+}
+
+// Traverse an aggregate node. Same comments in binary node apply here.
+void TIntermTraverser::traverseAggregate(TIntermAggregate *node)
+{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
+ bool visit = true;
+
+ TIntermSequence *sequence = node->getSequence();
+
if (preVisit)
visit = visitAggregate(PreVisit, node);
if (visit)
{
- bool inFunctionMap = false;
- if (node->getOp() == EOpFunctionCall)
+ for (auto *child : *sequence)
{
- inFunctionMap = isInFunctionMap(node);
- if (!inFunctionMap)
+ child->traverse(this);
+ if (visit && inVisit)
{
- // The function is not user-defined - it is likely built-in texture function.
- // Assume that those do not have out parameters.
- setInFunctionCallOutParameter(false);
+ if (child != sequence->back())
+ visit = visitAggregate(InVisit, node);
}
}
+ }
- incrementDepth(node);
+ if (visit && postVisit)
+ visitAggregate(PostVisit, node);
+}
- if (inFunctionMap)
+bool TIntermTraverser::CompareInsertion(const NodeInsertMultipleEntry &a,
+ const NodeInsertMultipleEntry &b)
+{
+ if (a.parent != b.parent)
+ {
+ return a.parent > b.parent;
+ }
+ return a.position > b.position;
+}
+
+void TIntermTraverser::updateTree()
+{
+ // Sort the insertions so that insertion position is decreasing. This way multiple insertions to
+ // the same parent node are handled correctly.
+ std::sort(mInsertions.begin(), mInsertions.end(), CompareInsertion);
+ for (size_t ii = 0; ii < mInsertions.size(); ++ii)
+ {
+ // We can't know here what the intended ordering of two insertions to the same position is,
+ // so it is not supported.
+ ASSERT(ii == 0 || mInsertions[ii].position != mInsertions[ii - 1].position ||
+ mInsertions[ii].parent != mInsertions[ii - 1].parent);
+ const NodeInsertMultipleEntry &insertion = mInsertions[ii];
+ ASSERT(insertion.parent);
+ if (!insertion.insertionsAfter.empty())
{
- TIntermSequence *params = getFunctionParameters(node);
- TIntermSequence::iterator paramIter = params->begin();
- for (auto *child : *sequence)
+ bool inserted = insertion.parent->insertChildNodes(insertion.position + 1,
+ insertion.insertionsAfter);
+ ASSERT(inserted);
+ }
+ if (!insertion.insertionsBefore.empty())
+ {
+ bool inserted =
+ insertion.parent->insertChildNodes(insertion.position, insertion.insertionsBefore);
+ ASSERT(inserted);
+ }
+ }
+ for (size_t ii = 0; ii < mReplacements.size(); ++ii)
+ {
+ const NodeUpdateEntry &replacement = mReplacements[ii];
+ ASSERT(replacement.parent);
+ bool replaced =
+ replacement.parent->replaceChildNode(replacement.original, replacement.replacement);
+ ASSERT(replaced);
+
+ if (!replacement.originalBecomesChildOfReplacement)
+ {
+ // In AST traversing, a parent is visited before its children.
+ // After we replace a node, if its immediate child is to
+ // be replaced, we need to make sure we don't update the replaced
+ // node; instead, we update the replacement node.
+ for (size_t jj = ii + 1; jj < mReplacements.size(); ++jj)
{
- ASSERT(paramIter != params->end());
- TQualifier qualifier = (*paramIter)->getAsTyped()->getQualifier();
- setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut);
+ NodeUpdateEntry &replacement2 = mReplacements[jj];
+ if (replacement2.parent == replacement.original)
+ replacement2.parent = replacement.replacement;
+ }
+ }
+ }
+ for (size_t ii = 0; ii < mMultiReplacements.size(); ++ii)
+ {
+ const NodeReplaceWithMultipleEntry &replacement = mMultiReplacements[ii];
+ ASSERT(replacement.parent);
+ bool replaced = replacement.parent->replaceChildNodeWithMultiple(replacement.original,
+ replacement.replacements);
+ ASSERT(replaced);
+ }
- child->traverse(this);
- if (visit && inVisit)
+ clearReplacementQueue();
+}
+
+void TIntermTraverser::clearReplacementQueue()
+{
+ mReplacements.clear();
+ mMultiReplacements.clear();
+ mInsertions.clear();
+}
+
+void TIntermTraverser::queueReplacement(TIntermNode *replacement, OriginalNode originalStatus)
+{
+ queueReplacementWithParent(getParentNode(), mPath.back(), replacement, originalStatus);
+}
+
+void TIntermTraverser::queueReplacementWithParent(TIntermNode *parent,
+ TIntermNode *original,
+ TIntermNode *replacement,
+ OriginalNode originalStatus)
+{
+ bool originalBecomesChild = (originalStatus == OriginalNode::BECOMES_CHILD);
+ mReplacements.push_back(NodeUpdateEntry(parent, original, replacement, originalBecomesChild));
+}
+
+TLValueTrackingTraverser::TLValueTrackingTraverser(bool preVisit,
+ bool inVisit,
+ bool postVisit,
+ TSymbolTable *symbolTable,
+ int shaderVersion)
+ : TIntermTraverser(preVisit, inVisit, postVisit, symbolTable),
+ mOperatorRequiresLValue(false),
+ mInFunctionCallOutParameter(false),
+ mShaderVersion(shaderVersion)
+{
+ ASSERT(symbolTable);
+}
+
+void TLValueTrackingTraverser::traverseFunctionPrototype(TIntermFunctionPrototype *node)
+{
+ TIntermSequence *sequence = node->getSequence();
+ addToFunctionMap(node->getFunctionSymbolInfo()->getId(), sequence);
+
+ TIntermTraverser::traverseFunctionPrototype(node);
+}
+
+void TLValueTrackingTraverser::traverseAggregate(TIntermAggregate *node)
+{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
+ bool visit = true;
+
+ TIntermSequence *sequence = node->getSequence();
+
+ if (preVisit)
+ visit = visitAggregate(PreVisit, node);
+
+ if (visit)
+ {
+ if (node->getOp() == EOpCallFunctionInAST)
+ {
+ if (isInFunctionMap(node))
+ {
+ TIntermSequence *params = getFunctionParameters(node);
+ TIntermSequence::iterator paramIter = params->begin();
+ for (auto *child : *sequence)
{
- if (child != sequence->back())
- visit = visitAggregate(InVisit, node);
+ ASSERT(paramIter != params->end());
+ TQualifier qualifier = (*paramIter)->getAsTyped()->getQualifier();
+ setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut);
+
+ child->traverse(this);
+ if (visit && inVisit)
+ {
+ if (child != sequence->back())
+ visit = visitAggregate(InVisit, node);
+ }
+
+ ++paramIter;
+ }
+ }
+ else
+ {
+ // The node might not be in the function map in case we're in the middle of
+ // transforming the AST, and have inserted function call nodes without inserting the
+ // function definitions yet.
+ setInFunctionCallOutParameter(false);
+ for (auto *child : *sequence)
+ {
+ child->traverse(this);
+ if (visit && inVisit)
+ {
+ if (child != sequence->back())
+ visit = visitAggregate(InVisit, node);
+ }
}
-
- ++paramIter;
}
setInFunctionCallOutParameter(false);
}
else
{
- if (node->getOp() == EOpSequence)
- pushParentBlock(node);
-
// Find the built-in function corresponding to this op so that we can determine the
// in/out qualifiers of its parameters.
TFunction *builtInFunc = nullptr;
- TString opString = GetOperatorString(node->getOp());
- if (!node->isConstructor() && !opString.empty())
+ if (!node->isFunctionCall() && !node->isConstructor())
{
- // The return type doesn't affect the mangled name of the function, which is used
- // to look it up from the symbol table.
- TType dummyReturnType;
- TFunction call(&opString, &dummyReturnType, node->getOp());
- for (auto *child : *sequence)
- {
- TType *paramType = child->getAsTyped()->getTypePointer();
- TConstParameter p(paramType);
- call.addParameter(p);
- }
-
- TSymbol *sym = mSymbolTable.findBuiltIn(call.getMangledName(), mShaderVersion);
- if (sym != nullptr && sym->isFunction())
- {
- builtInFunc = static_cast<TFunction *>(sym);
- ASSERT(builtInFunc->getParamCount() == sequence->size());
- }
+ builtInFunc = static_cast<TFunction *>(
+ mSymbolTable->findBuiltIn(node->getSymbolTableMangledName(), mShaderVersion));
}
size_t paramIndex = 0;
for (auto *child : *sequence)
{
+ // This assumes that raw functions called with
+ // EOpCallInternalRawFunction don't have out parameters.
TQualifier qualifier = EvqIn;
if (builtInFunc != nullptr)
qualifier = builtInFunc->getParam(paramIndex).type->getQualifier();
@@ -523,19 +817,11 @@ void TLValueTrackingTraverser::traverseAggregate(TIntermAggregate *node)
visit = visitAggregate(InVisit, node);
}
- if (node->getOp() == EOpSequence)
- incrementParentBlockPos();
-
++paramIndex;
}
setInFunctionCallOutParameter(false);
-
- if (node->getOp() == EOpSequence)
- popParentBlock();
}
-
- decrementDepth();
}
if (visit && postVisit)
@@ -543,28 +829,51 @@ void TLValueTrackingTraverser::traverseAggregate(TIntermAggregate *node)
}
//
-// Traverse a selection node. Same comments in binary node apply here.
+// Traverse a ternary node. Same comments in binary node apply here.
//
-void TIntermTraverser::traverseSelection(TIntermSelection *node)
+void TIntermTraverser::traverseTernary(TIntermTernary *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
bool visit = true;
if (preVisit)
- visit = visitSelection(PreVisit, node);
+ visit = visitTernary(PreVisit, node);
+
+ if (visit)
+ {
+ node->getCondition()->traverse(this);
+ if (node->getTrueExpression())
+ node->getTrueExpression()->traverse(this);
+ if (node->getFalseExpression())
+ node->getFalseExpression()->traverse(this);
+ }
+
+ if (visit && postVisit)
+ visitTernary(PostVisit, node);
+}
+
+// Traverse an if-else node. Same comments in binary node apply here.
+void TIntermTraverser::traverseIfElse(TIntermIfElse *node)
+{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
+ bool visit = true;
+
+ if (preVisit)
+ visit = visitIfElse(PreVisit, node);
if (visit)
{
- incrementDepth(node);
node->getCondition()->traverse(this);
if (node->getTrueBlock())
node->getTrueBlock()->traverse(this);
if (node->getFalseBlock())
node->getFalseBlock()->traverse(this);
- decrementDepth();
}
if (visit && postVisit)
- visitSelection(PostVisit, node);
+ visitIfElse(PostVisit, node);
}
//
@@ -572,6 +881,8 @@ void TIntermTraverser::traverseSelection(TIntermSelection *node)
//
void TIntermTraverser::traverseSwitch(TIntermSwitch *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
bool visit = true;
if (preVisit)
@@ -579,13 +890,11 @@ void TIntermTraverser::traverseSwitch(TIntermSwitch *node)
if (visit)
{
- incrementDepth(node);
node->getInit()->traverse(this);
if (inVisit)
visit = visitSwitch(InVisit, node);
if (visit && node->getStatementList())
node->getStatementList()->traverse(this);
- decrementDepth();
}
if (visit && postVisit)
@@ -597,13 +906,17 @@ void TIntermTraverser::traverseSwitch(TIntermSwitch *node)
//
void TIntermTraverser::traverseCase(TIntermCase *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
bool visit = true;
if (preVisit)
visit = visitCase(PreVisit, node);
if (visit && node->getCondition())
+ {
node->getCondition()->traverse(this);
+ }
if (visit && postVisit)
visitCase(PostVisit, node);
@@ -614,6 +927,8 @@ void TIntermTraverser::traverseCase(TIntermCase *node)
//
void TIntermTraverser::traverseLoop(TIntermLoop *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
bool visit = true;
if (preVisit)
@@ -621,8 +936,6 @@ void TIntermTraverser::traverseLoop(TIntermLoop *node)
if (visit)
{
- incrementDepth(node);
-
if (node->getInit())
node->getInit()->traverse(this);
@@ -634,8 +947,6 @@ void TIntermTraverser::traverseLoop(TIntermLoop *node)
if (node->getExpression())
node->getExpression()->traverse(this);
-
- decrementDepth();
}
if (visit && postVisit)
@@ -647,6 +958,8 @@ void TIntermTraverser::traverseLoop(TIntermLoop *node)
//
void TIntermTraverser::traverseBranch(TIntermBranch *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
bool visit = true;
if (preVisit)
@@ -654,9 +967,7 @@ void TIntermTraverser::traverseBranch(TIntermBranch *node)
if (visit && node->getExpression())
{
- incrementDepth(node);
node->getExpression()->traverse(this);
- decrementDepth();
}
if (visit && postVisit)
@@ -665,5 +976,8 @@ void TIntermTraverser::traverseBranch(TIntermBranch *node)
void TIntermTraverser::traverseRaw(TIntermRaw *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
visitRaw(node);
}
+
+} // namespace sh