SgExpression* doFdVariableUpdate( RewriteRule* rules, SgExpression* cache, SgExpression* old_val /* Cannot be referenced in output tree w/o copying */, SgExpression* new_val) { #ifdef FD_DEBUG cout << "Trying to convert from " << old_val->unparseToString() << " to " << new_val->unparseToString() << ", using cache " << cache->unparseToString() << endl; #endif SgTreeCopy tc; SgExpression* old_valCopy = isSgExpression(old_val->copy(tc)); ROSE_ASSERT (old_valCopy); SgCommaOpExp* innerComma = new SgCommaOpExp(SgNULL_FILE, old_valCopy, new_val); old_valCopy->set_parent(innerComma); new_val->set_parent(innerComma); SgExpression* expr = new SgCommaOpExp(SgNULL_FILE,cache,innerComma); cache->set_parent(expr); innerComma->set_parent(expr); // This is done so rewrite's expression replacement code will never find a // NULL parent for the expression being replaced SgExprStatement* dummyExprStatement = new SgExprStatement(SgNULL_FILE, expr); expr->set_parent(dummyExprStatement); SgNode* exprCopyForRewrite = expr; rewrite(rules, exprCopyForRewrite); // This might modify exprCopyForRewrite ROSE_ASSERT (isSgExpression(exprCopyForRewrite)); expr = isSgExpression(exprCopyForRewrite); expr->set_parent(NULL); dummyExprStatement->set_expression(NULL); delete dummyExprStatement; SgExpression* expr2 = expr; ROSE_ASSERT (expr2); if (// The rewrite rules may have changed the form of expr to something other than a comma pair isSgCommaOpExp(expr2) && isSgCommaOpExp(isSgCommaOpExp(expr2)->get_rhs_operand())) { SgExpression* cache2 = isSgCommaOpExp(expr2)->get_lhs_operand(); SgCommaOpExp* rhs = isSgCommaOpExp(isSgCommaOpExp(expr2)->get_rhs_operand()); // SgExpression* old_val2 = rhs->get_lhs_operand(); SgExpression* new_val2 = rhs->get_rhs_operand(); // return new SgAssignOp(SgNULL_FILE, cache2, new_val2); cache2->set_lvalue(true); SgAssignOp* assignmentOperator = new SgAssignOp(SgNULL_FILE, cache2, new_val2); cache2->set_parent(assignmentOperator); new_val2->set_parent(assignmentOperator); #ifdef FD_DEBUG printf ("In doFdVariableUpdate(): assignmentOperator = %p \n",assignmentOperator); #endif return assignmentOperator; } else { return expr2; } }
virtual void visit(SgNode* n) { SgReturnStmt* rs = isSgReturnStmt(n); if (rs) { // std::cout << "Converting return statement " << rs->unparseToString(); // std::cout << " into possible assignment to " << where_to_write_answer->unparseToString(); // std::cout << " and jump to " << label->get_name().getString() << std::endl; SgExpression* return_expr = rs->get_expression(); SgBasicBlock* block = SageBuilder::buildBasicBlock(); // printf ("Building IR node #1: new SgBasicBlock = %p \n",block); if (return_expr) { SgExpression* assignment = generateAssignmentMaybe(where_to_write_answer,return_expr); if (where_to_write_answer) where_to_write_answer->set_parent(assignment); if (return_expr != assignment) return_expr->set_parent(assignment); SgStatement* assign_stmt = SageBuilder::buildExprStatement(assignment); SageInterface::appendStatement(assign_stmt, block); } // block->get_statements().push_back(new SgGotoStatement(SgNULL_FILE, label)); SgGotoStatement* gotoStatement = new SgGotoStatement(SgNULL_FILE, label); gotoStatement->set_endOfConstruct(SgNULL_FILE); ROSE_ASSERT(n->get_parent() != NULL); SageInterface::appendStatement(gotoStatement, block); isSgStatement(n->get_parent())->replace_statement(rs, block); block->set_parent(n->get_parent()); ROSE_ASSERT(gotoStatement->get_parent() != NULL); } }
void Fortran_to_C::linearizeArrayDeclaration(SgArrayType* originalArrayType) { // Get dim_info SgExprListExp* dimInfo = originalArrayType->get_dim_info(); // Get dim list SgExpressionPtrList dimExpressionPtrList = dimInfo->get_expressions(); SgExpression* newDimExpr; Rose_STL_Container<SgExpression*>::iterator j = dimExpressionPtrList.begin(); while(j != dimExpressionPtrList.end()) { SgExpression* indexExpression = getFortranDimensionSize(*j); /* Total array size is equal to the multiplication of all individual dimension size. */ if(j != dimExpressionPtrList.begin()){ newDimExpr = buildMultiplyOp(newDimExpr, indexExpression); } else /* If it's first dimension, array size is just its first dimension size. */ { newDimExpr = indexExpression; } ++j; } // calling set_index won't replace the default index expression. I have to delete the default manually. removeList.push_back(originalArrayType->get_index()); originalArrayType->set_index(newDimExpr); newDimExpr->set_parent(originalArrayType); originalArrayType->set_rank(1); }
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 (isSgBasicBlock(n)) { SgBasicBlock* bb = isSgBasicBlock(n); SgStatementPtrList& stmts = bb->get_statements(); size_t initi; for (size_t decli = 0; decli < stmts.size(); ++decli) { if (isSgVariableDeclaration(stmts[decli])) { SgVariableDeclaration* decl = isSgVariableDeclaration(stmts[decli]); SgInitializedNamePtrList& vars = decl->get_variables(); for (size_t vari = 0; vari != vars.size(); ++vari) { SgInitializedName* in = vars[vari]; if (in->get_initializer() == 0) { bool used = false; for (initi = decli + 1; initi < stmts.size(); used |= containsVariableReference(stmts[initi], in), ++initi) { SgExprStatement* initExprStmt = isSgExprStatement(stmts[initi]); if (initExprStmt) { SgExpression* top = initExprStmt->get_expression(); if (isSgAssignOp(top)) { SgVarRefExp* vr = isSgVarRefExp(isSgAssignOp(top)->get_lhs_operand()); ROSE_ASSERT(isSgAssignOp(top) != NULL); SgExpression* newinit = isSgAssignOp(top)->get_rhs_operand(); if (!used && vr && vr->get_symbol()->get_declaration() == in) { ROSE_ASSERT(newinit != NULL); // printf ("MoveDeclarationsToFirstUseVisitor::visit(): newinit = %p = %s \n",newinit,newinit->class_name().c_str()); ROSE_ASSERT(newinit->get_type() != NULL); SgAssignInitializer* i = new SgAssignInitializer(SgNULL_FILE,newinit,newinit->get_type()); i->set_endOfConstruct(SgNULL_FILE); // printf ("Built a SgAssignInitializer #1 \n"); vars[vari]->set_initializer(i); stmts[initi] = decl; newinit->set_parent(i); // DQ (6/23/2006): Set the parent and file_info pointers // printf ("Setting parent of i = %p = %s to parent = %p = %s \n",i,i->class_name().c_str(),in,in->class_name().c_str()); i->set_parent(in); ROSE_ASSERT(i->get_parent() != NULL); i->set_file_info(new Sg_File_Info(*(newinit->get_file_info()))); ROSE_ASSERT(i->get_file_info() != NULL); // Assumes only one var per declaration FIXME ROSE_ASSERT (vars.size() == 1); stmts.erase(stmts.begin() + decli); --decli; // To counteract ++decli in loop header break; // To get out of initi loop } } } } } } } } } }
// Propagate definitions of a variable to its uses. // Assumptions: var is only assigned at the top level of body // nothing var depends on is assigned within body // Very simple algorithm designed to only handle simplest cases void simpleUndoFiniteDifferencingOne(SgBasicBlock* body, SgExpression* var) { SgExpression* value = 0; SgStatementPtrList& stmts = body->get_statements(); vector<SgStatement*> stmts_to_remove; for (SgStatementPtrList::iterator i = stmts.begin(); i != stmts.end(); ++i) { // cout << "Next statement: value = " << (value ? value->unparseToString() : "(null)") << endl; // cout << (*i)->unparseToString() << endl; if (isSgExprStatement(*i) && isSgAssignOp(isSgExprStatement(*i)->get_expression())) { SgAssignOp* assignment = isSgAssignOp(isSgExprStatement(*i)->get_expression()); // cout << "In assignment statement " << assignment->unparseToString() << endl; if (value) replaceCopiesOfExpression(var, value, assignment->get_rhs_operand()); if (isSgVarRefExp(assignment->get_lhs_operand()) && isSgVarRefExp(var)) { SgVarRefExp* vr = isSgVarRefExp(assignment->get_lhs_operand()); if (vr->get_symbol()->get_declaration() == isSgVarRefExp(var)->get_symbol()->get_declaration()) { value = assignment->get_rhs_operand(); stmts_to_remove.push_back(*i); } } } else { if (value) replaceCopiesOfExpression(var, value, *i); } } for (vector<SgStatement*>::iterator i = stmts_to_remove.begin(); i != stmts_to_remove.end(); ++i) { stmts.erase(std::find(stmts.begin(), stmts.end(), *i)); } if (value) { // DQ (12/17/2006): Separate out the construction of the SgAssignOp from the SgExprStatement to support debugging and testing. // stmts.push_back(new SgExprStatement(SgNULL_FILE, new SgAssignOp(SgNULL_FILE, var, value))); var->set_lvalue(true); SgAssignOp* assignmentOperator = new SgAssignOp(SgNULL_FILE, var, value); var->set_parent(assignmentOperator); value->set_parent(assignmentOperator); printf ("In simpleUndoFiniteDifferencingOne(): assignmentOperator = %p \n",assignmentOperator); // DQ: Note that the parent of the SgExprStatement will be set in AST post-processing (or it should be). SgExprStatement* es = new SgExprStatement(SgNULL_FILE, assignmentOperator); assignmentOperator->set_parent(es); stmts.push_back(es); es->set_parent(body); } }
/// \brief replace old with repl, and delete subtree rooted in old. /// \return old's operand static SgExpression& extractOperand(SgUnaryOp& old) { SgExpression* op = old.get_operand(); SgExpression* emptydummy = SB::buildIntVal(0); SI::replaceExpression(op, emptydummy, keep_old_tree); op->set_parent(NULL); return *op; }
void Fortran_to_C::translateArrayDeclaration(SgArrayType* originalArrayType) { // Get dim_info SgExprListExp* dimInfo = originalArrayType->get_dim_info(); // Get dim list SgExpressionPtrList dimExpressionPtrList = dimInfo->get_expressions(); // Get array base_type SgType* baseType = originalArrayType->get_base_type(); Rose_STL_Container<SgExpression*>::iterator j = dimExpressionPtrList.begin(); SgExpression* indexExpression = getFortranDimensionSize(*j); //std::cout << "array rank:" << originalArrayType->get_rank() << std::endl; if(originalArrayType->get_rank() == 1) { originalArrayType->set_base_type(baseType); originalArrayType->set_index(indexExpression); indexExpression->set_parent(originalArrayType); constantFolding(indexExpression); } else { SgArrayType* newType = buildArrayType(baseType,indexExpression); baseType->set_parent(newType); j = j + 1; for(; j< (dimExpressionPtrList.end()-1); ++j) { indexExpression = getFortranDimensionSize(*j); baseType = newType; newType = buildArrayType(baseType,indexExpression); baseType->set_parent(newType); } j = dimExpressionPtrList.end()-1; indexExpression = getFortranDimensionSize(*j); originalArrayType->set_base_type(newType); originalArrayType->set_index(indexExpression); indexExpression->set_parent(originalArrayType); } }
// Do partial redundancy elimination, looking for copies of one expression expr // within the basic block root. A control flow graph for root must be provided // in cfg, with a map from nodes to their statements in node_statements, a map // from edges to their CFG edge types in edge_type, and a map from edges to // their insertion points in edge_insertion_point. The algorithm used is that // of Paleri, Srikant, and Shankar ("Partial redundancy elimination: a simple, // pragmatic, and provably correct algorithm", Science of Computer Programming // 48 (2003) 1--20). void PRE::partialRedundancyEliminationOne( SgExpression* expr, SgBasicBlock* root, const myControlFlowGraph& cfg) { // SgBasicBlock* myFunctionBody = getFunctionDefinition(expr)->get_body(); // DQ (3/16/2006): Added assertions ROSE_ASSERT(expr != NULL); ROSE_ASSERT(root != NULL); vector<SgVariableSymbol*> symbols_in_expression = SageInterface::getSymbolsUsedInExpression(expr); if (anyOfListPotentiallyModifiedIn(symbols_in_expression, expr)) { // This expression updates its own arguments, and so is not idempotent // Return immediately return; } // Simple or not user-definable expressions if (isSgVarRefExp(expr)) return; if (isSgValueExp(expr)) return; if (isSgFunctionRefExp(expr)) return; if (isSgExprListExp(expr)) return; if (isSgInitializer(expr)) return; #if 0 if ( (isSgAddOp(expr) || isSgSubtractOp(expr)) && (isSgVarRefExp(isSgBinaryOp(expr)->get_lhs_operand()) || isSgValueExp(isSgBinaryOp(expr)->get_lhs_operand())) && (isSgVarRefExp(isSgBinaryOp(expr)->get_rhs_operand()) || isSgValueExp(isSgBinaryOp(expr)->get_rhs_operand()))) return; #endif // Expressions which do not keep a consistent value each time they are used if (!expressionTreeEqual(expr, expr)) return; // cerr << "Trying to do PRE using expression " << expr->unparseToString() << " whose type is " << expr->sage_class_name() << endl; VertexIter i = cfg.graph.vertices().begin(), end = cfg.graph.vertices().end(); // cerr << "CFG has " << distance(i, end) << " nodes" << endl; bool needToMakeCachevar = false; set<SgNode*> replacements; vector<pair<SgNode*, bool /* before */> > insertions; vector<bool> transp(cfg.graph.vertices().size()), comp(cfg.graph.vertices().size()), antloc(cfg.graph.vertices().size()); vector<SgNode*> first_computation(cfg.graph.vertices().size()), last_computation(cfg.graph.vertices().size()); // Set values of local node properties for (i = cfg.graph.vertices().begin(); i != end; ++i) { const vector<SgNode*>& stmts = cfg.node_statements[*i]; // Precompute test values for each statement vector<bool> argumentsModifiedInStatement(stmts.size()); vector<int> expressionComputedInStatement(stmts.size()); for (unsigned int j = 0; j < stmts.size(); ++j) { if (anyOfListPotentiallyModifiedIn(symbols_in_expression, stmts[j])) argumentsModifiedInStatement[j] = true; expressionComputedInStatement[j] = countComputationsOfExpressionIn(expr, stmts[j]); } // Compute transp transp[*i] = true; for (unsigned int j = 0; j < stmts.size(); ++j) if (argumentsModifiedInStatement[j]) transp[*i] = false; // Compute comp and do local redundancy elimination comp[*i] = false; SgNode* firstComputationInChain = 0; bool needToInsertComputation = false; bool computationInsertedOrUsed = false; // cout << "In node " << *i << endl; for (unsigned int j = 0; j < stmts.size(); ++j) { // cout << "In stmt " << j << ", expressionComputedInStatement = " << expressionComputedInStatement[j] // << ", argumentsModifiedInStatement = " << argumentsModifiedInStatement[j] << endl; if (expressionComputedInStatement[j] && !argumentsModifiedInStatement[j] && comp[*i] /* from last iter */) { // Do local redundancy elimination if (firstComputationInChain && needToInsertComputation) { insertions.push_back(make_pair(firstComputationInChain, true)); replacements.insert(firstComputationInChain); needToInsertComputation = false; } replacements.insert(stmts[j]); computationInsertedOrUsed = true; needToMakeCachevar = true; } if (expressionComputedInStatement[j]) { comp[*i] = true; if (!firstComputationInChain) { firstComputationInChain = stmts[j]; needToInsertComputation = true; if (expressionComputedInStatement[j] >= 2) { insertions.push_back(make_pair(stmts[j], true)); needToMakeCachevar = true; needToInsertComputation = false; computationInsertedOrUsed = true; replacements.insert(stmts[j]); } } last_computation[*i] = stmts[j]; } if (argumentsModifiedInStatement[j]) { comp[*i] = false; // Must come after expressionComputedInStatement check firstComputationInChain = 0; needToInsertComputation = false; } } assert (!computationInsertedOrUsed || needToMakeCachevar); // Compute antloc antloc[*i] = false; for (unsigned int j = 0; j < stmts.size(); ++j) { if (expressionComputedInStatement[j] && !argumentsModifiedInStatement[j]) { antloc[*i] = true; first_computation[*i] = stmts[j]; break; } if (argumentsModifiedInStatement[j]) { antloc[*i] = false; break; } } } // #define PRINT_PROPERTY(p) // for (i = cfg.graph.vertices().begin(); i != end; ++i) if (p[*i]) cerr << #p ": " << *i << endl; #define PRINT_PROPERTY(p) // for (i = cfg.graph.vertices().begin(); i != end; ++i) if (p[*i]) cerr << #p ": " << *i << endl; PRINT_PROPERTY(transp); PRINT_PROPERTY(comp); PRINT_PROPERTY(antloc); int (simpleGraph::*source_ptr)(int) const = &simpleGraph::source; int (simpleGraph::*target_ptr)(int) const = &simpleGraph::target; vector<bool> avin(cfg.graph.vertices().size(), true); vector<bool> avout(cfg.graph.vertices().size(), true); FIXPOINT_BEGIN(cfg) FIXPOINT_OUTPUT_BEGIN(avin, cfg); FIXPOINT_OUTPUT_BEGIN(avout, cfg); avin[v] = accumulate_neighbors(cfg, v, avout,cfg.graph.in_edges(v),&simpleGraph::source, logical_and<bool>(), true, false); avout[v] = comp[v] || (avin[v] && transp[v]); FIXPOINT_OUTPUT_END(avout, <=, cfg); FIXPOINT_OUTPUT_END(avin, <=, cfg); FIXPOINT_END(cfg, out_edges, OutEdgeIter) PRINT_PROPERTY(avin); PRINT_PROPERTY(avout); vector<bool> antin(cfg.graph.vertices().size(), true); vector<bool> antout(cfg.graph.vertices().size(), true); FIXPOINT_BEGIN(cfg) FIXPOINT_OUTPUT_BEGIN(antin, cfg); FIXPOINT_OUTPUT_BEGIN(antout, cfg); antout[v] = accumulate_neighbors(cfg, v, antin, cfg.graph.out_edges(v), target_ptr, logical_and<bool>(), true, false); antin[v] = antloc[v] || (antout[v] && transp[v]); FIXPOINT_OUTPUT_END(antout, <=, cfg); FIXPOINT_OUTPUT_END(antin, <=, cfg); FIXPOINT_END(cfg, in_edges, InEdgeIter) PRINT_PROPERTY(antin); PRINT_PROPERTY(antout); vector<bool> safein(cfg.graph.vertices().size()), safeout(cfg.graph.vertices().size()); for (i = cfg.graph.vertices().begin(); i != end; ++i) { safein[*i] = avin[*i] || antin[*i]; safeout[*i] = avout[*i] || antout[*i]; } PRINT_PROPERTY(safein); PRINT_PROPERTY(safeout); vector<bool> spavin(cfg.graph.vertices().size(), false); vector<bool> spavout(cfg.graph.vertices().size(), false); FIXPOINT_BEGIN(cfg) FIXPOINT_OUTPUT_BEGIN(spavin, cfg); FIXPOINT_OUTPUT_BEGIN(spavout, cfg); spavin[v] = safein[v] && accumulate_neighbors(cfg, v, spavout, cfg.graph.in_edges(v), source_ptr, logical_or<bool>(), false, false); spavout[v] = safeout[v] && (comp[v] || (spavin[v] && transp[v])); FIXPOINT_OUTPUT_END(spavout, >=, cfg); FIXPOINT_OUTPUT_END(spavin, >=, cfg); FIXPOINT_END(cfg, out_edges, OutEdgeIter) PRINT_PROPERTY(spavin); PRINT_PROPERTY(spavout); vector<bool> spantin(cfg.graph.vertices().size(), false); vector<bool> spantout(cfg.graph.vertices().size(), false); FIXPOINT_BEGIN(cfg) FIXPOINT_OUTPUT_BEGIN(spantin, cfg); FIXPOINT_OUTPUT_BEGIN(spantout, cfg); spantout[v] = safeout[v] && accumulate_neighbors(cfg, v, spantin, cfg.graph.out_edges(v), target_ptr, logical_or<bool>(), false, false); spantin[v] = safein[v] && (antloc[v] || (spantout[v] && transp[v])); FIXPOINT_OUTPUT_END(spantout, >=, cfg); FIXPOINT_OUTPUT_END(spantin, >=, cfg); FIXPOINT_END(cfg, in_edges, InEdgeIter) PRINT_PROPERTY(spantin); PRINT_PROPERTY(spantout); #undef PRINT_PROPERTY vector<bool> node_insert(cfg.graph.vertices().size()); vector<bool> replacef(cfg.graph.vertices().size()); vector<bool> replacel(cfg.graph.vertices().size()); // printf ("Intermediate test 1: needToMakeCachevar = %s \n",needToMakeCachevar ? "true" : "false"); for (i = cfg.graph.vertices().begin(); i != end; ++i) { node_insert[*i] = comp[*i] && spantout[*i] && (!transp[*i] || !spavin[*i]); replacef[*i] = antloc[*i] && (spavin[*i] || (transp[*i] && spantout[*i])); replacel[*i] = comp[*i] && (spantout[*i] || (transp[*i] && spavin[*i])); if (node_insert[*i]) { needToMakeCachevar = true; insertions.push_back(make_pair(last_computation[*i], true)); // cerr << "Insert computation of " << expr->unparseToString() << " just before last computation in " << *i << endl; } if (replacef[*i]) { needToMakeCachevar = true; replacements.insert(first_computation[*i]); // cerr << "Replace first computation of " << *i << endl; } if (replacel[*i]) { needToMakeCachevar = true; replacements.insert(last_computation[*i]); // cerr << "Replace last computation of " << *i << endl; } } vector<bool> edge_insert(cfg.graph.edges().size()); // printf ("Intermediate test 2: needToMakeCachevar = %s \n",needToMakeCachevar ? "true" : "false"); EdgeIter j = cfg.graph.edges().begin(), jend = cfg.graph.edges().end(); for (; j != jend; ++j) { edge_insert[*j] = !spavout[cfg.graph.source(*j)] && spavin[cfg.graph.target(*j)] && spantin[cfg.graph.target(*j)]; // printf ("edge_insert[*j] = %s \n",edge_insert[*j] ? "true" : "false"); if (edge_insert[*j]) { needToMakeCachevar = true; // cerr << "Insert computation of " << expr->unparseToString() << " on edge from " // << cfg.graph.source(*j) << " to " << cfg.graph.target(*j) << endl; } } // printf ("Before final test: needToMakeCachevar = %s \n",needToMakeCachevar ? "true" : "false"); // Add cache variable if necessary SgVarRefExp* cachevar = 0; if (needToMakeCachevar) { SgName cachevarname = "cachevar__"; cachevarname << ++SageInterface::gensym_counter; // printf ("Building variable name = %s \n",cachevarname.str()); SgType* type = expr->get_type(); if (isSgArrayType(type)) type = new SgPointerType(isSgArrayType(type)->get_base_type()); assert (SageInterface::isDefaultConstructible(type)); // FIXME: assert (isAssignable(type)); SgVariableDeclaration* decl = new SgVariableDeclaration(SgNULL_FILE, cachevarname, type, NULL); decl->set_definingDeclaration(decl); SgInitializedName* initname = decl->get_variables().back(); // DQ (10/5/2007): Added an assertion. ROSE_ASSERT(initname != NULL); decl->addToAttachedPreprocessingInfo( new PreprocessingInfo(PreprocessingInfo::CplusplusStyleComment, (string("// Partial redundancy elimination: ") + cachevarname.str() + " is a cache of " + expr->unparseToString()).c_str(), "Compiler-Generated in PRE", 0, 0, 0, PreprocessingInfo::before)); SgVariableSymbol* cachevarsym = new SgVariableSymbol(initname); decl->set_parent(root); // DQ (10/5/2007): Added scope (suggested by Jeremiah). initname->set_scope(root); root->get_statements().insert(root->get_statements().begin(),decl); root->insert_symbol(cachevarname, cachevarsym); cachevar = new SgVarRefExp(SgNULL_FILE, cachevarsym); cachevar->set_endOfConstruct(SgNULL_FILE); } // Do expression computation replacements for (set<SgNode*>::iterator i = replacements.begin(); i != replacements.end(); ++i) { ReplaceExpressionWithVarrefVisitor(expr, cachevar).traverse(*i, postorder); } // Do edge insertions // int count = 0; bool failAtEndOfFunction = false; for (j = cfg.graph.edges().begin(); j != jend; ++j) { // printf ("Build the insertion list! count = %d \n",count++); if (edge_insert[*j]) { #if 0 // DQ (3/13/2006): Compiler warns that "src" is unused, so I have commented it out! Vertex src = cfg.graph.source(*j), tgt = cfg.graph.target(*j); cerr << "Doing insertion between " << src << " and " << tgt << endl; #endif pair<SgNode*, bool> insert_point = cfg.edge_insertion_point[*j]; if (insert_point.first) { insertions.push_back(insert_point); } else { // DQ (3/16/2006): This is a visited when we fixup the NULL pointer to the initializer in a SgForStatment. cerr << "Warning: no insertion point found" << endl; //FIXME was assert printf ("Need to figure out what to do here! cfg.edge_insertion_point[*j] = %p \n",&(cfg.edge_insertion_point[*j])); failAtEndOfFunction = true; ROSE_ASSERT(false); } } } // Do within-node insertions // printf ("At start of loop: insertions.size() = %zu \n",insertions.size()); for (vector<pair<SgNode*, bool> >::iterator i = insertions.begin(); i != insertions.end(); ++i) { SgTreeCopy tc1, tc2; SgVarRefExp* cachevarCopy = isSgVarRefExp(cachevar->copy(tc1)); ROSE_ASSERT (cachevarCopy); cachevarCopy->set_lvalue(true); SgExpression* operation = new SgAssignOp(SgNULL_FILE, cachevarCopy, isSgExpression(expr->copy(tc2))); #if 0 printf ("Inside of loop: insertions.size() = %zu \n",insertions.size()); printf ("\n\ni->first = %p = %s = %s \n",i->first,i->first->class_name().c_str(),i->first->unparseToString().c_str()); printf ("operation = %p = %s = %s \n",operation,operation->class_name().c_str(),operation->unparseToString().c_str()); #endif if (isSgExpression(i->first) && !i->second) { SgNode* ifp = i->first->get_parent(); SgCommaOpExp* comma = new SgCommaOpExp(SgNULL_FILE, isSgExpression(i->first), operation); operation->set_parent(comma); comma->set_parent(ifp); i->first->set_parent(comma); if (isSgForStatement(ifp)) { isSgForStatement(ifp)->set_increment(comma); } else if (isSgBinaryOp(ifp) && isSgBinaryOp(ifp)->get_lhs_operand() == i->first) { isSgBinaryOp(ifp)->set_lhs_operand(comma); } else if (isSgBinaryOp(ifp) && isSgBinaryOp(ifp)->get_rhs_operand() == i->first) { isSgBinaryOp(ifp)->set_rhs_operand(comma); } else if (isSgUnaryOp(ifp) && isSgUnaryOp(ifp)->get_operand() == i->first) { isSgUnaryOp(ifp)->set_operand(comma); } else { cerr << ifp->sage_class_name() << endl; assert (!"Bad parent type for inserting comma expression"); } } else { SgStatement* the_computation = new SgExprStatement(SgNULL_FILE, operation); operation->set_parent(the_computation); // printf ("In pre.C: the_computation = %p = %s \n",the_computation,the_computation->class_name().c_str()); if (isSgBasicBlock(i->first) && i->second) { isSgBasicBlock(i->first)->get_statements().insert(isSgBasicBlock(i->first)->get_statements().begin(),the_computation); the_computation->set_parent(i->first); } else { #if 0 // DQ (3/14/2006): Bug here when SgExprStatement from SgForStatement test is used here! printf ("Bug here when SgExprStatement from SgForStatement test is used: i->first = %s \n",i->first->class_name().c_str()); i->first->get_file_info()->display("Location i->first"); printf ("Bug here when SgExprStatement from SgForStatement test is used: TransformationSupport::getStatement(i->first) = %s \n", TransformationSupport::getStatement(i->first)->class_name().c_str()); printf ("Bug here when SgExprStatement from SgForStatement test is used: the_computation = %s \n",the_computation->class_name().c_str()); the_computation->get_file_info()->display("Location the_computation: debug"); ROSE_ASSERT(i->first != NULL); ROSE_ASSERT(i->first->get_parent() != NULL); printf ("i->first->get_parent() = %s \n",i->first->get_parent()->class_name().c_str()); i->first->get_file_info()->display("Location i->first: debug"); #endif SgForStatement* forStatement = isSgForStatement(i->first->get_parent()); if (forStatement != NULL) { // Make sure that both pointers are not equal because they are both NULL! ROSE_ASSERT(forStatement->get_test() != NULL); SgExprStatement* possibleTest = isSgExprStatement(i->first); if ( forStatement->get_test() == possibleTest ) { // This is a special case of a SgExpressionStatement as a target in a SgForStatement // printf ("Found special case of target being the test of a SgForStatement \n"); forStatement->set_test(the_computation); the_computation->set_parent(forStatement); } } else { SgForInitStatement* forInitStatement = isSgForInitStatement(i->first->get_parent()); if (forInitStatement != NULL) { // printf ("Found the SgForInitStatement \n"); SgVariableDeclaration* possibleVariable = isSgVariableDeclaration(i->first); SgExprStatement* possibleExpression = isSgExprStatement(i->first); SgStatementPtrList & statementList = forInitStatement->get_init_stmt(); SgStatementPtrList::iterator i = statementList.begin(); bool addToForInitList = false; while ( (addToForInitList == false) && (i != statementList.end()) ) { // if ( *i == possibleVariable ) if ( *i == possibleVariable || *i == possibleExpression ) { // This is a special case of a SgExpressionStatement as a target in a SgForStatement // printf ("Found special case of SgForInitStatement transformation \n"); addToForInitList = true; } i++; } // Only modify the STL list outside of the loop over the list to avoid interator invalidation if (addToForInitList == true) { // Add the the_computation statment to the list in the SgForInitStatement. // Later if we abandon the SgForInitStatement then we would have to add it to // the list of SgInitializedName objects in the SgVariableDeclaration OR modify // the expression list to handle the extra expression (but I think this case in // handled above). // printf ("Adding the_computation to the list in the SgForInitStatement \n"); statementList.push_back(the_computation); the_computation->set_parent(forInitStatement); } } else { myStatementInsert(TransformationSupport::getStatement(i->first),the_computation,i->second,true); the_computation->set_parent(TransformationSupport::getStatement(i->first)); } } } } } // DQ (3/16/2006): debugging code to force failure at inspection point if (failAtEndOfFunction == true) { printf ("Error: internal error detected \n"); ROSE_ASSERT(false); } }
void RemoveConstantFoldedValueViaParent::visit ( SgNode* node ) { // This is an alternative implementation that allows us to handle expression that are not // traversed in the AST (e.g. types like SgArrayType which can contain expressions). ROSE_ASSERT(node != NULL); // DQ (3/11/2006): Set NULL pointers where we would like to have none. #if 0 printf ("In RemoveConstantFoldedValueViaParent::visit(): node = %p = %s \n",node,node->class_name().c_str()); #endif // DQ (10/12/2012): Turn this on so that we can detect failing IR nodes (failing later) that have valid originalExpressionTrees. // DQ (10/12/2012): Turn this back off because it appears to fail... #if 0 SgExpression* exp = isSgExpression(node); if (exp != NULL) { SgExpression* originalExpressionTree = exp->get_originalExpressionTree(); if (originalExpressionTree != NULL) { SgNode* parent = exp->get_parent(); if (parent != NULL) { printf ("Current IR node with SgExpression parent = %p = %s child = %p = %s originalExpressionTree = %p = %s \n",parent,parent->class_name().c_str(),node,node->class_name().c_str(),originalExpressionTree,originalExpressionTree->class_name().c_str()); bool traceReplacement = true; ConstantFoldedValueReplacer r(traceReplacement, exp); parent->processDataMemberReferenceToPointers(&r); // node->processDataMemberReferenceToPointers(&r); } // Set the originalExpressionTree to NULL. exp->set_originalExpressionTree(NULL); // Set the parent of originalExpressionTree to be the parent of exp. originalExpressionTree->set_parent(parent); // And then delete the folded constant. SageInterface::deleteAST(exp); } } #endif SgArrayType* arrayType = isSgArrayType(node); if (arrayType != NULL) { #if 0 printf ("Found an array type arrayType = %p arrayType->get_index() = %p \n",arrayType,arrayType->get_index()); #endif SgExpression* index = arrayType->get_index(); if (index != NULL) { #if 0 printf ("Fixup array index = %p = %s (traverse index AST subtree) \n",index,index->class_name().c_str()); #endif RemoveConstantFoldedValue astFixupTraversal; astFixupTraversal.traverse(index); #if 0 printf ("DONE: Fixup array index = %p (traverse index AST) \n\n\n\n",index); #endif #if 0 printf ("Found an array index = %p (fixup index directly) \n",index); #endif // Handle the case where the original expression tree is at the root of the subtree. SgExpression* originalExpressionTree = index->get_originalExpressionTree(); if (originalExpressionTree != NULL) { #if 0 printf ("Found an originalExpressionTree in the array index originalExpressionTree = %p \n",originalExpressionTree); #endif // DQ (6/12/2013): This appears to be a problem in EDG 4.7 (see test2011_117.C). std::vector<SgExpression*> redundantChainOfOriginalExpressionTrees; if (originalExpressionTree->get_originalExpressionTree() != NULL) { #if 0 printf ("Detected originalExpressionTree nested directly within the originalExpressionTree \n", originalExpressionTree,originalExpressionTree->class_name().c_str(), originalExpressionTree->get_originalExpressionTree(),originalExpressionTree->get_originalExpressionTree()->class_name().c_str()); #endif // Loop to the end of the chain of original expressions (which EDG 4.7 should never have constructed). while (originalExpressionTree->get_originalExpressionTree() != NULL) { #if 0 printf ("Looping through a chain of originalExpressionTrees \n"); #endif // Save the list of redundnat nodes so that we can delete them properly. redundantChainOfOriginalExpressionTrees.push_back(originalExpressionTree); originalExpressionTree = originalExpressionTree->get_originalExpressionTree(); } #if 0 printf ("Exiting as a test! \n"); ROSE_ASSERT(false); #endif } arrayType->set_index(originalExpressionTree); originalExpressionTree->set_parent(arrayType); index->set_originalExpressionTree(NULL); // printf ("DEBUGING: skip delete of index in array type \n"); delete index; // DQ (6/12/2013): Delete the nodes that we had to skip over (caused by chain of redundant entries from EDG 4.7). std::vector<SgExpression*>::iterator i = redundantChainOfOriginalExpressionTrees.begin(); while (i != redundantChainOfOriginalExpressionTrees.end()) { #if 0 printf ("deleting the redundnat originalExpressionTree chain caused by EDG 4.7 (delete %p = %s) \n",*i,(*i)->class_name().c_str()); #endif delete *i; i++; } index = NULL; } } } SgVariableDefinition* variableDefinition = isSgVariableDefinition(node); if (variableDefinition != NULL) { #if 0 printf ("Found a SgVariableDefinition \n"); #endif SgExpression* bitfieldExp = variableDefinition->get_bitfield(); if (bitfieldExp != NULL) { #if 0 printf ("Fixup bitfieldExp = %p (traverse bitfieldExp AST subtree) \n",bitfieldExp); #endif RemoveConstantFoldedValue astFixupTraversal; astFixupTraversal.traverse(bitfieldExp); // Handle the case where the original expression tree is at the root of the subtree. SgExpression* originalExpressionTree = bitfieldExp->get_originalExpressionTree(); if (originalExpressionTree != NULL) { #if 0 // DQ (9/18/2011): This code will not work since the bitfile data member in SgVariableDefinition is a SgUnsignedLongVal instead of a SgExpression. variableDefinition->set_bitfield(originalExpressionTree); originalExpressionTree->set_parent(variableDefinition); bitfieldExp->set_originalExpressionTree(NULL); delete bitfieldExp; bitfieldExp = NULL; #else // The ROSE AST needs to be fixed to handle more general expressions for bitfield widths (this does not effect the CFG). // TODO: Change the data type of the bitfield data member in SgVariableDefinition. // DQ (1/20/2014): This has been done now. // printf ("Member data bitfield widths need to be changed (in the ROSE IR) to support more general expressions (can't fix this original expression tree) \n"); #endif #if 0 // This case is not handled yet! printf ("Found an original expression tree in a bitfield expression \n"); ROSE_ASSERT(false); #endif } } } }
void ConstantFoldedValueReplacer::operator()(SgNode*& key, const SgName & debugStringName, bool /* traverse */ traceReplacement) { // This function is used to replace the expression in an AST node and avoids explicitly handling all of the cases // of where an IR node can exist in the AST (in this case expressions containing an opriginal expression tree could // be in a lot of locations). // Note that the key will be a reference to the pointer for each data member of the IR node where: // node->processDataMemberReferenceToPointers(&r); // is called. #if 0 printf ("Inside of ConstantFoldedValueReplacer::operator() key = %p = %s = %s node = %p = %s = %s \n", key,(key != NULL) ? key->class_name().c_str() : "NULL",(key != NULL) ? SageInterface::get_name(key).c_str() : "NULL", targetNode,(targetNode != NULL) ? targetNode->class_name().c_str() : "NULL",(targetNode != NULL) ? SageInterface::get_name(targetNode).c_str() : "NULL"); #endif if (key != NULL) { // Now reset the pointer to the subtree identified as redundent with a // subtree in the original AST to the subtree in the original (merged) AST. // Note: targetNode is the IR node to be replaced (set in the ConstantFoldedValueReplacer constructor call). if (key == targetNode) { #if 0 printf ("Note that key == originalNode \n"); #endif SgExpression* keyExpression = isSgExpression(key); // DQ (9/17/2011): We don't want to eliminate references to enum values (see test2005_194.C). // Though I wonder if it could be that we are not distinguishing the enum value and the // values of the enum variables (the order of the fields in the enum declaration). if (isSgEnumVal(keyExpression) == NULL) { if (keyExpression != NULL) { #if 0 printf ("Note that key is a valid expression keyExpression->get_originalExpressionTree() = %p \n",keyExpression->get_originalExpressionTree()); #endif if (keyExpression->get_originalExpressionTree() != NULL) { #if 0 printf ("key contains a originalExpressionTree = %p = %s \n",keyExpression->get_originalExpressionTree(),keyExpression->get_originalExpressionTree()->class_name().c_str()); #endif // DQ (10/8/2011): Added support for chains of expression trees. // while (keyExpression->get_originalExpressionTree()->get_originalExpressionTree() != NULL) while (keyExpression->get_originalExpressionTree()->get_originalExpressionTree() != NULL && isSgEnumVal(keyExpression->get_originalExpressionTree()) == NULL) { SgExpression* nestedOriginalExpressionTree = keyExpression->get_originalExpressionTree(); ROSE_ASSERT(nestedOriginalExpressionTree != NULL); #if 0 printf ("Found a chain of original expression trees (iterate to find the end of the chain: keyExpression = %p = %s keyExpression->get_originalExpressionTree() = %p = %s \n", keyExpression,keyExpression->class_name().c_str(),nestedOriginalExpressionTree,nestedOriginalExpressionTree->class_name().c_str()); #endif keyExpression = nestedOriginalExpressionTree; } // If this is an enum value, then we don't want the original expression tree (which // will otherwise be substituted into such places as SgCaseOptionStmt nodes, etc.). SgEnumVal* enumValue = isSgEnumVal(keyExpression->get_originalExpressionTree()); if (enumValue != NULL) { #if 0 printf ("Detected case of enumValue = %p \n",enumValue); #endif if (enumValue->get_originalExpressionTree()) { #if 0 printf ("Deleting the original expression in the nested enumValue \n"); #endif deleteOriginalExpressionTree(enumValue->get_originalExpressionTree()); enumValue->set_originalExpressionTree(NULL); } } ROSE_ASSERT(keyExpression->get_originalExpressionTree() != NULL); key = keyExpression->get_originalExpressionTree(); ROSE_ASSERT(key != NULL); // Set the parent node ROSE_ASSERT(keyExpression->get_originalExpressionTree() != NULL); keyExpression->get_originalExpressionTree()->set_parent(targetNode->get_parent()); SgExpression* targetExpression = isSgExpression(targetNode); // Clear the originalExpressionTree targetExpression->set_originalExpressionTree(NULL); ROSE_ASSERT(targetExpression->get_originalExpressionTree() == NULL); targetExpression->set_parent(NULL); // DQ (9/24/2011): This can be an expression tree (more than just a single IR node (see test2011_140.C). // delete targetNode; SageInterface::deleteAST(targetExpression); // Reset the pointer to avoid any dangling pointer problems. targetNode = NULL; } } else { #if 0 printf ("key is not a SgExpression \n"); #endif } } else { // For the case of a SgEnumVal, don't use the original expression tree (see test2005_194.C) // The original expression tree holds the value used for the enum field, instead of the // reference to the correct enum field). #if 0 printf ("ENUM VALUE special handling: we call deleteOriginalExpressionTree(keyExpression = %p) \n",keyExpression); #endif deleteOriginalExpressionTree(keyExpression); } } else { #if 0 printf ("key != originalNode \n"); #endif } } else { #if 0 printf ("key == NULL \n"); #endif } #if 0 printf ("Leaving ConstantFoldedValueReplacer::operator() new reset key = %p = %s \n",key,(key != NULL) ? key->class_name().c_str() : "NULL"); #endif }
void Fortran_to_C::translateArraySubscript(SgPntrArrRefExp* pntrArrRefExp) { // get lhs operand SgVarRefExp* arrayName = isSgVarRefExp(pntrArrRefExp->get_lhs_operand()); SgExpression* baseExp = isSgExpression(arrayName); // get array symbol SgVariableSymbol* arraySymbol = arrayName->get_symbol(); // get array type and dim_info SgArrayType* arrayType = isSgArrayType(arraySymbol->get_type()); ROSE_ASSERT(arrayType); SgExprListExp* dimInfo = arrayType->get_dim_info(); // get rhs operand SgExprListExp* arraySubscript = isSgExprListExp(pntrArrRefExp->get_rhs_operand()); if(arrayType->findBaseType()->variantT() == V_SgTypeString) { arraySubscript->prepend_expression(buildIntVal(1)); } /* No matter it is single or multi dimensional array, pntrArrRefExp always has a child, SgExprListExp, to store the subscript information. */ if(arraySubscript != NULL) { // get the list of subscript SgExpressionPtrList subscriptExprList = arraySubscript->get_expressions(); // get the list of dimension inforamtion from array definition. SgExpressionPtrList dimExpressionPtrList = dimInfo->get_expressions(); // Create new SgExpressionPtrList for the linearalized array subscript. SgExpressionPtrList newSubscriptExprList; // rank info has to match between subscripts and dim_info ROSE_ASSERT(arraySubscript->get_expressions().size() == dimInfo->get_expressions().size()); if(subscriptExprList.size() == 1) { Rose_STL_Container<SgExpression*>::iterator j1 = subscriptExprList.begin(); Rose_STL_Container<SgExpression*>::iterator j2 = dimExpressionPtrList.begin(); SgExpression* newIndexExp = get0basedIndex(*j1, *j2); pntrArrRefExp->set_rhs_operand(newIndexExp); } else { Rose_STL_Container<SgExpression*>::reverse_iterator j1 = subscriptExprList.rbegin(); Rose_STL_Container<SgExpression*>::reverse_iterator j2 = dimExpressionPtrList.rbegin(); SgExpression* newIndexExp = get0basedIndex(*j1, *j2); SgPntrArrRefExp* newPntrArrRefExp = buildPntrArrRefExp(baseExp, newIndexExp); baseExp->set_parent(newPntrArrRefExp); j1 = j1 + 1; j2 = j2 + 1; for(; j1< (subscriptExprList.rend()-1); ++j1, ++j2) { SgExpression* newIndexExp = get0basedIndex(*j1, *j2); baseExp = isSgExpression(newPntrArrRefExp); newPntrArrRefExp = buildPntrArrRefExp(baseExp, newIndexExp); baseExp->set_parent(newPntrArrRefExp); } newIndexExp = get0basedIndex(*j1, *j2); pntrArrRefExp->set_lhs_operand(newPntrArrRefExp); pntrArrRefExp->set_rhs_operand(newIndexExp); newIndexExp->set_parent(pntrArrRefExp); } } }
int main( int argc, char * argv[] ) { // Option to linearize the array. Rose_STL_Container<std::string> localCopy_argv = CommandlineProcessing::generateArgListFromArgcArgv(argc, argv); int newArgc; char** newArgv = NULL; vector<string> argList = localCopy_argv; if (CommandlineProcessing::isOption(argList,"-f2c:","linearize",true) == true) { isLinearlizeArray = true; } CommandlineProcessing::generateArgcArgvFromList(argList,newArgc, newArgv); // Build the AST used by ROSE SgProject* project = frontend(newArgc,newArgv); AstTests::runAllTests(project); if (SgProject::get_verbose() > 2) generateAstGraph(project,8000,"_orig"); // Traversal with Memory Pool to search for variableDeclaration variableDeclTraversal translateVariableDeclaration; traverseMemoryPoolVisitorPattern(translateVariableDeclaration); for(vector<SgVariableDeclaration*>::iterator dec=variableDeclList.begin(); dec!=variableDeclList.end(); ++dec) { /* For the Fortran AST, a single variableDeclaration can be shared by multiple variables. This violated the normalization rules for C unparser. Therefore, we have to transform it. */ SgVariableDeclaration* variableDeclaration = isSgVariableDeclaration(*dec); ROSE_ASSERT(variableDeclaration); if((variableDeclaration->get_variables()).size() != 1) { updateVariableDeclarationList(variableDeclaration); statementList.push_back(variableDeclaration); removeList.push_back(variableDeclaration); } } // reset the vector that collects all variable declaration. We need to walk through memory pool again to find types variableDeclList.clear(); traverseMemoryPoolVisitorPattern(translateVariableDeclaration); for(vector<SgVariableDeclaration*>::iterator dec=variableDeclList.begin(); dec!=variableDeclList.end(); ++dec) { SgVariableDeclaration* variableDeclaration = isSgVariableDeclaration(*dec); ROSE_ASSERT(variableDeclaration); SgInitializedNamePtrList initializedNameList = variableDeclaration->get_variables(); for(SgInitializedNamePtrList::iterator i=initializedNameList.begin(); i!=initializedNameList.end();++i) { SgInitializedName* initiallizedName = isSgInitializedName(*i); SgType* baseType = initiallizedName->get_type(); if(baseType->variantT() == V_SgArrayType) { SgArrayType* arrayBase = isSgArrayType(baseType); // At this moment, we are still working on the Fortran-stype AST. Therefore, there is no nested types for multi-dim array. if(arrayBase->findBaseType()->variantT() == V_SgTypeString) { arrayBase->reset_base_type(translateType(arrayBase->findBaseType())); arrayBase->set_rank(arrayBase->get_rank()+1); } } else { initiallizedName->set_type(translateType(baseType)); } } } // replace the AttributeSpecificationStatement Rose_STL_Container<SgNode*> AttributeSpecificationStatement = NodeQuery::querySubTree (project,V_SgAttributeSpecificationStatement); for (Rose_STL_Container<SgNode*>::iterator i = AttributeSpecificationStatement.begin(); i != AttributeSpecificationStatement.end(); i++) { SgAttributeSpecificationStatement* attributeSpecificationStatement = isSgAttributeSpecificationStatement(*i); ROSE_ASSERT(attributeSpecificationStatement); translateAttributeSpecificationStatement(attributeSpecificationStatement); statementList.push_back(attributeSpecificationStatement); removeList.push_back(attributeSpecificationStatement); } // replace the parameter reference parameterTraversal translateParameterRef; traverseMemoryPoolVisitorPattern(translateParameterRef); for(vector<SgVarRefExp*>::iterator i=parameterRefList.begin(); i!=parameterRefList.end(); ++i) { SgVarRefExp* parameterRef = isSgVarRefExp(*i); if(parameterSymbolList.find(parameterRef->get_symbol()) != parameterSymbolList.end()) { SgExpression* newExpr = isSgExpression(deepCopy(parameterSymbolList.find(parameterRef->get_symbol())->second)); ROSE_ASSERT(newExpr); newExpr->set_parent(parameterRef->get_parent()); replaceExpression(parameterRef, newExpr, false); } } /* Parameters will be replaced by #define, all the declarations should be removed */ for(map<SgVariableSymbol*,SgExpression*>::iterator i=parameterSymbolList.begin();i!=parameterSymbolList.end();++i) { SgVariableSymbol* symbol = i->first; SgInitializedName* initializedName = symbol->get_declaration(); SgVariableDeclaration* decl = isSgVariableDeclaration(initializedName->get_parent()); statementList.push_back(decl); removeList.push_back(decl); } // Traversal with Memory Pool to search for arrayType arrayTypeTraversal translateArrayType; traverseMemoryPoolVisitorPattern(translateArrayType); for(vector<SgArrayType*>::iterator i=arrayTypeList.begin(); i!=arrayTypeList.end(); ++i) { if(isLinearlizeArray) { linearizeArrayDeclaration(*i); } else { translateArrayDeclaration(*i); } } // Traversal with Memory Pool to search for pntrArrRefExp pntrArrRefTraversal translatePntrArrRefExp; traverseMemoryPoolVisitorPattern(translatePntrArrRefExp); for(vector<SgPntrArrRefExp*>::iterator i=pntrArrRefList.begin(); i!=pntrArrRefList.end(); ++i) { if(isLinearlizeArray) { linearizeArraySubscript(*i); } else { translateArraySubscript(*i); } } Rose_STL_Container<SgNode*> functionList = NodeQuery::querySubTree (project,V_SgFunctionDeclaration); for (Rose_STL_Container<SgNode*>::iterator i = functionList.begin(); i != functionList.end(); i++) { if((isSgProcedureHeaderStatement(*i) != NULL) || (isSgProgramHeaderStatement(*i) != NULL)){ SgFunctionDeclaration* functionBody = isSgFunctionDeclaration(*i); bool hasReturnVal = false; if(isSgProcedureHeaderStatement(functionBody)) { hasReturnVal = isSgProcedureHeaderStatement(functionBody)->isFunction(); } fixFortranSymbolTable(functionBody->get_definition(),hasReturnVal); } } // Traversal with Memory Pool to search for equivalenceStatement equivalencelTraversal translateEquivalenceStmt; traverseMemoryPoolVisitorPattern(translateEquivalenceStmt); for(vector<SgEquivalenceStatement*>::iterator i=equivalenceList.begin(); i!=equivalenceList.end(); ++i) { SgEquivalenceStatement* equivalenceStatement = isSgEquivalenceStatement(*i); ROSE_ASSERT(equivalenceStatement); translateEquivalenceStatement(equivalenceStatement); statementList.push_back(equivalenceStatement); removeList.push_back(equivalenceStatement); } // Simple traversal, bottom-up, to translate the rest f2cTraversal f2c; f2c.traverseInputFiles(project,postorder); // removing all the unsed statement from AST for(vector<SgStatement*>::iterator i=statementList.begin(); i!=statementList.end(); ++i) { removeStatement(*i); (*i)->set_parent(NULL); } // deepDelete the removed nodes for(vector<SgNode*>::iterator i=removeList.begin(); i!=removeList.end(); ++i) { deepDelete(*i); } /* 1. There should be no Fortran-specific AST nodes in the whole AST graph after the translation. TODO: make sure translator generating clean AST */ //generateDOT(*project); if (SgProject::get_verbose() > 2) generateAstGraph(project,8000); return backend(project); }
// 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 } } } }