// Traverse a block node. void TIntermTraverser::traverseBlock(TIntermBlock *node) { bool visit = true; TIntermSequence *sequence = node->getSequence(); if (preVisit) visit = visitBlock(PreVisit, node); if (visit) { incrementDepth(node); pushParentBlock(node); for (auto *child : *sequence) { child->traverse(this); if (visit && inVisit) { if (child != sequence->back()) visit = visitBlock(InVisit, node); } incrementParentBlockPos(); } popParentBlock(); decrementDepth(); } if (visit && postVisit) visitBlock(PostVisit, node); }
// // Traverse an aggregate node. Same comments in binary node apply here. // void TIntermTraverser::traverseAggregate(TIntermAggregate *node) { bool visit = true; TIntermSequence *sequence = node->getSequence(); if (preVisit) visit = visitAggregate(PreVisit, node); if (visit) { incrementDepth(node); if (node->getOp() == EOpSequence) pushParentBlock(node); else if (node->getOp() == EOpFunction) mInGlobalScope = false; for (auto *child : *sequence) { child->traverse(this); if (visit && inVisit) { if (child != sequence->back()) visit = visitAggregate(InVisit, node); } if (node->getOp() == EOpSequence) incrementParentBlockPos(); } if (node->getOp() == EOpSequence) popParentBlock(); else if (node->getOp() == EOpFunction) mInGlobalScope = true; decrementDepth(); } if (visit && postVisit) visitAggregate(PostVisit, node); }
void TLValueTrackingTraverser::traverseAggregate(TIntermAggregate *node) { bool visit = true; TIntermSequence *sequence = node->getSequence(); switch (node->getOp()) { case EOpFunction: { TIntermAggregate *params = sequence->front()->getAsAggregate(); ASSERT(params != nullptr); ASSERT(params->getOp() == EOpParameters); addToFunctionMap(node->getNameObj(), params->getSequence()); break; } case EOpPrototype: addToFunctionMap(node->getNameObj(), sequence); break; default: break; } if (preVisit) visit = visitAggregate(PreVisit, node); if (visit) { bool inFunctionMap = false; if (node->getOp() == EOpFunctionCall) { inFunctionMap = isInFunctionMap(node); if (!inFunctionMap) { // The function is not user-defined - it is likely built-in texture function. // Assume that those do not have out parameters. setInFunctionCallOutParameter(false); } } incrementDepth(node); if (inFunctionMap) { TIntermSequence *params = getFunctionParameters(node); TIntermSequence::iterator paramIter = params->begin(); for (auto *child : *sequence) { 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; } setInFunctionCallOutParameter(false); } else { if (node->getOp() == EOpSequence) pushParentBlock(node); else if (node->getOp() == EOpFunction) mInGlobalScope = false; // 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()) { // 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()); } } size_t paramIndex = 0; for (auto *child : *sequence) { TQualifier qualifier = EvqIn; if (builtInFunc != nullptr) qualifier = builtInFunc->getParam(paramIndex).type->getQualifier(); setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut); child->traverse(this); if (visit && inVisit) { if (child != sequence->back()) visit = visitAggregate(InVisit, node); } if (node->getOp() == EOpSequence) incrementParentBlockPos(); ++paramIndex; } setInFunctionCallOutParameter(false); if (node->getOp() == EOpSequence) popParentBlock(); else if (node->getOp() == EOpFunction) mInGlobalScope = true; } decrementDepth(); } if (visit && postVisit) visitAggregate(PostVisit, node); }