void replaceCopiesOfExpression(SgExpression* src, SgExpression* tgt, SgNode* root) { #ifdef FD_DEBUG cout << "replaceCopiesOfExpression: src = " << src->unparseToString() << ", tgt = " << tgt->unparseToString() << ", root = " << root->unparseToString() << endl; #endif vector<SgExpression*> copies_of_src; #ifdef FD_DEBUG cout << "---" << endl; #endif FdFindCopiesVisitor(src, copies_of_src).traverse(root, preorder); #ifdef FD_DEBUG cout << copies_of_src.size() << " copy(ies) found." << endl; #endif for (unsigned int i = 0; i < copies_of_src.size(); ++i) { SgTreeCopy tc; SgExpression* copy = isSgExpression(tgt->copy(tc)); SgExpression* parent = isSgExpression(copies_of_src[i]->get_parent()); assert (parent); parent->replace_expression(copies_of_src[i], copy); copy->set_parent(parent); } #ifdef FD_DEBUG cout << "result is " << root->unparseToString() << endl; #endif }
/* Given a node in the AST, it replaces all function calls with the corresponding expression from the fct2Var mapping. Since we traverse in order of function evaluation, all nodes that are lower in the subtree are supposed to have been mapped, since they have already appeared in the list. Also, we only replace the shallowest level of function calls in the surrent subtree, since we assume that replaceFunctionCallsInExpression has already been called for each of the subtrees rooted at the shallowest function calls lower than the current node: E.g.: f(g(h(i))) + 5 has the AST: + / \ fc1 5 / \ f fc2 / \ g fc3 / \ h i where fc? represents an SgFunctionCallExpression. Order of function evaluation is h(i), g(_), f(_). Calling 'replaceFunctionCallsInExpression' on '+' will generate temp_var + 5 but calling the same function on 'fc2' will generate f(temp_var) + 5 */ void FunctionCallNormalization::replaceFunctionCallsInExpression( SgNode *root, map<SgFunctionCallExp *, SgExpression *> fct2Var ) { if ( !root ) return; if ( NodeQuery::querySubTree( root, V_SgFunctionCallExp ).size() > 0 ) { list<SgNode *> toVisit; toVisit.push_back( root ); while ( !toVisit.empty() ) { SgNode *crt = toVisit.front(); // will visit every node above an function call exp, but not below // also, we will replace function call expressions found if ( !isSgFunctionCallExp( crt ) ) { vector<SgNode *> succ = ( crt )->get_traversalSuccessorContainer(); for ( vector<SgNode *>::iterator succIt = succ.begin(); succIt != succ.end(); succIt++ ) if ( isSgNode ( *succIt ) ) toVisit.push_back( *succIt ); } else { SgFunctionCallExp *call = isSgFunctionCallExp( crt ); ROSE_ASSERT ( call ); map<SgFunctionCallExp *, SgExpression *>::iterator mapIter; mapIter = fct2Var.find( call ); if ( mapIter == fct2Var.end() ) cout << "NOT FOUND " << call->unparseToString() << "\t" << call << "\n"; // a mapping for function call exps in the subtree must already exist ( postorder traversal ) ROSE_ASSERT ( mapIter != fct2Var.end() && mapIter->second ); // duplicate the variable SgTreeCopy treeCopy; SgExpression *scnd = mapIter->second; ROSE_ASSERT ( isSgExpression( scnd ) ); SgExpression *newVar = isSgExpression( scnd->copy( treeCopy ) ); ROSE_ASSERT ( newVar ); SgExpression *parent = isSgExpression( call->get_parent() ); ROSE_ASSERT ( parent ); // replace the node in the AST newVar->set_parent( parent ); int k = parent->replace_expression( call, newVar ); ROSE_ASSERT ( k == 1 ); delete call; } toVisit.pop_front(); } } }
virtual void visit(SgNode* n) { if (isSgVarRefExp(n)) { SgVarRefExp* copy_vr = isSgVarRefExp(n); assert (copy_vr->get_symbol()); SgInitializedName* copy = copy_vr->get_symbol()->get_declaration(); assert (copy); SgInitializer* copyinit = copy->get_initializer(); SgScopeStatement* copyscope = SageInterface::getScope(copy->get_parent()->get_parent()); if (isSgAssignInitializer(copyinit)) { SgAssignInitializer* init = isSgAssignInitializer(copyinit); SgExpression* orig_expr = init->get_operand(); // cout << "orig is " << orig_expr->unparseToString() << ", copy is " << copy->get_name().str() << endl; if (!isPotentiallyModified(copy_vr, copyscope) && !isSgGlobal(copyscope) && !isSgNamespaceDefinitionStatement(copyscope)) { bool shouldReplace = false; if (isSgVarRefExp(orig_expr)) { SgVarRefExp* orig_vr = isSgVarRefExp(orig_expr); // cout << "Found potential copy from " << orig_vr->get_symbol()->get_name().str() << " to " << copy_vr->get_symbol()->get_name().str() << endl; SgInitializedName* orig = orig_vr->get_symbol()->get_declaration(); assert (orig); SgNode* origscope = orig->get_parent()->get_parent(); assert (origscope); if (!hasAddressTaken(orig_vr, origscope) && isSgBasicBlock(copyscope) && !isPotentiallyModifiedDuringLifeOf(isSgBasicBlock(copyscope), orig, copy) && !isSgGlobal(origscope) && !isSgNamespaceDefinitionStatement(origscope)) { shouldReplace = true; } } else if (isSgValueExp(orig_expr)) { shouldReplace = true; } // cout << "shouldReplace is " << shouldReplace << endl; if (shouldReplace) { assert (orig_expr); SgExpression* orig_copy = isSgExpression(orig_expr /*->copy(SgTreeCopy()) */); assert (orig_copy); orig_copy->set_parent(copy_vr->get_parent()); orig_copy->set_lvalue(copy_vr->get_lvalue()); ROSE_ASSERT(copy_vr != NULL); ROSE_ASSERT(copy_vr->get_parent() != NULL); // ROSE_ASSERT(isSgExpression(copy_vr->get_parent()) != NULL); // DQ (12/15/2006): Need to handle cases where the parent is a SgStatement or a SgExpression (or make it an error). // isSgExpression(copy_vr->get_parent())->replace_expression(copy_vr, orig_copy); SgStatement* statement = isSgStatement(copy_vr->get_parent()); if (statement != NULL) { statement->replace_expression(copy_vr, orig_copy); } else { SgExpression* expression = isSgExpression(copy_vr->get_parent()); if (expression != NULL) { expression->replace_expression(copy_vr, orig_copy); } else { printf ("Error: what is this copy_vr->get_parent() = %s \n",copy_vr->get_parent()->class_name().c_str()); ROSE_ASSERT(false); } } } } } } }