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();
           }
       }
   }
Exemple #3
0
    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);
                            }
                        }

                    }
                }
            }
        }
    }