SgVariableDeclaration* buildStructVariable ( SgScopeStatement* scope, vector<SgType*> memberTypes, vector<string> memberNames, string structName = "", string varName = "", SgAggregateInitializer *initializer = NULL ) { ROSE_ASSERT(memberTypes.size() == memberNames.size()); SgClassDeclaration* classDeclaration = buildClassDeclarationAndDefinition(structName,scope); vector<SgType*>::iterator typeIterator = memberTypes.begin(); vector<string>::iterator memberNameIterator = memberNames.begin(); while (typeIterator != memberTypes.end()) { // printf ("Adding data member type = %s variable name = %s \n",(*typeIterator)->unparseToString().c_str(),memberNameIterator->c_str()); SgVariableDeclaration* memberDeclaration = new SgVariableDeclaration(SOURCE_POSITION,*memberNameIterator,*typeIterator,NULL); memberDeclaration->set_endOfConstruct(SOURCE_POSITION); classDeclaration->get_definition()->append_member(memberDeclaration); memberDeclaration->set_parent(classDeclaration->get_definition()); // Liao (2/13/2008) scope and symbols for member variables SgInitializedName* initializedName = *(memberDeclaration->get_variables().begin()); initializedName->set_file_info(SOURCE_POSITION); initializedName->set_scope(classDeclaration->get_definition()); // set nondefning declaration pointer memberDeclaration->set_firstNondefiningDeclaration(memberDeclaration); SgVariableSymbol* variableSymbol = new SgVariableSymbol(initializedName); classDeclaration->get_definition()->insert_symbol(*memberNameIterator,variableSymbol); typeIterator++; memberNameIterator++; } SgClassType* classType = new SgClassType(classDeclaration->get_firstNondefiningDeclaration()); SgVariableDeclaration* variableDeclaration = new SgVariableDeclaration(SOURCE_POSITION,varName,classType,initializer); variableDeclaration->set_endOfConstruct(SOURCE_POSITION); //Liao (2/13/2008) scope and symbols for struct variable SgInitializedName* initializedName = *(variableDeclaration->get_variables().begin()); initializedName->set_file_info(SOURCE_POSITION); initializedName->set_scope(scope); SgVariableSymbol* variableSymbol = new SgVariableSymbol(initializedName); scope->insert_symbol(varName,variableSymbol); //set nondefining declaration variableDeclaration->set_firstNondefiningDeclaration(variableDeclaration); // This is required, since it is not set in the SgVariableDeclaration constructor initializer->set_parent(variableDeclaration); variableDeclaration->set_variableDeclarationContainsBaseTypeDefiningDeclaration(true); variableDeclaration->set_baseTypeDefiningDeclaration(classDeclaration->get_definingDeclaration()); classDeclaration->set_parent(variableDeclaration); return variableDeclaration; }
DoxygenFile::DoxygenFile(SgProject *prj, string filename) { Sg_File_Info *info = new Sg_File_Info(filename, 0, 0); SgInitializedName *iname = new SgInitializedName; stringstream sname; sname << "SAGE_Doxygen_Dummy_" << rand(); iname->set_name(sname.str()); iname->set_type(new SgTypeInt); iname->set_file_info(info); iname->get_storageModifier().setExtern(); SgVariableDeclaration *decl = new SgVariableDeclaration; decl->get_variables().push_back(iname); decl->set_startOfConstruct(info); decl->set_endOfConstruct(info); decl->get_declarationModifier().get_storageModifier().setExtern(); iname->set_parent(decl); iname->set_prev_decl_item(iname); // SgGlobal *glob = prj->get_file(0).get_globalScope(); SgSourceFile* sourceFile = isSgSourceFile(prj->get_fileList()[0]); ROSE_ASSERT(sourceFile != NULL); SgGlobal *glob = sourceFile->get_globalScope(); // glob->insertStatementInScope(decl, true); glob->get_declarations().insert(glob->get_declarations().begin(),decl); decl->set_parent(glob); SgVariableSymbol* variableSymbol = new SgVariableSymbol(iname); glob->insert_symbol(sname.str(),variableSymbol); decl->set_parent(glob); std::cout << "Before complete string." << std::endl; //glob->append_declaration(decl); iname->set_scope(glob); decl->unparseToCompleteString(); std::cout << "After complete string." << std::endl; commentParent = decl; printf("commentParent = %p\n", commentParent); }
// ****************************************** // MAIN PROGRAM // ****************************************** int main( int argc, char * argv[] ) { // Initialize and check compatibility. See rose::initialize ROSE_INITIALIZE; // Build the AST used by ROSE SgProject* project = frontend(argc,argv); assert(project != NULL); vector<SgType*> memberTypes; vector<string> memberNames; string name = "a"; for (int i = 0; i < 10; i++) { memberTypes.push_back(SgTypeInt::createType()); name = "_" + name; memberNames.push_back(name); } // Build the initializer SgExprListExp* initializerList = new SgExprListExp(SOURCE_POSITION); initializerList->set_endOfConstruct(SOURCE_POSITION); SgAggregateInitializer* structureInitializer = new SgAggregateInitializer(SOURCE_POSITION,initializerList); structureInitializer->set_endOfConstruct(SOURCE_POSITION); // Build the data member initializers for the structure (one SgAssignInitializer for each data member) for (unsigned int i = 0; i < memberNames.size(); i++) { // Set initial value to "i" SgIntVal* value = new SgIntVal(SOURCE_POSITION,i); value->set_endOfConstruct(SOURCE_POSITION); SgAssignInitializer* memberInitializer = new SgAssignInitializer(SOURCE_POSITION,value); memberInitializer->set_endOfConstruct(SOURCE_POSITION); structureInitializer->append_initializer(memberInitializer); memberInitializer->set_parent(structureInitializer); } // Access the first file and add a struct with data members specified SgSourceFile* file = isSgSourceFile((*project)[0]); ROSE_ASSERT(file != NULL); SgVariableDeclaration* variableDeclaration = buildStructVariable(file->get_globalScope(),memberTypes,memberNames,"X","x",structureInitializer); file->get_globalScope()->prepend_declaration(variableDeclaration); variableDeclaration->set_parent(file->get_globalScope()); AstTests::runAllTests(project); // Code generation phase (write out new application "rose_<input file name>") return backend(project); }
void SimpleInstrumentation::visit ( SgNode* astNode ) { SgBasicBlock* block = isSgBasicBlock(astNode); if (block != NULL) { // Mark this as a transformation (required) Sg_File_Info* sourceLocation = Sg_File_Info::generateDefaultFileInfoForTransformationNode(); ROSE_ASSERT(sourceLocation != NULL); SgType* type = new SgTypeInt(); ROSE_ASSERT(type != NULL); SgName name = "newVariable"; SgVariableDeclaration* variableDeclaration = new SgVariableDeclaration(sourceLocation,name,type); ROSE_ASSERT(variableDeclaration != NULL); SgInitializedName* initializedName = *(variableDeclaration->get_variables().begin()); initializedName->set_file_info(Sg_File_Info::generateDefaultFileInfoForTransformationNode()); // DQ (6/18/2007): The unparser requires that the scope be set (for name qualification to work). initializedName->set_scope(block); // Liao (2/13/2008): AstTests requires this to be set variableDeclaration->set_firstNondefiningDeclaration(variableDeclaration); ROSE_ASSERT(block->get_statements().size() > 0); block->get_statements().insert(block->get_statements().begin(),variableDeclaration); variableDeclaration->set_parent(block); // Add a symbol to the sybol table for the new variable SgVariableSymbol* variableSymbol = new SgVariableSymbol(initializedName); block->insert_symbol(name,variableSymbol); } }
// 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); } }
// Main inliner code. Accepts a function call as a parameter, and inlines // only that single function call. Returns true if it succeeded, and false // otherwise. The function call must be to a named function, static member // function, or non-virtual non-static member function, and the function // must be known (not through a function pointer or member function // pointer). Also, the body of the function must already be visible. // Recursive procedures are handled properly (when allowRecursion is set), by // inlining one copy of the procedure into itself. Any other restrictions on // what can be inlined are bugs in the inliner code. bool doInline(SgFunctionCallExp* funcall, bool allowRecursion) { #if 0 // DQ (4/6/2015): Adding code to check for consitancy of checking the isTransformed flag. ROSE_ASSERT(funcall != NULL); ROSE_ASSERT(funcall->get_parent() != NULL); SgGlobal* globalScope = TransformationSupport::getGlobalScope(funcall); ROSE_ASSERT(globalScope != NULL); // checkTransformedFlagsVisitor(funcall->get_parent()); checkTransformedFlagsVisitor(globalScope); #endif SgExpression* funname = funcall->get_function(); SgExpression* funname2 = isSgFunctionRefExp(funname); SgDotExp* dotexp = isSgDotExp(funname); SgArrowExp* arrowexp = isSgArrowExp(funname); SgExpression* thisptr = 0; if (dotexp || arrowexp) { funname2 = isSgBinaryOp(funname)->get_rhs_operand(); if (dotexp) { SgExpression* lhs = dotexp->get_lhs_operand(); // FIXME -- patch this into p_lvalue bool is_lvalue = lhs->get_lvalue(); if (isSgInitializer(lhs)) is_lvalue = false; if (!is_lvalue) { SgAssignInitializer* ai = SageInterface::splitExpression(lhs); ROSE_ASSERT (isSgInitializer(ai->get_operand())); #if 1 printf ("ai = %p ai->isTransformation() = %s \n",ai,ai->isTransformation() ? "true" : "false"); #endif SgInitializedName* in = isSgInitializedName(ai->get_parent()); ROSE_ASSERT (in); removeRedundantCopyInConstruction(in); lhs = dotexp->get_lhs_operand(); // Should be a var ref now } thisptr = new SgAddressOfOp(SgNULL_FILE, lhs); } else if (arrowexp) { thisptr = arrowexp->get_lhs_operand(); } else { assert (false); } } if (!funname2) { // std::cout << "Inline failed: not a call to a named function" << std::endl; return false; // Probably a call through a fun ptr } SgFunctionSymbol* funsym = 0; if (isSgFunctionRefExp(funname2)) funsym = isSgFunctionRefExp(funname2)->get_symbol(); else if (isSgMemberFunctionRefExp(funname2)) funsym = isSgMemberFunctionRefExp(funname2)->get_symbol(); else assert (false); assert (funsym); if (isSgMemberFunctionSymbol(funsym) && isSgMemberFunctionSymbol(funsym)->get_declaration()->get_functionModifier().isVirtual()) { // std::cout << "Inline failed: cannot inline virtual member functions" << std::endl; return false; } SgFunctionDeclaration* fundecl = funsym->get_declaration(); fundecl = fundecl ? isSgFunctionDeclaration(fundecl->get_definingDeclaration()) : NULL; SgFunctionDefinition* fundef = fundecl ? fundecl->get_definition() : NULL; if (!fundef) { // std::cout << "Inline failed: no definition is visible" << std::endl; return false; // No definition of the function is visible } if (!allowRecursion) { SgNode* my_fundef = funcall; while (my_fundef && !isSgFunctionDefinition(my_fundef)) { // printf ("Before reset: my_fundef = %p = %s \n",my_fundef,my_fundef->class_name().c_str()); my_fundef = my_fundef->get_parent(); ROSE_ASSERT(my_fundef != NULL); // printf ("After reset: my_fundef = %p = %s \n",my_fundef,my_fundef->class_name().c_str()); } // printf ("After reset: my_fundef = %p = %s \n",my_fundef,my_fundef->class_name().c_str()); assert (isSgFunctionDefinition(my_fundef)); if (isSgFunctionDefinition(my_fundef) == fundef) { std::cout << "Inline failed: trying to inline a procedure into itself" << std::endl; return false; } } SgVariableDeclaration* thisdecl = 0; SgName thisname("this__"); thisname << ++gensym_counter; SgInitializedName* thisinitname = 0; if (isSgMemberFunctionSymbol(funsym) && !fundecl->get_declarationModifier().get_storageModifier().isStatic()) { assert (thisptr != NULL); SgType* thisptrtype = thisptr->get_type(); const SgSpecialFunctionModifier& specialMod = funsym->get_declaration()->get_specialFunctionModifier(); if (specialMod.isConstructor()) { SgFunctionType* ft = funsym->get_declaration()->get_type(); ROSE_ASSERT (ft); SgMemberFunctionType* mft = isSgMemberFunctionType(ft); ROSE_ASSERT (mft); SgType* ct = mft->get_class_type(); thisptrtype = new SgPointerType(ct); } SgConstVolatileModifier& thiscv = fundecl->get_declarationModifier().get_typeModifier().get_constVolatileModifier(); // if (thiscv.isConst() || thiscv.isVolatile()) { FIXME thisptrtype = new SgModifierType(thisptrtype); isSgModifierType(thisptrtype)->get_typeModifier().get_constVolatileModifier() = thiscv; // } // cout << thisptrtype->unparseToString() << " --- " << thiscv.isConst() << " " << thiscv.isVolatile() << endl; SgAssignInitializer* assignInitializer = new SgAssignInitializer(SgNULL_FILE, thisptr); assignInitializer->set_endOfConstruct(SgNULL_FILE); #if 1 printf ("before new SgVariableDeclaration(): assignInitializer = %p assignInitializer->isTransformation() = %s \n",assignInitializer,assignInitializer->isTransformation() ? "true" : "false"); #endif thisdecl = new SgVariableDeclaration(SgNULL_FILE, thisname, thisptrtype, assignInitializer); #if 1 printf ("(after new SgVariableDeclaration(): assignInitializer = %p assignInitializer->isTransformation() = %s \n",assignInitializer,assignInitializer->isTransformation() ? "true" : "false"); #endif thisdecl->set_endOfConstruct(SgNULL_FILE); thisdecl->get_definition()->set_endOfConstruct(SgNULL_FILE); thisdecl->set_definingDeclaration(thisdecl); thisinitname = (thisdecl->get_variables()).back(); //thisinitname = lastElementOfContainer(thisdecl->get_variables()); // thisinitname->set_endOfConstruct(SgNULL_FILE); assignInitializer->set_parent(thisinitname); markAsTransformation(assignInitializer); // printf ("Built new SgVariableDeclaration #1 = %p \n",thisdecl); // DQ (6/23/2006): New test ROSE_ASSERT(assignInitializer->get_parent() != NULL); } // Get the list of actual argument expressions from the function call, which we'll later use to initialize new local // variables in the inlined code. We need to detach the actual arguments from the AST here since we'll be reattaching // them below (otherwise we would violate the invariant that the AST is a tree). SgFunctionDefinition* targetFunction = PRE::getFunctionDefinition(funcall); SgExpressionPtrList funargs = funcall->get_args()->get_expressions(); funcall->get_args()->get_expressions().clear(); BOOST_FOREACH (SgExpression *actual, funargs) actual->set_parent(NULL); // Make a copy of the to-be-inlined function so we're not modifying and (re)inserting the original. SgBasicBlock* funbody_raw = fundef->get_body(); SgInitializedNamePtrList& params = fundecl->get_args(); std::vector<SgInitializedName*> inits; SgTreeCopy tc; SgFunctionDefinition* function_copy = isSgFunctionDefinition(fundef->copy(tc)); ROSE_ASSERT (function_copy); SgBasicBlock* funbody_copy = function_copy->get_body(); renameLabels(funbody_copy, targetFunction); ASSERT_require(funbody_raw->get_symbol_table()->size() == funbody_copy->get_symbol_table()->size()); // We don't need to keep the copied SgFunctionDefinition now that the labels in it have been moved to the target function // (having it in the memory pool confuses the AST tests), but we must not delete the formal argument list or the body // because we need them below. if (function_copy->get_declaration()) { ASSERT_require(function_copy->get_declaration()->get_parent() == function_copy); function_copy->get_declaration()->set_parent(NULL); function_copy->set_declaration(NULL); } if (function_copy->get_body()) { ASSERT_require(function_copy->get_body()->get_parent() == function_copy); function_copy->get_body()->set_parent(NULL); function_copy->set_body(NULL); } delete function_copy; function_copy = NULL; #if 0 SgPragma* pragmaBegin = new SgPragma("start_of_inline_function", SgNULL_FILE); SgPragmaDeclaration* pragmaBeginDecl = new SgPragmaDeclaration(SgNULL_FILE, pragmaBegin); pragmaBeginDecl->set_endOfConstruct(SgNULL_FILE); pragmaBegin->set_parent(pragmaBeginDecl); pragmaBeginDecl->set_definingDeclaration(pragmaBeginDecl); funbody_copy->prepend_statement(pragmaBeginDecl); pragmaBeginDecl->set_parent(funbody_copy); #endif // In the to-be-inserted function body, create new local variables with distinct non-conflicting names, one per formal // argument and having the same type as the formal argument. Initialize those new local variables with the actual // arguments. Also, build a paramMap that maps each formal argument (SgInitializedName) to its corresponding new local // variable (SgVariableSymbol). ReplaceParameterUseVisitor::paramMapType paramMap; SgInitializedNamePtrList::iterator formalIter = params.begin(); SgExpressionPtrList::iterator actualIter = funargs.begin(); for (size_t argNumber=0; formalIter != params.end() && actualIter != funargs.end(); ++argNumber, ++formalIter, ++actualIter) { SgInitializedName *formalArg = *formalIter; SgExpression *actualArg = *actualIter; // Build the new local variable. // FIXME[Robb P. Matzke 2014-12-12]: we need a better way to generate a non-conflicting local variable name SgAssignInitializer* initializer = new SgAssignInitializer(SgNULL_FILE, actualArg, formalArg->get_type()); ASSERT_not_null(initializer); initializer->set_endOfConstruct(SgNULL_FILE); #if 1 printf ("initializer = %p initializer->isTransformation() = %s \n",initializer,initializer->isTransformation() ? "true" : "false"); #endif SgName shadow_name(formalArg->get_name()); shadow_name << "__" << ++gensym_counter; SgVariableDeclaration* vardecl = new SgVariableDeclaration(SgNULL_FILE, shadow_name, formalArg->get_type(), initializer); vardecl->set_definingDeclaration(vardecl); vardecl->set_endOfConstruct(SgNULL_FILE); vardecl->get_definition()->set_endOfConstruct(SgNULL_FILE); vardecl->set_parent(funbody_copy); // Insert the new local variable into the (near) beginning of the to-be-inserted function body. We insert them in the // order their corresponding actuals/formals appear, although the C++ standard does not require this order of // evaluation. SgInitializedName* init = vardecl->get_variables().back(); inits.push_back(init); initializer->set_parent(init); init->set_scope(funbody_copy); funbody_copy->get_statements().insert(funbody_copy->get_statements().begin() + argNumber, vardecl); SgVariableSymbol* sym = new SgVariableSymbol(init); paramMap[formalArg] = sym; funbody_copy->insert_symbol(shadow_name, sym); sym->set_parent(funbody_copy->get_symbol_table()); } // Similarly for "this". We create a local variable in the to-be-inserted function body that will be initialized with the // caller's "this". if (thisdecl) { thisdecl->set_parent(funbody_copy); thisinitname->set_scope(funbody_copy); funbody_copy->get_statements().insert(funbody_copy->get_statements().begin(), thisdecl); SgVariableSymbol* thisSym = new SgVariableSymbol(thisinitname); funbody_copy->insert_symbol(thisname, thisSym); thisSym->set_parent(funbody_copy->get_symbol_table()); ReplaceThisWithRefVisitor(thisSym).traverse(funbody_copy, postorder); } ReplaceParameterUseVisitor(paramMap).traverse(funbody_copy, postorder); SgName end_of_inline_name = "rose_inline_end__"; end_of_inline_name << ++gensym_counter; SgLabelStatement* end_of_inline_label = new SgLabelStatement(SgNULL_FILE, end_of_inline_name); end_of_inline_label->set_endOfConstruct(SgNULL_FILE); #if 0 printf ("\n\nCalling AST copy mechanism on a SgBasicBlock \n"); // Need to set the parent of funbody_copy to avoid error. funbody_copy->set_parent(funbody_raw->get_parent()); printf ("This is a copy of funbody_raw = %p to build funbody_copy = %p \n",funbody_raw,funbody_copy); printf ("funbody_raw->get_statements().size() = %" PRIuPTR " \n",funbody_raw->get_statements().size()); printf ("funbody_copy->get_statements().size() = %" PRIuPTR " \n",funbody_copy->get_statements().size()); printf ("funbody_raw->get_symbol_table()->size() = %d \n",(int)funbody_raw->get_symbol_table()->size()); printf ("funbody_copy->get_symbol_table()->size() = %d \n",(int)funbody_copy->get_symbol_table()->size()); printf ("Output the symbol table for funbody_raw \n"); funbody_raw->get_symbol_table()->print("debugging copy problem"); // printf ("Output the symbol table for funbody_copy \n"); // funbody_copy->get_symbol_table()->print("debugging copy problem"); SgProject* project_copy = TransformationSupport::getProject(funbody_raw); ROSE_ASSERT(project_copy != NULL); const int MAX_NUMBER_OF_IR_NODES_TO_GRAPH_FOR_WHOLE_GRAPH = 4000; generateAstGraph(project_copy,MAX_NUMBER_OF_IR_NODES_TO_GRAPH_FOR_WHOLE_GRAPH); #endif funbody_copy->append_statement(end_of_inline_label); end_of_inline_label->set_scope(targetFunction); SgLabelSymbol* end_of_inline_label_sym = new SgLabelSymbol(end_of_inline_label); end_of_inline_label_sym->set_parent(targetFunction->get_symbol_table()); targetFunction->get_symbol_table()->insert(end_of_inline_label->get_name(), end_of_inline_label_sym); // To ensure that there is some statement after the label SgExprStatement* dummyStatement = SageBuilder::buildExprStatement(SageBuilder::buildNullExpression()); dummyStatement->set_endOfConstruct(SgNULL_FILE); funbody_copy->append_statement(dummyStatement); dummyStatement->set_parent(funbody_copy); #if 0 SgPragma* pragmaEnd = new SgPragma("end_of_inline_function", SgNULL_FILE); SgPragmaDeclaration* pragmaEndDecl = new SgPragmaDeclaration(SgNULL_FILE, pragmaEnd); pragmaEndDecl->set_endOfConstruct(SgNULL_FILE); pragmaEnd->set_parent(pragmaEndDecl); pragmaEndDecl->set_definingDeclaration(pragmaEndDecl); funbody_copy->append_statement(pragmaEndDecl); pragmaEndDecl->set_parent(funbody_copy); #endif ChangeReturnsToGotosPrevisitor previsitor = ChangeReturnsToGotosPrevisitor(end_of_inline_label, funbody_copy); replaceExpressionWithStatement(funcall, &previsitor); // Make sure the AST is consistent. To save time, we'll just fix things that we know can go wrong. For instance, the // SgAsmExpression.p_lvalue data member is required to be true for certain operators and is set to false in other // situations. Since we've introduced new expressions into the AST we need to adjust their p_lvalue according to the // operators where they were inserted. markLhsValues(targetFunction); #ifdef NDEBUG AstTests::runAllTests(SageInterface::getProject()); #endif #if 0 // DQ (4/6/2015): Adding code to check for consitancy of checking the isTransformed flag. ROSE_ASSERT(funcall != NULL); ROSE_ASSERT(funcall->get_parent() != NULL); ROSE_ASSERT(globalScope != NULL); // checkTransformedFlagsVisitor(funcall->get_parent()); checkTransformedFlagsVisitor(globalScope); #endif // DQ (4/7/2015): This fixes something I was required to fix over the weekend and which is fixed more directly, I think. // Mark the things we insert as being transformations so they get inserted into the output by backend() markAsTransformation(funbody_copy); return true; }
// Main inliner code. Accepts a function call as a parameter, and inlines // only that single function call. Returns true if it succeeded, and false // otherwise. The function call must be to a named function, static member // function, or non-virtual non-static member function, and the function // must be known (not through a function pointer or member function // pointer). Also, the body of the function must already be visible. // Recursive procedures are handled properly (when allowRecursion is set), by // inlining one copy of the procedure into itself. Any other restrictions on // what can be inlined are bugs in the inliner code. bool doInline(SgFunctionCallExp* funcall, bool allowRecursion) { SgExpression* funname = funcall->get_function(); SgExpression* funname2 = isSgFunctionRefExp(funname); SgDotExp* dotexp = isSgDotExp(funname); SgArrowExp* arrowexp = isSgArrowExp(funname); SgExpression* thisptr = 0; if (dotexp || arrowexp) { funname2 = isSgBinaryOp(funname)->get_rhs_operand(); if (dotexp) { SgExpression* lhs = dotexp->get_lhs_operand(); // FIXME -- patch this into p_lvalue bool is_lvalue = lhs->get_lvalue(); if (isSgInitializer(lhs)) is_lvalue = false; if (!is_lvalue) { SgAssignInitializer* ai = SageInterface::splitExpression(lhs); ROSE_ASSERT (isSgInitializer(ai->get_operand())); SgInitializedName* in = isSgInitializedName(ai->get_parent()); ROSE_ASSERT (in); removeRedundantCopyInConstruction(in); lhs = dotexp->get_lhs_operand(); // Should be a var ref now } thisptr = new SgAddressOfOp(SgNULL_FILE, lhs); } else if (arrowexp) { thisptr = arrowexp->get_lhs_operand(); } else { assert (false); } } if (!funname2) { // std::cout << "Inline failed: not a call to a named function" << std::endl; return false; // Probably a call through a fun ptr } SgFunctionSymbol* funsym = 0; if (isSgFunctionRefExp(funname2)) funsym = isSgFunctionRefExp(funname2)->get_symbol(); else if (isSgMemberFunctionRefExp(funname2)) funsym = isSgMemberFunctionRefExp(funname2)->get_symbol(); else assert (false); assert (funsym); if (isSgMemberFunctionSymbol(funsym) && isSgMemberFunctionSymbol(funsym)->get_declaration()->get_functionModifier().isVirtual()) { // std::cout << "Inline failed: cannot inline virtual member functions" << std::endl; return false; } SgFunctionDeclaration* fundecl = funsym->get_declaration(); SgFunctionDefinition* fundef = fundecl->get_definition(); if (!fundef) { // std::cout << "Inline failed: no definition is visible" << std::endl; return false; // No definition of the function is visible } if (!allowRecursion) { SgNode* my_fundef = funcall; while (my_fundef && !isSgFunctionDefinition(my_fundef)) { // printf ("Before reset: my_fundef = %p = %s \n",my_fundef,my_fundef->class_name().c_str()); my_fundef = my_fundef->get_parent(); ROSE_ASSERT(my_fundef != NULL); // printf ("After reset: my_fundef = %p = %s \n",my_fundef,my_fundef->class_name().c_str()); } // printf ("After reset: my_fundef = %p = %s \n",my_fundef,my_fundef->class_name().c_str()); assert (isSgFunctionDefinition(my_fundef)); if (isSgFunctionDefinition(my_fundef) == fundef) { std::cout << "Inline failed: trying to inline a procedure into itself" << std::endl; return false; } } SgVariableDeclaration* thisdecl = 0; SgName thisname("this__"); thisname << ++gensym_counter; SgInitializedName* thisinitname = 0; if (isSgMemberFunctionSymbol(funsym) && !fundecl->get_declarationModifier().get_storageModifier().isStatic()) { assert (thisptr != NULL); SgType* thisptrtype = thisptr->get_type(); const SgSpecialFunctionModifier& specialMod = funsym->get_declaration()->get_specialFunctionModifier(); if (specialMod.isConstructor()) { SgFunctionType* ft = funsym->get_declaration()->get_type(); ROSE_ASSERT (ft); SgMemberFunctionType* mft = isSgMemberFunctionType(ft); ROSE_ASSERT (mft); SgType* ct = mft->get_class_type(); thisptrtype = new SgPointerType(ct); } SgConstVolatileModifier& thiscv = fundecl->get_declarationModifier().get_typeModifier().get_constVolatileModifier(); // if (thiscv.isConst() || thiscv.isVolatile()) { FIXME thisptrtype = new SgModifierType(thisptrtype); isSgModifierType(thisptrtype)->get_typeModifier().get_constVolatileModifier() = thiscv; // } // cout << thisptrtype->unparseToString() << " --- " << thiscv.isConst() << " " << thiscv.isVolatile() << endl; SgAssignInitializer* assignInitializer = new SgAssignInitializer(SgNULL_FILE, thisptr); assignInitializer->set_endOfConstruct(SgNULL_FILE); // thisdecl = new SgVariableDeclaration(SgNULL_FILE, thisname, thisptrtype, new SgAssignInitializer(SgNULL_FILE, thisptr)); thisdecl = new SgVariableDeclaration(SgNULL_FILE, thisname, thisptrtype, assignInitializer); thisdecl->set_endOfConstruct(SgNULL_FILE); thisdecl->get_definition()->set_endOfConstruct(SgNULL_FILE); thisdecl->set_definingDeclaration(thisdecl); thisinitname = (thisdecl->get_variables()).back(); //thisinitname = lastElementOfContainer(thisdecl->get_variables()); // thisinitname->set_endOfConstruct(SgNULL_FILE); assignInitializer->set_parent(thisinitname); // printf ("Built new SgVariableDeclaration #1 = %p \n",thisdecl); // DQ (6/23/2006): New test ROSE_ASSERT(assignInitializer->get_parent() != NULL); } std::cout << "Trying to inline function " << fundecl->get_name().str() << std::endl; SgBasicBlock* funbody_raw = fundef->get_body(); SgInitializedNamePtrList& params = fundecl->get_args(); SgInitializedNamePtrList::iterator i; SgExpressionPtrList& funargs = funcall->get_args()->get_expressions(); SgExpressionPtrList::iterator j; //int ctr; // unused variable, Liao std::vector<SgInitializedName*> inits; SgTreeCopy tc; SgFunctionDefinition* function_copy = isSgFunctionDefinition(fundef->copy(tc)); ROSE_ASSERT (function_copy); SgBasicBlock* funbody_copy = function_copy->get_body(); SgFunctionDefinition* targetFunction = PRE::getFunctionDefinition(funcall); renameLabels(funbody_copy, targetFunction); std::cout << "Original symbol count: " << funbody_raw->get_symbol_table()->size() << std::endl; std::cout << "Copied symbol count: " << funbody_copy->get_symbol_table()->size() << std::endl; // std::cout << "Original symbol count f: " << fundef->get_symbol_table()->size() << std::endl; // std::cout << "Copied symbol count f: " << function_copy->get_symbol_table()->size() << std::endl; // We don't need to keep the copied function definition now that the // labels in it have been moved to the target function. Having it in the // memory pool confuses the AST tests. function_copy->set_declaration(NULL); function_copy->set_body(NULL); delete function_copy; function_copy = NULL; #if 0 SgPragma* pragmaBegin = new SgPragma("start_of_inline_function", SgNULL_FILE); SgPragmaDeclaration* pragmaBeginDecl = new SgPragmaDeclaration(SgNULL_FILE, pragmaBegin); pragmaBeginDecl->set_endOfConstruct(SgNULL_FILE); pragmaBegin->set_parent(pragmaBeginDecl); pragmaBeginDecl->set_definingDeclaration(pragmaBeginDecl); funbody_copy->prepend_statement(pragmaBeginDecl); pragmaBeginDecl->set_parent(funbody_copy); #endif ReplaceParameterUseVisitor::paramMapType paramMap; for (i = params.begin(), j = funargs.begin(); i != params.end() && j != funargs.end(); ++i, ++j) { SgAssignInitializer* ai = new SgAssignInitializer(SgNULL_FILE, *j, (*i)->get_type()); ROSE_ASSERT(ai != NULL); ai->set_endOfConstruct(SgNULL_FILE); SgName shadow_name((*i)->get_name()); shadow_name << "__" << ++gensym_counter; SgVariableDeclaration* vardecl = new SgVariableDeclaration(SgNULL_FILE,shadow_name,(*i)->get_type(),ai); vardecl->set_definingDeclaration(vardecl); vardecl->set_endOfConstruct(SgNULL_FILE); vardecl->get_definition()->set_endOfConstruct(SgNULL_FILE); printf ("Built new SgVariableDeclaration #2 = %p = %s initializer = %p \n",vardecl,shadow_name.str(),(*(vardecl->get_variables().begin()))->get_initializer()); vardecl->set_parent(funbody_copy); SgInitializedName* init = (vardecl->get_variables()).back(); // init->set_endOfConstruct(SgNULL_FILE); inits.push_back(init); ai->set_parent(init); init->set_scope(funbody_copy); funbody_copy->get_statements().insert(funbody_copy->get_statements().begin() + (i - params.begin()), vardecl); SgVariableSymbol* sym = new SgVariableSymbol(init); paramMap[*i] = sym; funbody_copy->insert_symbol(shadow_name, sym); sym->set_parent(funbody_copy->get_symbol_table()); } if (thisdecl) { thisdecl->set_parent(funbody_copy); thisinitname->set_scope(funbody_copy); funbody_copy->get_statements().insert(funbody_copy->get_statements().begin(), thisdecl); SgVariableSymbol* thisSym = new SgVariableSymbol(thisinitname); funbody_copy->insert_symbol(thisname, thisSym); thisSym->set_parent(funbody_copy->get_symbol_table()); ReplaceThisWithRefVisitor(thisSym).traverse(funbody_copy, postorder); } ReplaceParameterUseVisitor(paramMap).traverse(funbody_copy, postorder); SgName end_of_inline_name = "rose_inline_end__"; end_of_inline_name << ++gensym_counter; SgLabelStatement* end_of_inline_label = new SgLabelStatement(SgNULL_FILE, end_of_inline_name); end_of_inline_label->set_endOfConstruct(SgNULL_FILE); #if 0 printf ("\n\nCalling AST copy mechanism on a SgBasicBlock \n"); // Need to set the parent of funbody_copy to avoid error. funbody_copy->set_parent(funbody_raw->get_parent()); printf ("This is a copy of funbody_raw = %p to build funbody_copy = %p \n",funbody_raw,funbody_copy); printf ("funbody_raw->get_statements().size() = %zu \n",funbody_raw->get_statements().size()); printf ("funbody_copy->get_statements().size() = %zu \n",funbody_copy->get_statements().size()); printf ("funbody_raw->get_symbol_table()->size() = %d \n",(int)funbody_raw->get_symbol_table()->size()); printf ("funbody_copy->get_symbol_table()->size() = %d \n",(int)funbody_copy->get_symbol_table()->size()); printf ("Output the symbol table for funbody_raw \n"); funbody_raw->get_symbol_table()->print("debugging copy problem"); // printf ("Output the symbol table for funbody_copy \n"); // funbody_copy->get_symbol_table()->print("debugging copy problem"); SgProject* project_copy = TransformationSupport::getProject(funbody_raw); ROSE_ASSERT(project_copy != NULL); const int MAX_NUMBER_OF_IR_NODES_TO_GRAPH_FOR_WHOLE_GRAPH = 4000; generateAstGraph(project_copy,MAX_NUMBER_OF_IR_NODES_TO_GRAPH_FOR_WHOLE_GRAPH); #endif // printf ("Exiting as a test after testing the symbol table \n"); // ROSE_ASSERT(false); funbody_copy->append_statement(end_of_inline_label); end_of_inline_label->set_scope(targetFunction); SgLabelSymbol* end_of_inline_label_sym = new SgLabelSymbol(end_of_inline_label); end_of_inline_label_sym->set_parent(targetFunction->get_symbol_table()); targetFunction->get_symbol_table()->insert(end_of_inline_label->get_name(), end_of_inline_label_sym); // To ensure that there is some statement after the label SgExprStatement* dummyStatement = SageBuilder::buildExprStatement(SageBuilder::buildNullExpression()); dummyStatement->set_endOfConstruct(SgNULL_FILE); funbody_copy->append_statement(dummyStatement); dummyStatement->set_parent(funbody_copy); #if 0 SgPragma* pragmaEnd = new SgPragma("end_of_inline_function", SgNULL_FILE); SgPragmaDeclaration* pragmaEndDecl = new SgPragmaDeclaration(SgNULL_FILE, pragmaEnd); pragmaEndDecl->set_endOfConstruct(SgNULL_FILE); pragmaEnd->set_parent(pragmaEndDecl); pragmaEndDecl->set_definingDeclaration(pragmaEndDecl); funbody_copy->append_statement(pragmaEndDecl); pragmaEndDecl->set_parent(funbody_copy); #endif // std::cout << "funbody_copy is " << funbody_copy->unparseToString() << std::endl; ChangeReturnsToGotosPrevisitor previsitor = ChangeReturnsToGotosPrevisitor(end_of_inline_label, funbody_copy); // std::cout << "funbody_copy 2 is " << funbody_copy->unparseToString() << std::endl; replaceExpressionWithStatement(funcall, &previsitor); // std::cout << "Inline succeeded " << funcall->get_parent()->unparseToString() << std::endl; return true; }
// 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 } } } }