SgFunctionDeclaration *CudaOutliner::createFuncSkeleton (const string& name, SgType* ret_type, SgFunctionParameterList* params, SgScopeStatement* scope) { ROSE_ASSERT(scope != NULL); ROSE_ASSERT(isSgGlobal(scope)!=NULL); SgFunctionDeclaration* func; SgProcedureHeaderStatement* fortranRoutine; if (SageInterface::is_Fortran_language()) { fortranRoutine = SageBuilder::buildProcedureHeaderStatement(name.c_str(),ret_type, params, SgProcedureHeaderStatement::e_subroutine_subprogram_kind,scope); func = isSgFunctionDeclaration(fortranRoutine); } else { func = SageBuilder::buildDefiningFunctionDeclaration(name,ret_type,params,scope); } ROSE_ASSERT (func != NULL); SgFunctionSymbol* func_symbol = scope->lookup_function_symbol(func->get_name()); ROSE_ASSERT(func_symbol != NULL); if (0)//Outliner::enable_debug) { printf("Found function symbol in %p for function:%s\n",scope,func->get_name().getString().c_str()); } return func; }
void SecureFunctionTypeTraversal::visit(SgNode* sgn) { if(isSgFunctionCallExp(sgn)) { SgFunctionDeclaration* fndecl = isSgFunctionCallExp(sgn)->getAssociatedFunctionDeclaration(); string filename = fndecl->get_file_info()->get_filename(); if(filename != "compilerGenerated") { StringUtility::FileNameClassification classification; classification = StringUtility::classifyFileName(filename, this->sourcedir, this->trustedlibs); //StringUtility::FileNameLocation filetypeclassification = classification.getLocation(); //cout << sgn->unparseToString() << filename << " : " << classification.getLocation() << ", " << classification.getLibrary() << endl; bool isSecure; if(untrustedFunctions.find(fndecl->get_name().getString()) != untrustedFunctions.end()) { isSecure = false; } else if(classification.isLibraryCode() || classification.isUserCode()) { isSecure = true; } else { isSecure = false; } AstAttribute* attr = dynamic_cast<AstAttribute*> ( new SecureFunctionType(isSecure) ); sgn->setAttribute("SECURE_TYPE", attr); } } }
NameQuerySynthesizedAttributeType NameQuery::queryNameFunctionDeclarationNames (SgNode * astNode) { ROSE_ASSERT (astNode != 0); NameQuerySynthesizedAttributeType returnNameList; SgFunctionDeclaration *sageFunctionDeclaration = isSgFunctionDeclaration (astNode); if (sageFunctionDeclaration != NULL) { string name = sageFunctionDeclaration->get_name ().str (); #if DEBUG_NAMEQUERY printf ("In case: CLASS_DECL_STMT name = %s \n", name.c_str ()); #endif returnNameList.push_back (name); } return returnNameList; } /* End function queryNameFunctionDeclarationNames() */
string Doxygen::getDeclStmtName(SgDeclarationStatement *st) { SgFunctionDeclaration *fn = isSgFunctionDeclaration(st); SgVariableDeclaration *vn = isSgVariableDeclaration(st); SgClassDeclaration *cn = isSgClassDeclaration(st); if (fn) { return fn->get_name().str(); } else if (vn) { /* XXX The following is a bit dodgy since single * SgVariableDeclaration may declare multiple * variables. But doxygen doesn't handle this case * properly. A useful transform may split up the * SgVariableDeclaration for doxygen's sake */ return (*(vn->get_variables().begin()))->get_name().str(); } else if (cn) { return cn->get_name().str(); } else { fprintf(stderr, "Cannot handle this case: %s\n", st->sage_class_name()); abort(); } }
int main(int argc, char *argv[]) { std::string filename; SgProject *project = frontend(argc, argv); EDefUse *edu=new EDefUse(project); if (edu->run(false)==1) { std::cerr<<"createFDG:: DFAnalysis failed! -- edu->run(false)==0"<<endl; exit(0); } std::vector<InterproceduralInfo*> ip; list < SgNode * >functionDeclarations = NodeQuery::querySubTree(project, V_SgFunctionDeclaration); for (list < SgNode * >::iterator i = functionDeclarations.begin(); i != functionDeclarations.end(); i++) { ControlDependenceGraph *cdg; DataDependenceGraph *ddg; InterproceduralInfo *ipi; SgFunctionDeclaration *fD = isSgFunctionDeclaration(*i); // SGFunctionDefinition * fDef; ROSE_ASSERT(fD != NULL); // CI (01/08/2007): A missing function definition is an indicator to a // // // librarycall. // * An other possibility would be a programmer-mistake, which we // don't treat at this point. // I assume librarycall if (fD->get_definition() == NULL) { } else { // get the control depenence for this function ipi=new InterproceduralInfo(fD); ROSE_ASSERT(ipi != NULL); ddg = new DataDependenceGraph(fD->get_definition(),edu); // get control dependence for this function defintion cdg = new ControlDependenceGraph(fD->get_definition(), ipi); cdg->computeAdditionalFunctioncallDepencencies(); cdg->computeInterproceduralInformation(ipi); // cdg->debugCoutNodeList(); FunctionDependenceGraph *fdg=new FunctionDependenceGraph(cdg,ddg,ipi); filename = (fD->get_definition()->get_file_info()->get_filenameString ()) + "." + (fD->get_name().getString()) + ".fdg.dot"; fdg->writeDot((char *)filename.c_str()); } } }
static string chooseConstructor(SgProject* project) { static const char * const d_constructor_names[] = { "init", "initialize", "prepare", "ready", "outfit", NULL }; static FunctionNameSet functionNames; Rose_STL_Container<SgNode*> functionDeclarationList = NodeQuery::querySubTree(project, V_SgFunctionDeclaration); for(Rose_STL_Container<SgNode*>::iterator i = functionDeclarationList.begin(); i != functionDeclarationList.end(); ++i) { SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(*i); ROSE_ASSERT(functionDeclaration != NULL); functionNames.insert(functionDeclaration->get_name().str()); } FunctionNameSet::iterator notFound = functionNames.end(); for(const char * const *j = d_constructor_names; *j ; ++j) { string candidate = *j; if (functionNames.find(candidate) == notFound) return candidate; } return ""; }
void RtedTransformation::insertVariableCreateInitForParams( SgFunctionDefinition& fndef) { SgBasicBlock* body = fndef.get_body(); ROSE_ASSERT( body); SgInitializedNamePtrList names = fndef.get_declaration()->get_parameterList()->get_args(); BOOST_FOREACH( SgInitializedName* param, names) { SgType* initType = param->get_type(); // nov2010 code: // reference variables don't allocate new memory // if we call createVariable the RTS will think it's a double // allocation fault // \pp we skip array types because they will be handled elsewhere // \todo not sure if this is correct here, b/c arrays would decay // to pointers anyway. However, this decay is not represented // in the nov2010 code, thus we skip these initializations // here. if ( isSgReferenceType(initType) || isSgArrayType(skip_ModifierType(initType)) ) continue; SgFunctionDeclaration* fndecl = fndef.get_declaration(); std::cerr << ">>> " << fndecl->get_name() << std::endl; ROSE_ASSERT(isSgFunctionDefinition(param->get_scope())); body->prepend_statement( buildVariableCreateCallStmt(param, true) ); }
int main(int argc, char *argv[]) { std::string filename; SgProject *project = frontend(argc, argv); std::vector<InterproceduralInfo*> ip; // list < SgNode * >functionDeclarations = NodeQuery::querySubTree(project, V_SgFunctionDeclaration); NodeQuerySynthesizedAttributeType functionDeclarations = NodeQuery::querySubTree(project, V_SgFunctionDeclaration); // for (list < SgNode * >::iterator i = functionDeclarations.begin(); i != functionDeclarations.end(); i++) for (NodeQuerySynthesizedAttributeType::iterator i = functionDeclarations.begin(); i != functionDeclarations.end(); i++) { ControlDependenceGraph *cdg; InterproceduralInfo *ipi; SgFunctionDeclaration *fD = isSgFunctionDeclaration(*i); // SGFunctionDefinition * fDef; ROSE_ASSERT(fD != NULL); // CI (01/08/2007): A missing function definition is an indicator to a // // // librarycall. // * An other possibility would be a programmer-mistake, which we // don't treat at this point. // I assume librarycall if (fD->get_definition() == NULL) { } else { // get the control depenence for this function ipi=new InterproceduralInfo(fD); ROSE_ASSERT(ipi != NULL); // get control dependence for this function defintion cdg = new ControlDependenceGraph(fD->get_definition(), ipi); cdg->computeAdditionalFunctioncallDepencencies(); // cdg->computeInterproceduralInformation(ipi); // cdg->debugCoutNodeList(); // Liao, Feb. 7/2008, //strip off absolute path to avoid polluting the source tree with generated .dot files filename = StringUtility::stripPathFromFileName((fD->get_definition()->get_file_info()->get_filenameString ())) + "." + (fD->get_name().getString()) + ".cdg.dot"; cdg->writeDot((char *)filename.c_str()); } } }
void Traversal::processNode(SgNode* n, SynthesizedAttribute& synthesizedAttribute ) { // Look for names of functions SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(n); if (functionDeclaration != NULL) { string name = functionDeclaration->get_name().str(); #if DEBUG > 3 SgFunctionDefinition* functionDefinition = functionDeclaration->get_definition(); if (functionDefinition != NULL) printf ("SgFunctionDefinition: %s \n",name.c_str()); else printf ("SgFunctionDeclaration: %s \n",name.c_str()); #endif synthesizedAttribute.nameList.push_back( NameStructureType(name,n)); // nameSet.insert(name); } SgInitializedName* initializedName = isSgInitializedName(n); if (initializedName != NULL) { string name = initializedName->get_name().str(); #if DEBUG > 3 printf ("SgInitializedName: %s \n",name.c_str()); #endif synthesizedAttribute.nameList.push_back( NameStructureType(name,n)); // nameSet.insert(name); } SgNamespaceDeclarationStatement* namespaceDeclaration = isSgNamespaceDeclarationStatement(n); if (namespaceDeclaration != NULL) { string name = namespaceDeclaration->get_name().str(); #if DEBUG > 3 printf ("SgNamespaceDeclaration: %s \n",name.c_str()); #endif synthesizedAttribute.nameList.push_back( NameStructureType(name,n)); // nameSet.insert(name); } }
void PreAndPostOrderTraversal::preOrderVisit(SgNode* n) { SgFunctionDeclaration * dec = isSgFunctionDeclaration(n); if (dec != NULL) { cout << "Found function declaration " << dec->get_name().getString(); Sg_File_Info * start = dec->get_startOfConstruct(); Sg_File_Info * end = dec->get_endOfConstruct(); if(start->isCompilerGenerated()) { cout << ", which is compiler-generated" << endl; } else { cout << " in file " << start->get_raw_filename() << ", " << start->get_file_id() << " from line " << start->get_line() << ", col " << start->get_col() << " to line " << end->get_line() << ", col " << end->get_col() << endl; } SgFunctionType * type = dec->get_type(); SgType * retType = type->get_return_type(); cout << "Return type: " << retType->unparseToString() << endl; SgFunctionParameterList * params = dec->get_parameterList(); SgInitializedNamePtrList & ptrList = params->get_args(); if(!ptrList.empty()) { cout << "Parameter types: "; for(SgInitializedNamePtrList::iterator j = ptrList.begin(); j != ptrList.end(); j++) { SgType * pType = (*j)->get_type(); cout << pType->unparseToString() << " "; } cout << endl; } cout << "Linkage: " << dec->get_linkage() << endl; cout << endl; } SgFunctionDefinition * def = isSgFunctionDefinition(n); if (def != NULL) { cout << "Found function definition " << def->get_declaration()->get_name().getString(); Sg_File_Info * start = def->get_startOfConstruct(); Sg_File_Info * end = def->get_endOfConstruct(); if(start->isCompilerGenerated()) { cout << ", which is compiler-generated" << endl; } else { cout << " in file " << start->get_raw_filename() << " from line " << start->get_line() << ", col " << start->get_col() << " to line " << end->get_line() << ", col " << end->get_col() << endl; SgBasicBlock * body = def->get_body(); Sg_File_Info * bodyStart = body->get_startOfConstruct(); Sg_File_Info * bodyEnd = body->get_endOfConstruct(); cout << "Function body from line " << bodyStart->get_line() << ", col " << bodyStart->get_col() << " to line " << bodyEnd->get_line() << ", col " << bodyEnd->get_col() << endl; } cout << endl; } }
int main( int argc, char * argv[] ) { // Build the AST used by ROSE SgProject* project = frontend(argc,argv); ROSE_ASSERT(project != NULL); // Build a list of functions within the AST Rose_STL_Container<SgNode*> functionDeclarationList = NodeQuery::querySubTree (project,V_SgFunctionDeclaration); int counter = 0; for (Rose_STL_Container<SgNode*>::iterator i = functionDeclarationList.begin(); i != functionDeclarationList.end(); i++) { // Build a pointer to the current type so that we can call the get_name() member function. SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(*i); ROSE_ASSERT(functionDeclaration != NULL); // DQ (3/5/2006): Only output the non-compiler generated IR nodes if ( (*i)->get_file_info()->isCompilerGenerated() == false) { // output the function number and the name of the function printf ("Function #%2d name is %s at line %d \n", counter++,functionDeclaration->get_name().str(), functionDeclaration->get_file_info()->get_line()); } else { // Output something about the compiler-generated builtin functions printf ("Compiler-generated (builtin) function #%2d name is %s \n", counter++,functionDeclaration->get_name().str()); } } // Note: Show composition of AST queries return 0; }
foreach (SgFunctionCallExp *nfce, callExprs) { SgFunctionDeclaration *CFD = nfce->getAssociatedFunctionDeclaration(); std::string fname = CFD->get_name().getString(); size_t pos = 0; if (((pos = fname.find("RecvReturnPause_")) != std::string::npos) || ((pos = fname.find("WriteMemPause")) != std::string::npos && lastStmt != nfce->get_parent()) || ((pos = fname.find("SendReturn_")) != std::string::npos && lastStmt != nfce->get_parent()) && pos == 0) { SgStatement *brkStmt = SageBuilder::buildBreakStmt(); SgStatement *parent = isSgStatement(nfce->get_parent()); SageInterface::insertStatementAfter(parent, brkStmt); } }
// Function printFunctionDeclarationList will print all function names in the list void printFunctionDeclarationList(Rose_STL_Container<SgNode*> functionDeclarationList) { int counter = 0; for (Rose_STL_Container<SgNode*>::iterator i = functionDeclarationList.begin(); i != functionDeclarationList.end(); i++) { // Build a pointer to the current type so that we can call the get_name() member function. SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(*i); ROSE_ASSERT(functionDeclaration != NULL); // output the function number and the name of the function printf ("function name #%d is %s at line %d \n", counter++,functionDeclaration->get_name().str(), functionDeclaration->get_file_info()->get_line()); } }
void findCandidateFunctionDefinitions (SgProject* project, std::vector<SgFunctionDefinition* >& candidateFuncDefs) { ROSE_ASSERT (project != NULL); // For each source file in the project SgFilePtrList & ptr_list = project->get_fileList(); for (SgFilePtrList::iterator iter = ptr_list.begin(); iter!=ptr_list.end(); iter++) { SgFile* sageFile = (*iter); SgSourceFile * sfile = isSgSourceFile(sageFile); ROSE_ASSERT(sfile); // SgGlobal *root = sfile->get_globalScope(); if (enable_debug) cout<<"Processing each function within the files "<< sfile->get_file_info()->get_filename() <<endl; // cout<<"\t loop at:"<< cur_loop->get_file_info()->get_line() <<endl; // This is wrong, many functions in question are not top level declarations!! //SgDeclarationStatementPtrList& declList = root->get_declarations (); //VariantVector vv; Rose_STL_Container<SgNode*> defList = NodeQuery::querySubTree(sfile, V_SgFunctionDefinition); // bool hasOpenMP= false; // flag to indicate if omp.h is needed in this file //For each function body in the scope //for (SgDeclarationStatementPtrList::iterator p = declList.begin(); p != declList.end(); ++p) for (Rose_STL_Container<SgNode*>::iterator p = defList.begin(); p != defList.end(); ++p) { SgFunctionDefinition *defn = isSgFunctionDefinition(*p); ROSE_ASSERT (defn != NULL); SgFunctionDeclaration *func = defn->get_declaration(); ROSE_ASSERT (func != NULL); if (enable_debug) cout<<"\t considering function "<< func->get_name() << " at "<< func->get_file_info()->get_line()<<endl; //ignore functions in system headers, Can keep them to test robustness if (defn->get_file_info()->get_filename()!=sageFile->get_file_info()->get_filename()) { if (enable_debug) cout<<"\t Skipped since the function's associated file name does not match current file being considered. Mostly from a header. "<<endl; continue; } candidateFuncDefs.push_back(defn); } // end for def list } // end for file list }
// Function querySolverAccessFunctions() // find access functions (function name starts with "get_" or "set_") NodeQuerySynthesizedAttributeType querySolverAccessFunctions (SgNode * astNode) { ROSE_ASSERT (astNode != 0); NodeQuerySynthesizedAttributeType returnNodeList; SgFunctionDeclaration* funcDecl = isSgFunctionDeclaration(astNode); if (funcDecl != NULL) { string functionName = funcDecl->get_name().str(); if ( (functionName.length() >= 4) && ((functionName.substr(0,4) == "get_") || (functionName.substr(0,4) == "set_")) ) returnNodeList.push_back (astNode); } return returnNodeList; }
bool isHtThreadControlStmt(SgStatement *S) { SgExprStatement *es = isSgExprStatement(S); SgFunctionCallExp *fce = 0; if (es && (fce = isSgFunctionCallExp(es->get_expression()))) { SgFunctionDeclaration *calleeFD = fce->getAssociatedFunctionDeclaration(); std::string fname = calleeFD->get_name().getString(); size_t pos = 0; if (fname == "WriteMemPause" || fname == "ReadMemPause" || fname == "HtBarrier" || (((pos = fname.find("SendCall_")) != std::string::npos /* || (pos = fname.find("SendCallFork_")) != std::string::npos */ || (pos = fname.find("SendReturn_")) != std::string::npos || (pos = fname.find("RecvReturnJoin_")) != std::string::npos) && pos == 0)) { return true; } } return false; }
void visitorTraversal::visit(SgNode* n) { SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(n); if (functionDeclaration != NULL) { SgFunctionDefinition* functionDefinition = functionDeclaration->get_definition(); if (functionDefinition != NULL) { SgBasicBlock* functionBody = functionDefinition->get_body(); ROSE_ASSERT(functionBody != NULL); ControlFlowGraph controlflow; // The CFG can only be called on a function definition (at present) makeCfg(functionDefinition,controlflow); string fileName = functionDeclaration->get_name().str(); fileName += ".dot"; ofstream dotfile(fileName.c_str()); printCfgAsDot(dotfile, controlflow); } } }
void SimpleInstrumentation::visit ( SgNode* astNode ) { // Demonstrate and test append mechanism for statements // printf ("In assemblyFunction(): astNode->sage_class_name() = %s \n",astNode->sage_class_name()); if (isSgFunctionDeclaration(astNode) != NULL) { // printf ("Found a function declaration \n"); SgFunctionDeclaration* functionDeclarationStatement = isSgFunctionDeclaration(astNode); SgName sageName = functionDeclarationStatement->get_name(); string functionNameString = sageName.str(); // Make sure this is the "main" function before we insert new code if (functionNameString == "main") { string globalDeclarations = "int k;"; string functionSource = ""; string localDeclarations = "\ void myTimerFunctionStart(void) \n\ { \n\ int xyzVariable; \n\ } \n\n\
int main(int argc, char * argv[]) { // Build the AST used by ROSE project = frontend(argc,argv); /*convertToOMPNormalForm(project, project); // Run internal consistancy tests on AST AstTests::runAllTests(project); Rose_STL_Container<SgNode*> functions = NodeQuery::querySubTree(project, V_SgFunctionDefinition); for (Rose_STL_Container<SgNode*>::const_iterator i = functions.begin(); i != functions.end(); ++i) { SgFunctionDefinition* func = isSgFunctionDefinition(*i); ROSE_ASSERT(func); printf("func = %s\n", func->unparseToString().c_str()); // output the CFG to a file ofstream fileCFG; fileCFG.open((func->get_declaration()->get_name().getString()+"_cfg.dot").c_str()); cout << " writing to file "<<(func->get_declaration()->get_name().getString()+"_cfg.dot")<<"\n"; cfgToDot(fileCFG, func->get_declaration()->get_name(), func->cfgForBeginning()); fileCFG.close(); } backend(project);*/ //generatePDF ( *project ); // find a declaration for foo() Rose_STL_Container<SgNode*> funcDecls = NodeQuery::querySubTree(project, V_SgFunctionDeclaration); for(Rose_STL_Container<SgNode*>::iterator it = funcDecls.begin(); it!=funcDecls.end(); it++) { SgFunctionDeclaration* decl = isSgFunctionDeclaration(*it); ROSE_ASSERT(decl); if(decl->get_name().getString() == "foo") { fooDecl = decl; break; } } if(!fooDecl) { printf("ERROR: could not find declaration of function foo()!\n"); numFails++; } testParsing(); convertToOMPNormalForm(project, project); testOMPForSensitiveInsertion(); AstTests::runAllTests(project); insertTopBottomOmpDirectives(project, ompUtils::omp_critical, true, &fooCallStmtCreate); insertTopBottomOmpDirectives(project, ompUtils::omp_single, false, &fooCallStmtCreate); // Run internal consistancy tests on AST // // Generate the CFGs of all the functions to ensure that all CFG data is good Rose_STL_Container<SgNode*> functions = NodeQuery::querySubTree(project, V_SgFunctionDefinition); for (Rose_STL_Container<SgNode*>::const_iterator i = functions.begin(); i != functions.end(); ++i) { SgFunctionDefinition* func = isSgFunctionDefinition(*i); ROSE_ASSERT(func); printf("func = %s\n", func->unparseToString().c_str()); // output the CFG to a file ofstream fileCFG; fileCFG.open((func->get_declaration()->get_name().getString()+"_cfg.dot").c_str()); cout << " writing to file "<<(func->get_declaration()->get_name().getString()+"_cfg.dot")<<"\n"; cfgToDot(fileCFG, func->get_declaration()->get_name(), func->cfgForBeginning()); fileCFG.close(); } backend(project); system("diff rose_test_example.c test_example.valid_rose_output.c > selfTest.out"); struct stat file; stat("selfTest.out",&file); if(file.st_size!=0) { printf("Error: found differences between rose_test_example.c and the canonical test_example.valid_rose_output.c! Details in selfTest.out.\n"); numFails++; } if(numFails==0) cout << "PASSED\n"; else cout << "FAILED!\n"; }
int main( int argc, char * argv[] ) { // Build the AST used by ROSE SgProject* project = frontend(argc,argv); ROSE_ASSERT(project != NULL); // Build a list of functions within the AST and find all access functions // (function name starts with "get_" or "set_") // Build list using a query of the whole AST Rose_STL_Container<SgNode*> functionDefinitionList = NodeQuery::querySubTree (project,V_SgFunctionDefinition); // Build list using nested Queries (operating on return result of previous query) // Rose_STL_Container<SgNode*> accessFunctionsList; // accessFunctionsList = NodeQuery::queryNodeList (functionDeclarationList,&querySolverAccessFunctions); // printFunctionDeclarationList(accessFunctionsList); // Alternative form of same query building the list using a query of the whole AST // accessFunctionsList = NodeQuery::querySubTree (project,&querySolverAccessFunctions); // printFunctionDeclarationList(accessFunctionsList); int counter = 0; for (Rose_STL_Container<SgNode*>::iterator i = functionDefinitionList.begin(); i != functionDefinitionList.end(); i++) { SgFunctionDefinition* fnc = isSgFunctionDefinition(*i); stringstream ss; SgFunctionDeclaration* functionDeclaration = fnc->get_declaration(); string fileName= functionDeclaration->get_name().str();//StringUtility::stripPathFromFileName(mainDef->get_file_info()->get_filenameString()); string dotFileName1; ss << fileName << "." << counter << ".dot"; counter++; dotFileName1 = ss.str(); //SgFunctionDefinition* fnc = functionDeclaration->get_definition(); if (fnc != NULL) { StaticCFG::CFG* cfg = new StaticCFG::CFG(fnc); SgIncidenceDirectedGraph* g = new SgIncidenceDirectedGraph(); visitorTraversal* vis = new visitorTraversal(); g = cfg->getGraph(); myGraph* mg = new myGraph(); mg = instantiateGraph(g, (*cfg)); vis->tltnodes = 0; vis->paths = 0; std::cout << dotFileName1 << std::endl; cfgToDot(fnc,dotFileName1); //vis->firstPrepGraph(constcfg); //t1 = getCPUTime(); vis->constructPathAnalyzer(mg, true, 0, 0, true); //t2 = getCPUTim std::cout << "function: " << fileName << std::endl; std::cout << "paths: " << vis->paths << std::endl; delete vis; delete cfg; delete g; delete mg; //std::cout << "took: " << timeDifference(t2, t1) << std::endl; } } SgProject* proj = project; SgFunctionDeclaration* mainDefDecl = SageInterface::findMain(proj); if (mainDefDecl != NULL) { SgFunctionDefinition* mainDef = mainDefDecl->get_definition(); visitorTraversal* vis = new visitorTraversal(); StaticCFG::CFG cfg(mainDef); //cfg.buildFullCFG(); stringstream ss; string fileName= StringUtility::stripPathFromFileName(mainDef->get_file_info()->get_filenameString()); string dotFileName1=fileName+"."+ mainDef->get_declaration()->get_name() +".dot"; cfgToDot(mainDef,dotFileName1); //cfg->buildFullCFG(); SgIncidenceDirectedGraph* g = new SgIncidenceDirectedGraph(); g = cfg.getGraph(); myGraph* mg = new myGraph(); mg = instantiateGraph(g, cfg); vis->tltnodes = 0; vis->paths = 0; //vis->firstPrepGraph(constcfg); vis->constructPathAnalyzer(mg, true, 0, 0, true); //std::cout << "took: " << timeDifference(t2, t1) << std::endl; //cfg.clearNodesAndEdges(); std::cout << "finished" << std::endl; std::cout << "tltnodes: " << vis->tltnodes << " paths: " << vis->paths << std::endl; //std::cout << "ipaths: " << ipaths << std::endl; delete vis; } // Another way to query for collections of IR nodes VariantVector vv1 = V_SgClassDefinition; std::cout << "Number of class definitions in the memory pool is: " << NodeQuery::queryMemoryPool(vv1).size() << std::endl; // Another way to query for collections of multiple IR nodes. // VariantVector(V_SgType) is internally expanded to all IR nodes derived from SgType. VariantVector vv2 = VariantVector(V_SgClassDefinition) + VariantVector(V_SgType); std::cout << "Number of class definitions AND types in the memory pool is: " << NodeQuery::queryMemoryPool(vv2).size() << std::endl; // Note: Show composition of AST queries return 0; }
DOTSynthesizedAttribute AstDOTGeneration::evaluateSynthesizedAttribute(SgNode* node, DOTInheritedAttribute ia, SubTreeSynthesizedAttributes l) { SubTreeSynthesizedAttributes::iterator iter; ROSE_ASSERT(node); // printf ("AstDOTGeneration::evaluateSynthesizedAttribute(): node = %s \n",node->class_name().c_str()); // DQ (5/3/2006): Skip this IR node if it is specified as such in the inherited attribute if (ia.skipSubTree == true) { // I am unclear if I should return NULL or node as a parameter to DOTSynthesizedAttribute // Figured this out: if we return a valid pointer then we get a node in the DOT graph // (with just the pointer value as a label), where as if we return a DOTSynthesizedAttribute // with a NUL pointer then the node will NOT appear in the DOT graph. // return DOTSynthesizedAttribute(node); return DOTSynthesizedAttribute(NULL); } string nodeoption; if(AstTests::isProblematic(node)) { // cout << "problematic node found." << endl; nodeoption="color=\"orange\" "; } string nodelabel=string("\\n")+node->class_name(); // DQ (1/24/2009): Added support for output of isForward flag in the dot graph. SgDeclarationStatement* genericDeclaration = isSgDeclarationStatement(node); if (genericDeclaration != NULL) { // At the moment the mnemonic name is stored, but it could be computed in the // future from the kind and the tostring() function. string name = (genericDeclaration->isForward() == true) ? "isForward" : "!isForward"; ROSE_ASSERT(name.empty() == false); // DQ (3/20/2011): Added class names to the generated dot file graphs of the AST. SgClassDeclaration* classDeclaration = isSgClassDeclaration(genericDeclaration); if (classDeclaration != NULL) { nodelabel += string("\\n") + classDeclaration->get_name(); } // DQ (3/20/2011): Added function names to the generated dot file graphs of the AST. SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(genericDeclaration); if (functionDeclaration != NULL) { nodelabel += string("\\n") + functionDeclaration->get_name(); } nodelabel += string("\\n") + name; } // DQ (4/6/2011): Added support for output of the name for SgInitializedName IR nodes. SgInitializedName* initializedName = isSgInitializedName(node); if (initializedName != NULL) { nodelabel += string("\\n") + initializedName->get_name(); } // DQ (4/6/2011): Added support for output of the name for SgInitializedName IR nodes. SgIntVal* intValue = isSgIntVal(node); if (intValue != NULL) { nodelabel += string("\\n value = ") + StringUtility::numberToString(intValue->get_value()); } // DQ (4/6/2011): Added support for output of the name for SgInitializedName IR nodes. SgVarRefExp* varRefExp = isSgVarRefExp(node); if (varRefExp != NULL) { SgVariableSymbol* variableSymbol = varRefExp->get_symbol(); ROSE_ASSERT(variableSymbol != NULL); string name = variableSymbol->get_name(); nodelabel += string("\\n name = ") + name; } // DQ (1/19/2009): Added support for output of what specific instrcution this is in the dot graph. SgAsmInstruction* genericInstruction = isSgAsmInstruction(node); if (genericInstruction != NULL) { #ifdef ROSE_BUILD_BINARY_ANALYSIS_SUPPORT // At the moment the mnemonic name is stored, but it could be computed in the // future from the kind and the tostring() function. #if 1 string unparsedInstruction = unparseInstruction(genericInstruction); string addressString = StringUtility::numberToString( (void*) genericInstruction->get_address() ); // string name = genericInstruction->get_mnemonic(); string name = unparsedInstruction + "\\n address: " + addressString; #else string name = unparsedInstruction + "\\n" + addressString; #endif ROSE_ASSERT(name.empty() == false); nodelabel += string("\\n") + name; #else printf ("Warning: In AstDOTGeneration.C ROSE_BUILD_BINARY_ANALYSIS_SUPPORT is not defined \n"); #endif } SgAsmExpression* genericExpression = isSgAsmExpression(node); if (genericExpression != NULL) { #ifdef ROSE_BUILD_BINARY_ANALYSIS_SUPPORT string name = unparseExpression(genericExpression, NULL, NULL); ROSE_ASSERT(name.empty() == false); nodelabel += string("\\n") + name; #else printf ("Warning: In AstDOTGeneration.C ROSE_BUILD_BINARY_ANALYSIS_SUPPORT is not defined \n"); #endif } // DQ (10/29/2008): Added some support for additional output of internal names for specific IR nodes. // In generall there are long list of these IR nodes in the binary and this helps make some sense of // the lists (sections, symbols, etc.). SgAsmExecutableFileFormat* binaryFileFormatNode = isSgAsmExecutableFileFormat(node); if (binaryFileFormatNode != NULL) { #ifdef ROSE_BUILD_BINARY_ANALYSIS_SUPPORT // The case of binary file format IR nodes can be especially confusing so we want the // default to output some more specific information for some IR nodes (e.g. sections). string name; SgAsmGenericSection* genericSection = isSgAsmGenericSection(node); if (genericSection != NULL) { SgAsmGenericString* genericString = genericSection->get_name(); ROSE_ASSERT(genericString != NULL); name = genericString->get_string(); } SgAsmGenericSymbol* genericSymbol = isSgAsmGenericSymbol(node); if (genericSymbol != NULL) { SgAsmGenericString* genericString = genericSymbol->get_name(); ROSE_ASSERT(genericString != NULL); name = genericString->get_string(); if (name.empty() == true) name = "no_name_for_symbol"; } SgAsmGenericDLL* genericDLL = isSgAsmGenericDLL(node); if (genericDLL != NULL) { SgAsmGenericString* genericString = genericDLL->get_name(); ROSE_ASSERT(genericString != NULL); name = genericString->get_string(); } SgAsmPEImportItem* peImportItem = isSgAsmPEImportItem(node); if (peImportItem != NULL) { SgAsmGenericString* genericString = peImportItem->get_name(); ROSE_ASSERT(genericString != NULL); name = genericString->get_string(); } SgAsmDwarfLine* asmDwarfLine = isSgAsmDwarfLine(node); if (asmDwarfLine != NULL) { char buffer[100]; // It does not work to embed the "\n" into the single sprintf parameter. // sprintf(buffer," Addr: 0x%08"PRIx64" \n line: %d col: %d ",asmDwarfLine->get_address(),asmDwarfLine->get_line(),asmDwarfLine->get_column()); sprintf(buffer,"Addr: 0x%08"PRIx64,asmDwarfLine->get_address()); name = buffer; sprintf(buffer,"line: %d col: %d",asmDwarfLine->get_line(),asmDwarfLine->get_column()); name += string("\\n") + buffer; } SgAsmDwarfConstruct* asmDwarfConstruct = isSgAsmDwarfConstruct(node); if (asmDwarfConstruct != NULL) { name = asmDwarfConstruct->get_name(); } #if 0 // This might not be the best way to implement this, since we want to detect common base classes of IR nodes. switch (node->variantT()) { case V_SgAsmElfSection: { SgAsmElfSection* n = isSgAsmElfSection(node); name = n->get_name(); break; } default: { // No additional information is suggested for the default case! } } #endif if (name.empty() == false) nodelabel += string("\\n") + name; #else printf ("Warning: In AstDOTGeneration.C ROSE_BUILD_BINARY_ANALYSIS_SUPPORT is not defined \n"); #endif } // DQ (11/29/2008): Output the directives in the label of the IR node. SgC_PreprocessorDirectiveStatement* preprocessorDirective = isSgC_PreprocessorDirectiveStatement(node); if (preprocessorDirective != NULL) { string s = preprocessorDirective->get_directiveString(); // Change any double quotes to single quotes so that DOT will not misunderstand the generated lables. while (s.find("\"") != string::npos) { s.replace(s.find("\""),1,"\'"); } if (s.empty() == false) nodelabel += string("\\n") + s; } nodelabel += additionalNodeInfo(node); // DQ (11/1/2003) added mechanism to add additional options (to add color, etc.) // nodeoption += additionalNodeOptions(node); string additionalOptions = additionalNodeOptions(node); // printf ("nodeoption = %s size() = %ld \n",nodeoption.c_str(),nodeoption.size()); // printf ("additionalOptions = %s size() = %ld \n",additionalOptions.c_str(),additionalOptions.size()); string x; string y; x += additionalOptions; nodeoption += additionalOptions; DOTSynthesizedAttribute d(0); // DQ (7/27/2008): Added mechanism to support pruning of AST bool commentoutNode = commentOutNodeInGraph(node); if (commentoutNode == true) { // DQ (11/10/2008): Fixed to only output message when (verbose_level > 0); command-line option. // DQ (7/27/2008): For now just return to test this mechanism, then we want to add comment "//" propoerly to generated DOT file. if (SgProject::get_verbose() > 0) { printf ("Skipping the use of this IR node in the DOT Graph \n"); } } else { // ************************** switch(traversal) { case TOPDOWNBOTTOMUP: dotrep.addNode(node,dotrep.traceFormat(ia.tdbuTracePos,tdbuTrace)+nodelabel,nodeoption); break; case PREORDER: case TOPDOWN: dotrep.addNode(node,dotrep.traceFormat(ia.tdTracePos)+nodelabel,nodeoption); break; case POSTORDER: case BOTTOMUP: dotrep.addNode(node,dotrep.traceFormat(buTrace)+nodelabel,nodeoption); break; default: assert(false); } ++tdbuTrace; ++buTrace; // add edges or null values int testnum=0; for (iter = l.begin(); iter != l.end(); iter++) { string edgelabel = string(node->get_traversalSuccessorNamesContainer()[testnum]); string toErasePrefix = "p_"; if (AstTests::isPrefix(toErasePrefix,edgelabel)) { edgelabel.erase(0, toErasePrefix.size()); } if ( iter->node == NULL) { // SgNode* snode=node->get_traversalSuccessorContainer()[testnum]; AstSuccessorsSelectors::SuccessorsContainer c; AstSuccessorsSelectors::selectDefaultSuccessors(node,c); SgNode* snode=c[testnum]; // isDefault shows that the default constructor for synth attribute was used if (l[testnum].isDefault() && snode && (visitedNodes.find(snode) != visitedNodes.end()) ) { // handle bugs in SAGE dotrep.addEdge(node,edgelabel,snode,"dir=forward arrowhead=\"odot\" color=red "); } else { if (snode == NULL) { dotrep.addNullValue(node,"",edgelabel,""); } } } else { // DQ (3/5/2007) added mechanism to add additional options (to add color, etc.) string edgeoption = additionalEdgeOptions(node,iter->node,edgelabel); switch(traversal) { case TOPDOWNBOTTOMUP: dotrep.addEdge(node,edgelabel,(*iter).node,edgeoption + "dir=both"); break; case PREORDER: case TOPDOWN: dotrep.addEdge(node,edgelabel,(*iter).node,edgeoption + "dir=forward"); break; case POSTORDER: case BOTTOMUP: dotrep.addEdge(node,edgelabel,(*iter).node,edgeoption + "dir=back"); break; default: assert(false); } } testnum++; } // ************************** } // DQ (7/4/2008): Support for edges specified in AST attributes AstAttributeMechanism* astAttributeContainer = node->get_attributeMechanism(); if (astAttributeContainer != NULL) { // Loop over all the attributes at this IR node for (AstAttributeMechanism::iterator i = astAttributeContainer->begin(); i != astAttributeContainer->end(); i++) { // std::string name = i->first; AstAttribute* attribute = i->second; ROSE_ASSERT(attribute != NULL); // This can return a non-empty list in user-defined attributes (derived from AstAttribute). // printf ("Calling attribute->additionalNodeInfo() \n"); std::vector<AstAttribute::AttributeNodeInfo> nodeList = attribute->additionalNodeInfo(); // printf ("nodeList.size() = %lu \n",nodeList.size()); for (std::vector<AstAttribute::AttributeNodeInfo>::iterator i_node = nodeList.begin(); i_node != nodeList.end(); i_node++) { SgNode* nodePtr = i_node->nodePtr; string nodelabel = i_node->label; string nodeoption = i_node->options; // printf ("In AstDOTGeneration::evaluateSynthesizedAttribute(): Adding a node nodelabel = %s nodeoption = %s \n",nodelabel.c_str(),nodeoption.c_str()); // dotrep.addNode(NULL,dotrep.traceFormat(ia.tdTracePos)+nodelabel,nodeoption); dotrep.addNode( nodePtr, dotrep.traceFormat(ia.tdTracePos) + nodelabel, nodeoption ); } // printf ("Calling attribute->additionalEdgeInfo() \n"); std::vector<AstAttribute::AttributeEdgeInfo> edgeList = attribute->additionalEdgeInfo(); // printf ("edgeList.size() = %lu \n",edgeList.size()); for (std::vector<AstAttribute::AttributeEdgeInfo>::iterator i_edge = edgeList.begin(); i_edge != edgeList.end(); i_edge++) { string edgelabel = i_edge->label; string edgeoption = i_edge->options; // printf ("In AstDOTGeneration::evaluateSynthesizedAttribute(): Adding an edge from i_edge->fromNode = %p to i_edge->toNode = %p edgelabel = %s edgeoption = %s \n",i_edge->fromNode,i_edge->toNode,edgelabel.c_str(),edgeoption.c_str()); dotrep.addEdge(i_edge->fromNode,edgelabel,i_edge->toNode,edgeoption + "dir=forward"); } } } switch(node->variantT()) { // DQ (9/1/2008): Added case for output of SgProject rooted DOT file. // This allows source code and binary files to be combined into the same DOT file. case V_SgProject: { SgProject* project = dynamic_cast<SgProject*>(node); ROSE_ASSERT(project != NULL); string generatedProjectName = SageInterface::generateProjectName( project ); // printf ("generatedProjectName (from SgProject) = %s \n",generatedProjectName.c_str()); if (generatedProjectName.length() > 40) { // printf ("Warning: generatedProjectName (from SgProject) = %s \n",generatedProjectName.c_str()); generatedProjectName = "aggregatedFileNameTooLong"; printf ("Proposed (generated) filename is too long, shortened to: %s \n",generatedProjectName.c_str()); } string filename = string("./") + generatedProjectName + ".dot"; // printf ("generated filename for dot file (from SgProject) = %s \n",filename.c_str()); if ( SgProject::get_verbose() >= 1 ) printf ("Output the DOT graph from the SgProject IR node (filename = %s) \n",filename.c_str()); dotrep.writeToFileAsGraph(filename); break; } // case V_SgFile: case V_SgSourceFile: case V_SgBinaryComposite: { SgFile* file = dynamic_cast<SgFile*>(node); ROSE_ASSERT(file != NULL); string original_filename = file->getFileName(); // DQ (7/4/2008): Fix filenamePostfix to go before the "." // string filename = string("./") + ROSE::stripPathFromFileName(original_filename) + "."+filenamePostfix+"dot"; string filename = string("./") + ROSE::stripPathFromFileName(original_filename) + filenamePostfix + ".dot"; // printf ("generated filename for dot file (from SgSourceFile or SgBinaryComposite) = %s file->get_parent() = %p \n",filename.c_str(),file->get_parent()); // printf ("file->get_parent() = %p \n",file->get_parent()); // cout << "generating DOT file (from SgSourceFile or SgBinaryComposite): " << filename2 << " ... "; // DQ (9/1/2008): this effects the output of DOT files when multiple files are specified // on the command line. A SgProject is still built even when a single file is specificed // on the command line, however there are cases where a SgFile can be built without a // SgProject and this case allows those SgFile rooted subtrees to be output as DOT files. // If there is a SgProject then output the dot file from there, else output as a SgFile. if (file->get_parent() == NULL) { // If there is no SgProject then output the file now! if ( SgProject::get_verbose() >= 1 ) printf ("Output the DOT graph from the SgFile IR node (no SgProject available) \n"); dotrep.writeToFileAsGraph(filename); } else { // There is a SgProject IR node, but if we will be traversing it we want to output the // graph then (so that the graph will include the SgProject IR nodes and connect multiple // files (SgSourceFile or SgBinaryComposite IR nodes). if ( visitedNodes.find(file->get_parent()) == visitedNodes.end() ) { // This SgProject node was not input as part of the traversal, // so we will not be traversing the SgProject IR nodes and we // have to output the graph now! if ( SgProject::get_verbose() >= 1 ) printf ("Output the DOT graph from the SgFile IR node (SgProject was not traversed) \n"); dotrep.writeToFileAsGraph(filename); } else { if ( SgProject::get_verbose() >= 1 ) printf ("Skip the output of the DOT graph from the SgFile IR node (SgProject will be traversed) \n"); } } // cout << "done." << endl; break; } // DQ (7/23/2005): Implemented default case to avoid g++ warnings // about enum values not handled by this switch default: { // nothing to do here break; } } d.node = node; return d; }
DetectMacroExpansionsToBeUnparsedAsAstTransformationsSynthesizedAttribute DetectMacroExpansionsToBeUnparsedAsAstTransformations::evaluateSynthesizedAttribute ( SgNode* n, DetectMacroExpansionsToBeUnparsedAsAstTransformationsInheritedAttribute inheritedAttribute, SubTreeSynthesizedAttributes synthesizedAttributeList ) { DetectMacroExpansionsToBeUnparsedAsAstTransformationsSynthesizedAttribute returnAttribute(n); #if 0 printf ("In (Detect Transformations in Macro Expansions) evaluateSynthesizedAttribute(): n = %s n->get_containsTransformation() = %s \n",n->class_name().c_str(),n->get_containsTransformation() ? "true" : "false"); #endif // DQ (11/8/2015): This has to be moved to after the tokenStreamSequenceMap has been setup since we need that to determine if // IR nodes have a token mapping or not (subparts of macros expansions will not and we need this infor to recognize parts of // the AST that are associated with macro expansions. // DQ (11/8/2015): If this has been marked as containing a transformation then check if there is token info for each of the children. // If there is not token info for each of the children then this currentStatement (e.g. n) must be marked as a transformation. // This case happens when a transformation is done to a child of a statement that is part of a macro. In this case the parent will // have token information which is the macro call, but since there is a transformation, we have to unparse the fully expanded form // of the macro (from the AST), so the whole subtree must be unparsed. NOTE: this case might be more complex if multiple statements // are associated with a macro (so that there is not a single root of the subtree. I need to build an example of this to better // understand if there is a problem and if so just what would be the best solution. It will b at least an iterative refinement of // this specific problem. See tests/roseTests/astInterfaceTests/inputmoveDeclarationToInnermostScope_test2015_135.C for an example // of this problem. if (n->get_containsTransformation() == true) { #if 0 printf ("Found case of statement marked as containing a transforamtion \n"); #endif SgStatement* currentStatement = isSgStatement(n); #if 0 if (currentStatement != NULL) { // printf ("currentStatement = %p = %s \n",currentStatement,currentStatement->class_name().c_str()); printf ("currentStatement = %s \n",currentStatement->class_name().c_str()); printf (" --- currentStatement->isTransformation() = %s \n",currentStatement->isTransformation() ? "true" : "false"); } #endif // We have to test for a macro exapansion (will only work on statement level grainularity where parent statement has child statements). bool all_children_have_token_info = true; for (size_t i = 0; i < synthesizedAttributeList.size(); i++) { SgStatement* statement = isSgStatement(synthesizedAttributeList[i].node); if (statement != NULL) { #if 0 // printf ("(child) statement = %p = %s \n",statement,statement->class_name().c_str()); printf ("(child) statement = %s \n",statement->class_name().c_str()); printf (" --- statement->isTransformation() = %s \n",statement->isTransformation() ? "true" : "false"); printf (" --- statement->get_containsTransformation() = %s \n",statement->get_containsTransformation() ? "true" : "false"); #endif // DQ (11/8/2015): We might need to also check the surrounding white space as well (except that I think this is set later). if (tokenStreamSequenceMap.find(statement) != tokenStreamSequenceMap.end()) { // If we have a token mapping then we don't have to do anything. TokenStreamSequenceToNodeMapping* mapping = tokenStreamSequenceMap[statement]; ROSE_ASSERT(mapping != NULL); } else { #if 0 // printf ("Parent statement = %p = %s No token stream information found for child statement = %p = %s \n", // currentStatement,currentStatement->class_name().c_str(),statement,statement->class_name().c_str()); printf ("Parent statement = %s No token stream information found for child statement = %s \n", currentStatement->class_name().c_str(),statement->class_name().c_str()); printf (" --- at line: %d \n",statement->get_file_info()->get_line()); // When this is a function declaration, try to understand more about it. SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(statement); if (functionDeclaration != NULL) { printf (" --- functionDeclaration name = %s \n",functionDeclaration->get_name().str()); } #endif all_children_have_token_info = false; } } } if (currentStatement != NULL && all_children_have_token_info == false) { #if 0 // printf ("*** Found case of statement marked as containing a transforamtion, but all children without token info (detected a macro expansion): currentStatement = %p = %s \n",currentStatement,currentStatement->class_name().c_str()); printf ("*** Found case of statement marked as containing a transforamtion, but all children without token info (detected a macro expansion): currentStatement = %s \n",currentStatement->class_name().c_str()); #endif // DQ (11/9/2015): Added support for specific scopes where we don't want them the be // unparsed from the token stream when children of them are transformed. // DQ (11/8/2015): I think that this should not apply to a SgBasicBlock (for example see // tests/roseTests/astInterfaceTests/inputmoveDeclarationToInnermostScope_test2015_94.C). // The reason is that a block is not the same sort for compound statement as a SgForStatement. // if (isSgBasicBlock(currentStatement) == NULL) bool current_statement_is_allowed_to_have_statements_with_unmapped_token_sequences = ( (isSgGlobal(currentStatement) != NULL) || (isSgBasicBlock(currentStatement) != NULL) || // (isSgEnumDefinition(currentStatement) != NULL) || (isSgClassDefinition(currentStatement) != NULL) ); if (current_statement_is_allowed_to_have_statements_with_unmapped_token_sequences == false) { // Mark as a transformation instead of containing a transformation. currentStatement->setTransformation(); // We also need to mark this too! currentStatement->setOutputInCodeGeneration(); // And reset this to NOT contain a transformation. currentStatement->set_containsTransformation(false); #if 0 printf ("Exiting as a test! \n"); ROSE_ASSERT(false); #endif } else { #if 0 // printf ("This currentStatement = %p = %s is allowed to have a child without a token sequence mapping \n",currentStatement,currentStatement->class_name().c_str()); printf ("This currentStatement = %s is allowed to have a child without a token sequence mapping \n",currentStatement->class_name().c_str()); #endif } } #if 0 // Debugging code. if (isSgForStatement(n) != NULL) { printf ("Exiting as a test! \n"); ROSE_ASSERT(false); } #endif } return returnAttribute; }
SynthesizedAttribute Traversal::evaluateSynthesizedAttribute ( SgNode* astNode, InheritedAttribute inheritedAttribute, SynthesizedAttributesList childAttributes ) { SynthesizedAttribute localResult; // printf ("evaluateSynthesizedAttribute(): astNode = %p = %s inheritedAttribute.isFirstFile = %s \n",astNode,astNode->class_name().c_str(),inheritedAttribute.isFirstFile ? "true" : "false"); // Accumulate any valid pointer to main on a child node and pass it to the local synthesized attribute. for (size_t i = 0; i < childAttributes.size(); i++) { if (childAttributes[i].main_function != NULL) { localResult.main_function = childAttributes[i].main_function; } } if (inheritedAttribute.isFirstFile == true) { SgGlobal* globalScope = isSgGlobal(astNode); if (globalScope != NULL) { // Gather all of the functions in global scope of the first file. vector<SgDeclarationStatement*> globalScopeDeclarationsToMove = globalScope->get_declarations(); inheritedAttribute.statements_from_first_file = globalScopeDeclarationsToMove; // printf ("evaluateSynthesizedAttribute(): Gather all of the functions in global scope of the first file inheritedAttribute.statements_from_first_file.size() = %zu \n",inheritedAttribute.statements_from_first_file.size()); // Erase the declarations in the global scope of the first file. globalScope->get_declarations().clear(); } SgDeclarationStatement* declarationStatement = isSgDeclarationStatement(astNode); if (declarationStatement != NULL && isSgGlobal(declarationStatement->get_parent()) != NULL) { // Mark as a transformation (recursively mark the whole subtree). // printf ("*** Mark as a transformation: declarationStatement = %p \n",declarationStatement); markAsTransformation(declarationStatement); if (declarationStatement->get_firstNondefiningDeclaration() != NULL) markAsTransformation(declarationStatement->get_firstNondefiningDeclaration()); } } else { SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(astNode); if (functionDeclaration != NULL && functionDeclaration->get_name() == "main") { // Save the pointer to the main function (in the second file). localResult.main_function = functionDeclaration; // printf ("Found the main function ...(saved pointer) inheritedAttribute.main_function = %p \n",localResult.main_function); } // printf ("evaluateSynthesizedAttribute(): localResult.main_function = %p \n",localResult.main_function); // Test for the selected insertion point in the 2nd file for the declarations gathered from the first file. SgGlobal* globalScope = isSgGlobal(astNode); if (globalScope != NULL && localResult.main_function != NULL) { printf ("evaluateSynthesizedAttribute(): Found the main function ...\n"); vector<SgDeclarationStatement*>::iterator i = find(globalScope->get_declarations().begin(),globalScope->get_declarations().end(),localResult.main_function); globalScope->get_declarations().insert(i,inheritedAttribute.statements_from_first_file.begin(),inheritedAttribute.statements_from_first_file.end()); #if 0 // Set the parents of each declaration to match the new location (avoids warning that might later be an error). for (size_t i = 0; i < inheritedAttribute.statements_from_first_file.size(); i++) { inheritedAttribute.statements_from_first_file[i]->set_parent(globalScope); } #endif } } return localResult; }
ATerm convertNodeToAterm(SgNode* n) { if (n == NULL) { #if 0 printf ("convertNodeToAterm(): n = %p = %s \n",n,"NULL"); #endif return ATmake("NULL"); } ROSE_ASSERT(n != NULL); #if 0 printf ("convertNodeToAterm(): n = %p = %s \n",n,n->class_name().c_str()); #endif ATerm term; switch (n->variantT()) { // case V_SgFile: case V_SgSourceFile: // Special case needed to include file name // term = ATmake("File(<str>, <term>)", isSgFile(n)->getFileName(), convertNodeToAterm(isSgFile(n)->get_root())); term = ATmake("File(<str>, <term>)", isSgSourceFile(n)->getFileName().c_str(), convertNodeToAterm(isSgSourceFile(n)->get_globalScope())); break; case V_SgPlusPlusOp: case V_SgMinusMinusOp: // Special cases needed to include prefix/postfix status term = ATmake("<appl(<appl>, <term>)>", getShortVariantName((VariantT)(n->variantT())).c_str(), (isSgUnaryOp(n)->get_mode() == SgUnaryOp::prefix ? "Prefix" : isSgUnaryOp(n)->get_mode() == SgUnaryOp::postfix ? "Postfix" : "Unknown"), convertNodeToAterm(isSgUnaryOp(n)->get_operand())); break; case V_SgExpressionRoot: // Special case to remove this node term = convertNodeToAterm(isSgExpressionRoot(n)->get_operand()); break; case V_SgCastExp: // Special case needed to include type term = ATmake("Cast(<term>, <term>)>", convertNodeToAterm(isSgUnaryOp(n)->get_operand()), convertNodeToAterm(isSgCastExp(n)->get_type())); break; case V_SgVarRefExp: // Special case needed to include id term = ATmake("Var(<str>)", uniqueId(isSgVarRefExp(n)->get_symbol()->get_declaration()).c_str()); break; case V_SgFunctionRefExp: // Special case needed to include id term = ATmake( "Func(<str>)", uniqueId(isSgFunctionRefExp(n)->get_symbol()->get_declaration()).c_str()); break; case V_SgIntVal: // Special case needed to include value term = ATmake("IntC(<int>)", isSgIntVal(n)->get_value()); break; case V_SgUnsignedIntVal: term = ATmake("UnsignedIntC(<int>)", isSgUnsignedIntVal(n)->get_value()); break; case V_SgUnsignedLongVal: { ostringstream s; s << isSgUnsignedLongVal(n)->get_value(); term = ATmake("UnsignedLongC(<str>)", s.str().c_str()); } break; case V_SgUnsignedLongLongIntVal: { ostringstream s; s << isSgUnsignedLongLongIntVal(n)->get_value(); term = ATmake("UnsignedLongLongC(<str>)", s.str().c_str()); } break; case V_SgDoubleVal: term = ATmake("DoubleC(<real>)", isSgDoubleVal(n)->get_value()); break; case V_SgInitializedName: { // Works around double initname problem SgInitializer* initializer = isSgInitializedName(n)->get_initializer(); const SgName& name = isSgInitializedName(n)->get_name(); SgType* type = isSgInitializedName(n)->get_type(); ROSE_ASSERT(type != NULL); #if 0 printf ("convertNodeToAterm(): case V_SgInitializedName: name = %s initializer = %p type = %p = %s \n",name.str(),initializer,type,type->class_name().c_str()); #endif // Works around fact that ... is not really an initname and shouldn't be a type either if (isSgTypeEllipse(type)) { term = ATmake("Ellipses"); } else { std::string uniqueIdString = uniqueId(n); #if 0 printf ("uniqueIdString = %s \n",uniqueIdString.c_str()); printf ("Calling generate ATerm for SgInitializedName->get_name() name = %s \n",name.str()); ATerm name_aterm = ATmake("Name(<str>)",name.str()); // ATerm name_aterm = ATmake(name.str()); printf ("Calling convertNodeToAterm(type) \n"); ATerm type_aterm = convertNodeToAterm(type); printf ("Calling convertNodeToAterm(initializer) \n"); #endif ATerm initializer_aterm = convertNodeToAterm(initializer); #if 0 printf ("Calling ATmake() \n"); #endif #if 1 term = ATmake("InitName(<str>, <term>, <term>) {[id, <str>]}", (name.str() ? name.str() : ""), convertNodeToAterm(type), convertNodeToAterm(initializer), uniqueId(n).c_str()); // uniqueIdString.c_str()); #else term = ATmake("InitName(<term>,<term>)", //(name.str() ? name.str() : ""), // name_aterm, type_aterm, initializer_aterm // uniqueId(n).c_str()); // uniqueIdString.c_str()); ); #endif #if 0 printf ("Calling ATsetAnnotation() \n"); #endif term = ATsetAnnotation(term, ATmake("id"), ATmake("<str>", uniqueId(n).c_str())); #if 0 printf ("DONE: Calling ATsetAnnotation() \n"); #endif } break; } case V_SgFunctionDeclaration: { // Special case needed to include name SgFunctionDeclaration* fd = isSgFunctionDeclaration(n); term = ATmake("Function(<str>, <term>, <term>, <term>)", fd->get_name().str(), convertNodeToAterm(fd->get_orig_return_type()), convertSgNodeRangeToAterm(fd->get_args().begin(), fd->get_args().end()), convertNodeToAterm(fd->get_definition())); term = ATsetAnnotation(term, ATmake("id"), ATmake("<str>", uniqueId(n).c_str())); } break; case V_SgClassDeclaration: { // Special case needed to distinguish forward/full definitions and to // include class name SgClassDeclaration* decl = isSgClassDeclaration(n); assert (decl); SgName sname = decl->get_name(); const char* name = sname.str(); // Suggestion: have a field named local_definition in each class // declaration that is 0 whenever the current declaration doesn't // have a definition attached, even if there is another declaration // which does have a definition attached. SgClassDefinition* defn = decl->get_definition(); // cout << "defn = 0x" << hex << defn << endl << dec; if (decl->isForward()) defn = 0; if (defn) term = ATmake("Class(<str>, <term>)", (name ? name : ""), // Will be simpler when SgName // becomes string convertNodeToAterm(defn)); else term = ATmake("ClassFwd(<str>)", (name ? name : "")); term = ATsetAnnotation(term, ATmake("id"), ATmake("<str>", uniqueId(n).c_str())); } break; case V_SgEnumDeclaration: { // Special case to include enum name and enumerator names which are not // traversal children SgName sname = isSgEnumDeclaration(n)->get_name(); const char* name = sname.str(); const SgInitializedNamePtrList& enumerators = isSgEnumDeclaration(n)->get_enumerators(); term = ATmake("Enum(<str>, <term>)", (name ? name : "{anonymous}"), convertSgNodeRangeToAterm(enumerators.begin(), enumerators.end())); term = ATsetAnnotation(term, ATmake("id"), ATmake("<str>", uniqueId(n).c_str())); } break; case V_SgPointerType: { // Special case because types can't be traversed yet SgType* type = isSgPointerType(n)->get_base_type(); ATerm t = convertNodeToAterm(type); term = ATmake("Pointer(<term>)", t); } break; case V_SgReferenceType: { // Special case because types can't be traversed yet SgType* type = isSgReferenceType(n)->get_base_type(); ATerm t = convertNodeToAterm(type); term = ATmake("Reference(<term>)", t); } break; case V_SgModifierType: { // Special case for type traversal and to prettify modifier names SgType* type = isSgModifierType(n)->get_base_type(); SgTypeModifier& modifier = isSgModifierType(n)->get_typeModifier(); SgConstVolatileModifier& cvmod = modifier.get_constVolatileModifier(); term = convertNodeToAterm(type); if (cvmod.isConst()) term = ATmake("Const(<term>)", term); if (cvmod.isVolatile()) term = ATmake("Volatile(<term>)", term); } break; case V_SgArrayType: { // Special case because types can't be traversed yet, and to get length SgType* type = isSgArrayType(n)->get_base_type(); ATerm t = convertNodeToAterm(type); term = ATmake("Array(<term>, <term>)", t, (isSgArrayType(n)->get_index() ? convertNodeToAterm((n->get_traversalSuccessorContainer())[4]) : ATmake("<str>", "NULL"))); assert (term); } break; case V_SgFunctionType: { // Special case to allow argument list to be traversed SgFunctionType* ft = isSgFunctionType(n); ATerm ret = convertNodeToAterm(ft->get_return_type()); ATerm args_list = convertSgNodeRangeToAterm(ft->get_arguments().begin(), ft->get_arguments().end()); term = ATmake("FunctionType(<term>, <term>)", ret, args_list); } break; case V_SgEnumType: case V_SgClassType: case V_SgTypedefType: { // Special cases to optionally put in type definition instead of // reference SgNamedType* nt = isSgNamedType(n); assert (nt); SgName sname = nt->get_name(); // char* name = sname.str(); SgDeclarationStatement* decl = nt->get_declaration(); assert (decl); SgClassDefinition* defn = isSgClassDeclaration(decl) ? isSgClassDeclaration(decl)->get_definition() : 0; term = ATmake("Type(<term>)", (nt->get_autonomous_declaration() || !defn ? ATmake("id(<str>)", uniqueId(decl).c_str()) : convertNodeToAterm(nt->get_declaration()))); } break; case V_SgLabelStatement: { // Special case to put in label id const char* name = isSgLabelStatement(n)->get_name().str(); term = ATmake("Label(<str>)", (name ? name : "")); term = ATsetAnnotation(term, ATmake("id"), ATmake("<str>", uniqueId(n).c_str())); } break; case V_SgGotoStatement: { // Special case to put in label id term = ATmake("Goto(<str>)", uniqueId(isSgGotoStatement(n)->get_label()).c_str()); } break; case V_SgTypedefDeclaration: { // Special case to put in typedef name const SgName& name = isSgTypedefDeclaration(n)->get_name(); SgType* type = isSgTypedefDeclaration(n)->get_base_type(); term = ATmake("Typedef(<str>, <term>)", (name.str() ? name.str() : ""), convertNodeToAterm(type)); term = ATsetAnnotation(term, ATmake("id"), ATmake("<str>", uniqueId(n).c_str())); } break; case V_SgTemplateDeclaration: { // Traversal doesn't work for these SgTemplateDeclaration* td = isSgTemplateDeclaration(n); ROSE_ASSERT (td); // SgTemplateParameterPtrListPtr paramsPtr = td->get_templateParameters(); // SgTemplateParameterPtrList & paramsPtr = td->get_templateParameters(); // SgTemplateParameterPtrList params = paramsPtr ? *paramsPtr : SgTemplateParameterPtrList(); SgTemplateParameterPtrList & params = td->get_templateParameters(); string templateKindString; switch (td->get_template_kind()) { case SgTemplateDeclaration::e_template_none: templateKindString = "None"; break; case SgTemplateDeclaration::e_template_class: templateKindString = "Class"; break; case SgTemplateDeclaration::e_template_m_class: templateKindString = "MemberClass"; break; case SgTemplateDeclaration::e_template_function: templateKindString = "Function"; break; case SgTemplateDeclaration::e_template_m_function: templateKindString = "MemberFunction"; break; case SgTemplateDeclaration::e_template_m_data: templateKindString = "MemberData"; break; default: templateKindString = "Unknown"; break; } term = ATmake("TemplateDeclaration(<appl>, <str>, <term>, <str>)", templateKindString.c_str(), td->get_name().str(), convertSgNodeRangeToAterm(params.begin(), params.end()), td->get_string().str()); } break; case V_SgTemplateInstantiationDecl: { // Traversal doesn't work for these SgTemplateInstantiationDecl* td = isSgTemplateInstantiationDecl(n); ROSE_ASSERT (td); // SgTemplateArgumentPtrListPtr argsPtr = td->get_templateArguments(); // SgTemplateArgumentPtrList args = argsPtr ? *argsPtr : SgTemplateArgumentPtrList(); SgTemplateArgumentPtrList & args = td->get_templateArguments(); term = ATmake("TemplateInstantiationDecl(<str>, <term>)", td->get_templateDeclaration()->get_name().str(), convertSgNodeRangeToAterm(args.begin(), args.end())); } break; case V_SgTemplateParameter: { // Traversal doesn't work for these SgTemplateParameter* tp = isSgTemplateParameter(n); ROSE_ASSERT (tp); switch (tp->get_parameterType()) { case SgTemplateParameter::parameter_undefined: { term = ATmake("Undefined"); } break; case SgTemplateParameter::type_parameter: { term = ATmake("Type(<term>)", convertNodeToAterm(tp->get_defaultTypeParameter())); } break; case SgTemplateParameter::nontype_parameter: { term = ATmake("Nontype(<term>, <term>)", convertNodeToAterm(tp->get_type()), convertNodeToAterm(tp->get_defaultExpressionParameter())); } break; case SgTemplateParameter::template_parameter: { term = ATmake("Template"); } break; default: term = ATmake("Unknown"); break; } } break; case V_SgTemplateArgument: { // Traversal doesn't work for these SgTemplateArgument* ta = isSgTemplateArgument(n); ROSE_ASSERT (ta); switch (ta->get_argumentType()) { case SgTemplateArgument::argument_undefined: term = ATmake("Undefined"); break; case SgTemplateArgument::type_argument: term = ATmake("Type(<term>)", convertNodeToAterm(ta->get_type())); break; case SgTemplateArgument::nontype_argument: term = ATmake("Nontype(<term>)", convertNodeToAterm(ta->get_expression())); break; // case SgTemplateArgument::template_argument: // term = ATmake("Template"); // break; default: term = ATmake("Unknown"); break; } } break; default: { bool isContainer = (AstTests::numSuccContainers(n) == 1) || (!isSgType(n) && (n->get_traversalSuccessorContainer().size() == 0)); term = ATmake((isContainer ? "<appl(<term>)>" : "<appl(<list>)>"), getShortVariantName((VariantT)(n->variantT())).c_str(), (isSgType(n) ? ATmake("[]") : getTraversalChildrenAsAterm(n))); // Special case for types is because of traversal problems } break; } #if 0 printf ("Base of switch statement in convertNodeToAterm(): n = %p = %s \n",n,n->class_name().c_str()); #endif assert (term); term = ATsetAnnotation(term, ATmake("ptr"), pointerAsAterm(n)); #if 1 if (n->get_file_info() != NULL) { term = ATsetAnnotation(term, ATmake("location"),convertFileInfoToAterm(n->get_file_info())); } if (isSgExpression(n)) term = ATsetAnnotation(term, ATmake("type"), convertNodeToAterm(isSgExpression(n)->get_type())); #endif #if 0 printf ("Leaving convertNodeToAterm(): n = %p = %s \n",n,n->class_name().c_str()); #endif #if 0 printf ("--- n->class_name() = %s ATwriteToString(term) = %s \n",n->class_name().c_str(),ATwriteToString(term)); #endif // cout << n->sage_class_name() << " -> " << ATwriteToString(term) << endl; return term; }
void SystemDependenceGraph::build() { boost::unordered_map<CFGVertex, Vertex> cfgVerticesToSdgVertices; boost::unordered_map<SgNode*, Vertex> astNodesToSdgVertices; //map<SgFunctionCallExp*, vector<SDGNode*> > funcCallToArgs; vector<CallSiteInfo> functionCalls; map<SgNode*, vector<Vertex> > actualInParameters; map<SgNode*, vector<Vertex> > actualOutParameters; map<SgNode*, Vertex> formalInParameters; map<SgNode*, Vertex> formalOutParameters; vector<SgFunctionDefinition*> funcDefs = SageInterface::querySubTree<SgFunctionDefinition>(project_, V_SgFunctionDefinition); foreach (SgFunctionDefinition* funcDef, funcDefs) { SgFunctionDeclaration* funcDecl = funcDef->get_declaration(); CFG* cfg = new CFG(funcDef, cfgNodefilter_); functionsToCFGs_[funcDecl] = cfg; // For each function, build an entry node for it. SDGNode* entry = new SDGNode(SDGNode::Entry); entry->astNode = funcDef; //entry->funcDef = funcDef; Vertex entryVertex = addVertex(entry); functionsToEntries_[funcDecl] = entryVertex; // Add all out formal parameters to SDG. const SgInitializedNamePtrList& formalArgs = funcDecl->get_args(); foreach (SgInitializedName* initName, formalArgs) { // If the parameter is passed by reference, create a formal-out node. if (isParaPassedByRef(initName->get_type())) { SDGNode* formalOutNode = new SDGNode(SDGNode::FormalOut); formalOutNode->astNode = initName; Vertex formalOutVertex = addVertex(formalOutNode); formalOutParameters[initName] = formalOutVertex; // Add a CD edge from call node to this formal-out node. addTrueCDEdge(entryVertex, formalOutVertex); } } // A vertex representing the returned value. Vertex returnVertex; // If the function returns something, build a formal-out node. if (!isSgTypeVoid(funcDecl->get_type()->get_return_type())) { SDGNode* formalOutNode = new SDGNode(SDGNode::FormalOut); // Assign the function declaration to the AST node of this vertex to make // it possible to classify this node into the subgraph of this function. formalOutNode->astNode = funcDecl; returnVertex = addVertex(formalOutNode); formalOutParameters[funcDecl] = returnVertex; // Add a CD edge from call node to this formal-out node. addTrueCDEdge(entryVertex, returnVertex); } // Add all CFG vertices to SDG. foreach (CFGVertex cfgVertex, boost::vertices(*cfg)) { if (cfgVertex == cfg->getEntry() || cfgVertex == cfg->getExit()) continue; SgNode* astNode = (*cfg)[cfgVertex]->getNode(); // If this node is an initialized name and it is a parameter, make it // as a formal in node. SgInitializedName* initName = isSgInitializedName(astNode); if (initName && isSgFunctionParameterList(initName->get_parent())) { SDGNode* formalInNode = new SDGNode(SDGNode::FormalIn); formalInNode->astNode = initName; Vertex formalInVertex = addVertex(formalInNode); formalInParameters[initName] = formalInVertex; cfgVerticesToSdgVertices[cfgVertex] = formalInVertex; astNodesToSdgVertices[astNode] = formalInVertex; // Add a CD edge from call node to this formal-in node. addTrueCDEdge(entryVertex, formalInVertex); continue; } // Add a new node to SDG. SDGNode* newSdgNode = new SDGNode(SDGNode::ASTNode); //newSdgNode->cfgNode = (*cfg)[cfgVertex]; newSdgNode->astNode = astNode; Vertex sdgVertex = addVertex(newSdgNode); cfgVerticesToSdgVertices[cfgVertex] = sdgVertex; astNodesToSdgVertices[astNode] = sdgVertex; // Connect a vertex containing the return statement to the formal-out return vertex. if (isSgReturnStmt(astNode) || isSgReturnStmt(astNode->get_parent())) { SDGEdge* newEdge = new SDGEdge(SDGEdge::DataDependence); addEdge(sdgVertex, returnVertex, newEdge); } // If this CFG node contains a function call expression, extract its all parameters // and make them as actual-in nodes. if (SgFunctionCallExp* funcCallExpr = isSgFunctionCallExp(astNode)) { CallSiteInfo callInfo; callInfo.funcCall = funcCallExpr; callInfo.vertex = sdgVertex; // Change the node type. newSdgNode->type = SDGNode::FunctionCall; vector<SDGNode*> argsNodes; // Get the associated function declaration. SgFunctionDeclaration* funcDecl = funcCallExpr->getAssociatedFunctionDeclaration(); if (funcDecl == NULL) continue; ROSE_ASSERT(funcDecl); const SgInitializedNamePtrList& formalArgs = funcDecl->get_args(); SgExprListExp* args = funcCallExpr->get_args(); const SgExpressionPtrList& actualArgs = args->get_expressions(); if (formalArgs.size() != actualArgs.size()) { cout << "The following function has variadic arguments:\n"; cout << funcDecl->get_file_info()->get_filename() << endl; cout << funcDecl->get_name() << formalArgs.size() << " " << actualArgs.size() << endl; continue; } for (int i = 0, s = actualArgs.size(); i < s; ++i) { // Make sure that this parameter node is added to SDG then we // change its node type from normal AST node to a ActualIn arg. ROSE_ASSERT(astNodesToSdgVertices.count(actualArgs[i])); Vertex paraInVertex = astNodesToSdgVertices.at(actualArgs[i]); SDGNode* paraInNode = (*this)[paraInVertex]; paraInNode->type = SDGNode::ActualIn; actualInParameters[formalArgs[i]].push_back(paraInVertex); callInfo.inPara.push_back(paraInVertex); // Add a CD edge from call node to this actual-in node. addTrueCDEdge(sdgVertex, paraInVertex); // If the parameter is passed by reference, create a parameter-out node. if (isParaPassedByRef(formalArgs[i]->get_type())) { SDGNode* paraOutNode = new SDGNode(SDGNode::ActualOut); paraOutNode->astNode = actualArgs[i]; //argsNodes.push_back(paraInNode); // Add an actual-out parameter node. Vertex paraOutVertex = addVertex(paraOutNode); actualOutParameters[formalArgs[i]].push_back(paraOutVertex); callInfo.outPara.push_back(paraOutVertex); // Add a CD edge from call node to this actual-out node. addTrueCDEdge(sdgVertex, paraOutVertex); } } if (!isSgTypeVoid(funcDecl->get_type()->get_return_type())) { // If this function returns a value, create a actual-out vertex. SDGNode* paraOutNode = new SDGNode(SDGNode::ActualOut); paraOutNode->astNode = funcCallExpr; // Add an actual-out parameter node. Vertex paraOutVertex = addVertex(paraOutNode); actualOutParameters[funcDecl].push_back(paraOutVertex); callInfo.outPara.push_back(paraOutVertex); callInfo.isVoid = false; callInfo.returned = paraOutVertex; // Add a CD edge from call node to this actual-out node. addTrueCDEdge(sdgVertex, paraOutVertex); } functionCalls.push_back(callInfo); //funcCallToArgs[funcCallExpr] = argsNodes; } } // Add control dependence edges. addControlDependenceEdges(cfgVerticesToSdgVertices, *cfg, entryVertex); }
InheritedAttribute visitorTraversal::evaluateInheritedAttribute(SgNode* n, InheritedAttribute inheritedAttribute) { Sg_File_Info* s = n->get_startOfConstruct(); Sg_File_Info* e = n->get_endOfConstruct(); Sg_File_Info* f = n->get_file_info(); for(int x=0; x < inheritedAttribute.depth; ++x) { printf(" "); } if(s != NULL && e != NULL && !isSgLabelStatement(n)) { printf ("%s (%d, %d, %d)->(%d, %d): %s",n->sage_class_name(),s->get_file_id()+1,s->get_raw_line(),s->get_raw_col(),e->get_raw_line(),e->get_raw_col(), verbose ? n->unparseToString().c_str() : "" ); if(isSgAsmDwarfConstruct(n)) { printf(" [DWARF construct name: %s]", isSgAsmDwarfConstruct(n)->get_name().c_str()); } SgExprStatement * exprStmt = isSgExprStatement(n); if(exprStmt != NULL) { printf(" [expr type: %s]", exprStmt->get_expression()->sage_class_name()); SgFunctionCallExp * fcall = isSgFunctionCallExp(exprStmt->get_expression()); if(fcall != NULL) { SgExpression * funcExpr = fcall->get_function(); if(funcExpr != NULL) { printf(" [function expr: %s]", funcExpr->class_name().c_str()); } SgFunctionDeclaration * fdecl = fcall->getAssociatedFunctionDeclaration(); if(fdecl != NULL) { printf(" [called function: %s]", fdecl->get_name().str()); } } } if(isSgFunctionDeclaration(n)) { printf(" [declares function: %s]", isSgFunctionDeclaration(n)->get_name().str()); } SgStatement * sgStmt = isSgStatement(n); if(sgStmt != NULL) { printf(" [scope: %s, %p]", sgStmt->get_scope()->sage_class_name(), sgStmt->get_scope()); } //SgLabelStatement * lblStmt = isSgLabelStatement(n); //if(lblStmt != NULL) { // SgStatement * lblStmt2 = lblStmt->get_statement(); //} } else if (f != NULL) { SgInitializedName * iname = isSgInitializedName(n); if(iname != NULL) { SgType* inameType = iname->get_type(); printf("%s (%d, %d, %d): %s [type: %s", n->sage_class_name(),f->get_file_id()+1,f->get_raw_line(),f->get_raw_col(),n->unparseToString().c_str(),inameType->class_name().c_str()); SgDeclarationStatement * ds = isSgDeclarationStatement(iname->get_parent()); if(ds != NULL) { if(ds->get_declarationModifier().get_storageModifier().isStatic()) { printf(" static"); } } SgArrayType * art = isSgArrayType(iname->get_type()); if(art != NULL) { printf(" %d", art->get_rank()); } printf("]"); if(isSgAsmDwarfConstruct(n)) { printf(" [DWARF construct name: %s]", isSgAsmDwarfConstruct(n)->get_name().c_str()); } } else { printf("%s (%d, %d, %d): %s", n->sage_class_name(),f->get_file_id()+1,f->get_raw_line(),f->get_raw_col(), verbose ? n->unparseToString().c_str() : ""); } } else { printf("%s : %s", n->sage_class_name(), verbose ? n->unparseToString().c_str() : ""); if(isSgAsmDwarfConstruct(n)) { printf(" [DWARF construct name: %s]", isSgAsmDwarfConstruct(n)->get_name().c_str()); } } printf(" succ# %lu", n->get_numberOfTraversalSuccessors()); printf("\n"); return InheritedAttribute(inheritedAttribute.depth+1); }
SgFunctionDeclaration * CudaOutliner::generateFunction ( SgBasicBlock* s, const string& func_name_str, ASTtools::VarSymSet_t& syms, MintHostSymToDevInitMap_t hostToDevVars, const ASTtools::VarSymSet_t& pdSyms, const ASTtools::VarSymSet_t& psyms, SgScopeStatement* scope) { //Create a function named 'func_name_str', with a parameter list from 'syms' //pdSyms specifies symbols which must use pointer dereferencing if replaced during outlining, //only used when -rose:outline:temp_variable is used //psyms are the symbols for OpenMP private variables, or dead variables (not live-in, not live-out) ROSE_ASSERT ( s && scope); ROSE_ASSERT(isSgGlobal(scope)); // step 1: perform necessary liveness and side effect analysis, if requested. // --------------------------------------------------------- std::set< SgInitializedName *> liveIns, liveOuts; // Collect read-only variables of the outlining target std::set<SgInitializedName*> readOnlyVars; if (Outliner::temp_variable||Outliner::enable_classic) { SgStatement* firstStmt = (s->get_statements())[0]; if (isSgForStatement(firstStmt)&& Outliner::enable_liveness) { LivenessAnalysis * liv = SageInterface::call_liveness_analysis (SageInterface::getProject()); SageInterface::getLiveVariables(liv, isSgForStatement(firstStmt), liveIns, liveOuts); } SageInterface::collectReadOnlyVariables(s,readOnlyVars); if (0)//Outliner::enable_debug) { cout<<" INFO:Mint: CudaOutliner::generateFunction()---Found "<<readOnlyVars.size()<<" read only variables..:"; for (std::set<SgInitializedName*>::const_iterator iter = readOnlyVars.begin(); iter!=readOnlyVars.end(); iter++) cout<<" "<<(*iter)->get_name().getString()<<" "; cout<<endl; cout<<"CudaOutliner::generateFunction() -----Found "<<liveOuts.size()<<" live out variables..:"; for (std::set<SgInitializedName*>::const_iterator iter = liveOuts.begin(); iter!=liveOuts.end(); iter++) cout<<" "<<(*iter)->get_name().getString()<<" "; cout<<endl; } } //step 2. Create function skeleton, 'func'. // ----------------------------------------- SgName func_name (func_name_str); SgFunctionParameterList *parameterList = buildFunctionParameterList(); SgType* func_Type = SgTypeVoid::createType (); SgFunctionDeclaration* func = createFuncSkeleton (func_name, func_Type ,parameterList, scope); //adds __global__ keyword func->get_functionModifier().setCudaKernel(); ROSE_ASSERT (func); // Liao, 4/15/2009 , enforce C-bindings for C++ outlined code // enable C code to call this outlined function // Only apply to C++ , pure C has trouble in recognizing extern "C" // Another way is to attach the function with preprocessing info: // #if __cplusplus // extern "C" // #endif // We don't choose it since the language linkage information is not explicit in AST if ( SageInterface::is_Cxx_language() || is_mixed_C_and_Cxx_language() \ || is_mixed_Fortran_and_Cxx_language() || is_mixed_Fortran_and_C_and_Cxx_language() ) { // Make function 'extern "C"' func->get_declarationModifier().get_storageModifier().setExtern(); func->set_linkage ("C"); } //step 3. Create the function body // ----------------------------------------- // Generate the function body by deep-copying 's'. SgBasicBlock* func_body = func->get_definition()->get_body(); ROSE_ASSERT (func_body != NULL); // This does a copy of the statements in "s" to the function body of the outlined function. ROSE_ASSERT(func_body->get_statements().empty() == true); // This calls AST copy on each statement in the SgBasicBlock, but not on the block, so the // symbol table is setup by AST copy mechanism and it is setup properly SageInterface::moveStatementsBetweenBlocks (s, func_body); if (Outliner::useNewFile) ASTtools::setSourcePositionAtRootAndAllChildrenAsTransformation(func_body); //step 4: variable handling, including: // ----------------------------------------- // create parameters of the outlined functions // add statements to unwrap the parameters if wrapping is requested // add repacking statements if necessary // replace variables to access to parameters, directly or indirectly // do not wrap parameters Outliner::enable_classic = true; functionParameterHandling(syms, hostToDevVars, pdSyms, psyms, readOnlyVars, liveOuts, func); ROSE_ASSERT (func != NULL); // Retest this... // Copied the similar fix from the rose outliner // Liao 2/6/2013. It is essential to rebuild function type after the parameter list is finalized. // The original function type was build using empty parameter list. SgType* stale_func_type = func->get_type(); func->set_type(buildFunctionType(func->get_type()->get_return_type(), buildFunctionParameterTypeList(func->get_parameterList()))); SgFunctionDeclaration* non_def_func = isSgFunctionDeclaration(func->get_firstNondefiningDeclaration ()) ; ROSE_ASSERT (non_def_func != NULL); ROSE_ASSERT (stale_func_type == non_def_func->get_type()); non_def_func->set_type(func->get_type()); ROSE_ASSERT(func->get_definition()->get_body()->get_parent() == func->get_definition()); ROSE_ASSERT(scope->lookup_function_symbol(func->get_name())); return func; }
int main(int argc, char *argv[]) { std::string filename; SgProject *project = frontend(argc, argv); #ifdef NEWDU EDefUse *edu=new EDefUse(project); // Create the global def-use analysis if (edu->run(false)==0) { std::cerr<<"DFAnalysis failed!"<<endl; } #endif std::vector<InterproceduralInfo*> ip; // list < SgNode * >functionDeclarations = NodeQuery::querySubTree(project, V_SgFunctionDeclaration); NodeQuerySynthesizedAttributeType functionDeclarations = NodeQuery::querySubTree(project, V_SgFunctionDeclaration); // for (list < SgNode * >::iterator i = functionDeclarations.begin(); i != functionDeclarations.end(); i++) for (NodeQuerySynthesizedAttributeType::iterator i = functionDeclarations.begin(); i != functionDeclarations.end(); i++) { DataDependenceGraph *ddg; InterproceduralInfo *ipi; SgFunctionDeclaration *fD = isSgFunctionDeclaration(*i); // SGFunctionDefinition * fDef; ROSE_ASSERT(fD != NULL); // CI (01/08/2007): A missing function definition is an indicator to a // // // librarycall. // * An other possibility would be a programmer-mistake, which we // don't treat at this point. // I assume librarycall if (fD->get_definition() == NULL) { } else { // get the control depenence for this function ipi=new InterproceduralInfo(fD); ROSE_ASSERT(ipi != NULL); // get the data dependence for this function #ifdef NEWDU ddg = new DataDependenceGraph(fD->get_definition(),edu); #else ddg = new DataDependenceGraph(fD->get_definition()); #endif //printf("DDG for %s:\n", fD->get_name().str()); // Liao, Feb. 7/2008, //strip off absolute path to avoid polluting the source tree with generated .dot files //filename = (fD->get_definition()->get_file_info()->get_filenameString ()) filename = StringUtility::stripPathFromFileName((fD->get_definition()->get_file_info()->get_filenameString ())) + "." + (fD->get_name().getString()) + ".ddg.dot"; ddg->writeDot((char *)filename.c_str()); } } return 0; }
int main (int argc, char *argv[]) { /* indicate whether include files need to be added */ bool loopTransformApplied = false ; /* more bools at top of file... */ bool withPAPI = false ; bool showStats = false ; bool enablePostProcessing = false ; /***********************************************/ /* Process command line options */ /***********************************************/ Rose_STL_Container<string> cmdLineArgs = CommandlineProcessing::generateArgListFromArgcArgv(argc,argv) ; if ( CommandlineProcessing::isOption( cmdLineArgs, "-et:", "(s|stats)", true) ) { showStats = true ; } if ( CommandlineProcessing::isOption( cmdLineArgs, "-et:", "(p|papi)", true) ) { withPAPI = true ; } if ( CommandlineProcessing::isOption( cmdLineArgs, "-et:", "(l|loops)", true) ) { emitSeqSeg = false ; } if ( CommandlineProcessing::isOption( cmdLineArgs, "-et:", "noiter", true) ) { countIters = false ; } if ( CommandlineProcessing::isOption( cmdLineArgs, "-et:", "fast", true) ) { fullLoopStat = false ; emitSeqSeg = false ; countIters = false ; withPAPI = false ; enablePostProcessing = true ; } dumpFunc = (showStats ? "ET_LogStats" : "ET_Dump") ; /***********************************************/ /* Invoke ROSE */ /***********************************************/ /* build AST */ SgProject* project = frontend(argc, argv); ROSE_ASSERT(project); if (project->get_fileList().empty() == false) { /* make sure AST is well formed */ AstTests::runAllTests(project); /* set up some needed typedefs for runtime support */ SgGlobal *globalScope = SageInterface::getFirstGlobalScope(project) ; ETtype = buildTypedefDeclaration("ET_Idx_t", buildShortType(), globalScope)->get_type() ; /* insert probes into each function in this file */ Rose_STL_Container<SgNode*> funcDefs = NodeQuery::querySubTree(project, V_SgFunctionDefinition) ; for (Rose_STL_Container<SgNode*>::iterator f_itr = funcDefs.begin(); f_itr != funcDefs.end(); ++f_itr) { SgFunctionDefinition *funcDef = isSgFunctionDefinition(*f_itr) ; ROSE_ASSERT(funcDef); #ifdef ET_DEBUG printf("--- %s ---\n", funcDef->get_qualified_name().str()) ; #endif SgBasicBlock *funcBody = funcDef->get_body() ; if (funcBody == NULL) continue ; /* should be impossible to get here... */ SgFunctionDeclaration *funcDecl = funcDef->get_declaration() ; ROSE_ASSERT(funcDecl); /* don't transform header file code */ if (strstr(funcDecl->get_name().str(), "operator")) continue ; #ifdef ET_DEBUG printf("--- %s ---\n", funcDecl->get_name().str()) ; #endif int loopCount = 0 ; /* used to create local variable names */ int segCount = 0 ; TransformFunction(funcDecl, funcBody, funcBody, &loopCount, &segCount) ; if (loopCount != 0) { loopTransformApplied = true ; } } SgFunctionDeclaration *mainFunc = SageInterface::findMain(project) ; if (countIters == false && (loopTransformApplied || mainFunc != NULL)) { SageInterface::attachArbitraryText(globalScope, std::string("#define ET_NO_COUNT_ITERS 1\n")) ; } /* files containing at least one loop require run-time support */ if (loopTransformApplied) { SageInterface::attachArbitraryText(globalScope, std::string("#include \"ETrt.h\"\n")) ; } /* fold run-time support code into file containing main() */ if (mainFunc != NULL) { SgFunctionDefinition *mainFuncDef = mainFunc->get_definition() ; /* include ETrt.c just before main() in this file */ if (!fullLoopStat) { SageInterface::attachArbitraryText(globalScope, std::string("#define ET_SIMPLE_LOOP_STATS 1\n") ); } if (enablePostProcessing) { SageInterface::attachArbitraryText(globalScope, std::string("#define ET_POST_PROCESS_SEQ_TO_LOOP 1\n") ); } if (withPAPI) { SageInterface::attachArbitraryText(globalScope, std::string("#define ET_PAPI 1\n\n") ); } SageInterface::attachArbitraryText(globalScope, std::string("#include \"ETrt.c\"\n") ); if (withPAPI) { /* Insert PAPI initialization code at top of main */ SgBasicBlock *mainBody = mainFuncDef->get_body() ; Rose_STL_Container<SgNode*> blockStmts = NodeQuery::querySubTree(mainBody, V_SgStatement, AstQueryNamespace::ChildrenOnly) ; for (Rose_STL_Container<SgNode*>::iterator s_itr = blockStmts.begin(); s_itr != blockStmts.end(); ++s_itr) { SgStatement *stmt = isSgStatement(*s_itr) ; ROSE_ASSERT(stmt); /* skip variable declarations */ if (isSgDeclarationStatement(stmt)) continue ; SgExprStatement *initCall = buildFunctionCallStmt( SgName("ET_Init"), buildVoidType(), buildExprListExp(), mainFuncDef->get_body()) ; stmt->get_scope()->insert_statement(stmt, initCall) ; break ; } } /* insert finalization code at end of main() */ Rose_STL_Container<SgNode*> retStmts = NodeQuery::querySubTree(mainFunc, V_SgReturnStmt) ; if (retStmts.size() > 0) { for (Rose_STL_Container<SgNode*>::iterator r_itr = retStmts.begin(); r_itr != retStmts.end(); ++r_itr) { SgReturnStmt *ret = isSgReturnStmt(*r_itr) ; ROSE_ASSERT(ret); SgExprStatement *sanityCall = buildFunctionCallStmt( SgName("ET_SanityCheck"), buildVoidType(), buildExprListExp(), mainFuncDef->get_body()) ; ret->get_scope()->insert_statement(ret, sanityCall) ; SgExprStatement *logStatCall = buildFunctionCallStmt( SgName(dumpFunc), buildVoidType(), buildExprListExp(), mainFuncDef->get_body()) ; ret->get_scope()->insert_statement(ret, logStatCall) ; } } else { SgExprStatement *sanityCall = buildFunctionCallStmt( SgName("ET_SanityCheck"), buildVoidType(), buildExprListExp(), mainFuncDef->get_body()) ; mainFuncDef->get_body()->append_statement(sanityCall) ; SgExprStatement *logStatCall = buildFunctionCallStmt( SgName(dumpFunc), buildVoidType(), buildExprListExp(), mainFuncDef->get_body()) ; mainFuncDef->get_body()->append_statement(logStatCall) ; } } } /* make sure AST is well formed */ AstTests::runAllTests(project); // generateDOT (*project); return backend(project); }
// 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; }