bool isMethodCall(SgFunctionCallExp *functionCall, bool &isDotExp) { ROSE_ASSERT(functionCall != NULL); SgExpression *expression = functionCall->get_function(); ROSE_ASSERT(expression != NULL); bool isMethod = false; isDotExp = false; switch(expression->variantT()) { case V_SgDotExp: { isMethod = true; SgDotExp *dotExp = isSgDotExp(expression); ROSE_ASSERT(dotExp != NULL); SgExpression *lhs = dotExp->get_lhs_operand(); ROSE_ASSERT(lhs != NULL); SgPointerDerefExp *pointerDerefExp = isSgPointerDerefExp(lhs); if ( pointerDerefExp != NULL ) { ; } else { isDotExp = true; } break; } case V_SgMemberFunctionRefExp: case V_SgArrowExp: { isMethod = true; break; } case V_SgFunctionRefExp: case V_SgPointerDerefExp: { isMethod = false; break; } default: { std::cerr << "Was not expecting an " << expression->sage_class_name() << std::endl; std::cerr << "in a function call." << std::endl; ROSE_ABORT(); } } return isMethod; }
// Do finite differencing on one expression within one context. The expression // must be defined and valid within the entire body of root. The rewrite rules // are used to simplify expressions. When a variable var is updated from // old_value to new_value, an expression of the form (var, (old_value, // new_value)) is created and rewritten. The rewrite rules may either produce // an arbitrary expression (which will be used as-is) or one of the form (var, // (something, value)) (which will be changed to (var = value)). void doFiniteDifferencingOne(SgExpression* e, SgBasicBlock* root, RewriteRule* rules) { SgStatementPtrList& root_stmts = root->get_statements(); SgStatementPtrList::iterator i; for (i = root_stmts.begin(); i != root_stmts.end(); ++i) { if (expressionComputedIn(e, *i)) break; } if (i == root_stmts.end()) return; // Expression is not used within root, so quit vector<SgVariableSymbol*> used_symbols = SageInterface::getSymbolsUsedInExpression(e); SgName cachename = "cache_fd__"; cachename << ++SageInterface::gensym_counter; SgVariableDeclaration* cachedecl = new SgVariableDeclaration(SgNULL_FILE, cachename, e->get_type(),0 /* new SgAssignInitializer(SgNULL_FILE, e) */); SgInitializedName* cachevar = cachedecl->get_variables().back(); ROSE_ASSERT (cachevar); root->get_statements().insert(i, cachedecl); cachedecl->set_parent(root); cachedecl->set_definingDeclaration(cachedecl); cachevar->set_scope(root); SgVariableSymbol* sym = new SgVariableSymbol(cachevar); root->insert_symbol(cachename, sym); SgVarRefExp* vr = new SgVarRefExp(SgNULL_FILE, sym); vr->set_endOfConstruct(SgNULL_FILE); replaceCopiesOfExpression(e, vr, root); vector<SgExpression*> modifications_to_used_symbols; FdFindModifyingStatementsVisitor(used_symbols, modifications_to_used_symbols).go(root); cachedecl->addToAttachedPreprocessingInfo( new PreprocessingInfo(PreprocessingInfo::CplusplusStyleComment,(string("// Finite differencing: ") + cachename.str() + " is a cache of " + e->unparseToString()).c_str(),"Compiler-Generated in Finite Differencing",0, 0, 0, PreprocessingInfo::before)); if (modifications_to_used_symbols.size() == 0) { SgInitializer* cacheinit = new SgAssignInitializer(SgNULL_FILE, e); e->set_parent(cacheinit); cachevar->set_initializer(cacheinit); cacheinit->set_parent(cachevar); } else { for (unsigned int i = 0; i < modifications_to_used_symbols.size(); ++i) { SgExpression* modstmt = modifications_to_used_symbols[i]; #ifdef FD_DEBUG cout << "Updating cache after " << modstmt->unparseToString() << endl; #endif SgExpression* updateCache = 0; SgVarRefExp* varref = new SgVarRefExp(SgNULL_FILE, sym); varref->set_endOfConstruct(SgNULL_FILE); SgTreeCopy tc; SgExpression* eCopy = isSgExpression(e->copy(tc)); switch (modstmt->variantT()) { case V_SgAssignOp: { SgAssignOp* assignment = isSgAssignOp(modstmt); assert (assignment); SgExpression* lhs = assignment->get_lhs_operand(); SgExpression* rhs = assignment->get_rhs_operand(); replaceCopiesOfExpression(lhs, rhs, eCopy); } break; case V_SgPlusAssignOp: case V_SgMinusAssignOp: case V_SgAndAssignOp: case V_SgIorAssignOp: case V_SgMultAssignOp: case V_SgDivAssignOp: case V_SgModAssignOp: case V_SgXorAssignOp: case V_SgLshiftAssignOp: case V_SgRshiftAssignOp: { SgBinaryOp* assignment = isSgBinaryOp(modstmt); assert (assignment); SgExpression* lhs = assignment->get_lhs_operand(); SgExpression* rhs = assignment->get_rhs_operand(); SgTreeCopy tc; SgExpression* rhsCopy = isSgExpression(rhs->copy(tc)); SgExpression* newval = 0; switch (modstmt->variantT()) { #define DO_OP(op, nonassignment) \ case V_##op: { \ newval = new nonassignment(SgNULL_FILE, lhs, rhsCopy); \ newval->set_endOfConstruct(SgNULL_FILE); \ } \ break DO_OP(SgPlusAssignOp, SgAddOp); DO_OP(SgMinusAssignOp, SgSubtractOp); DO_OP(SgAndAssignOp, SgBitAndOp); DO_OP(SgIorAssignOp, SgBitOrOp); DO_OP(SgMultAssignOp, SgMultiplyOp); DO_OP(SgDivAssignOp, SgDivideOp); DO_OP(SgModAssignOp, SgModOp); DO_OP(SgXorAssignOp, SgBitXorOp); DO_OP(SgLshiftAssignOp, SgLshiftOp); DO_OP(SgRshiftAssignOp, SgRshiftOp); #undef DO_OP default: break; } assert (newval); replaceCopiesOfExpression(lhs, newval, eCopy); } break; case V_SgPlusPlusOp: { SgExpression* lhs = isSgPlusPlusOp(modstmt)->get_operand(); SgIntVal* one = new SgIntVal(SgNULL_FILE, 1); one->set_endOfConstruct(SgNULL_FILE); SgAddOp* add = new SgAddOp(SgNULL_FILE, lhs, one); add->set_endOfConstruct(SgNULL_FILE); lhs->set_parent(add); one->set_parent(add); replaceCopiesOfExpression(lhs,add,eCopy); } break; case V_SgMinusMinusOp: { SgExpression* lhs = isSgMinusMinusOp(modstmt)->get_operand(); SgIntVal* one = new SgIntVal(SgNULL_FILE, 1); one->set_endOfConstruct(SgNULL_FILE); SgSubtractOp* sub = new SgSubtractOp(SgNULL_FILE, lhs, one); sub->set_endOfConstruct(SgNULL_FILE); lhs->set_parent(sub); one->set_parent(sub); replaceCopiesOfExpression(lhs,sub,eCopy); } break; default: cerr << modstmt->sage_class_name() << endl; assert (false); break; } #ifdef FD_DEBUG cout << "e is " << e->unparseToString() << endl; cout << "eCopy is " << eCopy->unparseToString() << endl; #endif updateCache = doFdVariableUpdate(rules, varref, e, eCopy); #ifdef FD_DEBUG cout << "updateCache is " << updateCache->unparseToString() << endl; #endif if (updateCache) { ROSE_ASSERT(modstmt != NULL); SgNode* ifp = modstmt->get_parent(); SgCommaOpExp* comma = new SgCommaOpExp(SgNULL_FILE, updateCache, modstmt); modstmt->set_parent(comma); updateCache->set_parent(comma); if (ifp == NULL) { printf ("modstmt->get_parent() == NULL modstmt = %p = %s \n",modstmt,modstmt->class_name().c_str()); modstmt->get_startOfConstruct()->display("modstmt->get_parent() == NULL: debug"); } ROSE_ASSERT(ifp != NULL); #ifdef FD_DEBUG cout << "New expression is " << comma->unparseToString() << endl; cout << "IFP is " << ifp->sage_class_name() << ": " << ifp->unparseToString() << endl; #endif if (isSgExpression(ifp)) { isSgExpression(ifp)->replace_expression(modstmt, comma); comma->set_parent(ifp); } else { // DQ (12/16/2006): Need to handle cases that are not SgExpression (now that SgExpressionRoot is not used!) // cerr << ifp->sage_class_name() << endl; // assert (!"Bad parent type for inserting comma expression"); SgStatement* statement = isSgStatement(ifp); if (statement != NULL) { #ifdef FD_DEBUG printf ("Before statement->replace_expression(): statement = %p = %s modstmt = %p = %s \n",statement,statement->class_name().c_str(),modstmt,modstmt->class_name().c_str()); SgExprStatement* expresionStatement = isSgExprStatement(statement); if (expresionStatement != NULL) { SgExpression* expression = expresionStatement->get_expression(); printf ("expressionStatement expression = %p = %s \n",expression,expression->class_name().c_str()); } #endif statement->replace_expression(modstmt, comma); comma->set_parent(statement); } else { ROSE_ASSERT(ifp != NULL); printf ("Error: parent is neither a SgExpression nor a SgStatement ifp = %p = %s \n",ifp,ifp->class_name().c_str()); ROSE_ASSERT(false); } } #ifdef FD_DEBUG cout << "IFP is now " << ifp->unparseToString() << endl; #endif } } } }