00001
00015 #include <OpenAnalysis/ICFG/ManagerICFG.hpp>
00016 #include <OpenAnalysis/Utils/Util.hpp>
00017 #include <OpenAnalysis/Utils/OutputBuilderDOT.hpp>
00018
00019 static bool debug = false;
00020
00021 namespace OA {
00022 namespace ICFG {
00023
00024
00027 ManagerICFGStandard::ManagerICFGStandard(OA_ptr<ICFGIRInterface> _ir)
00028 : mIR(_ir)
00031 {
00032 OA_DEBUG_CTRL_MACRO("DEBUG_ManagerICFGStandard:ALL", debug);
00033 }
00034
00035 bool ManagerICFGStandard::stmt_has_call(StmtHandle stmt)
00036 {
00037 bool callflag = false;
00038 OA_ptr<IRCallsiteIterator> callsiteItPtr = mIR->getCallsites(stmt);
00039 for ( ; callsiteItPtr->isValid(); ++(*callsiteItPtr)) {
00040 CallHandle call = callsiteItPtr->current();
00041 OA_ptr<ProcHandleIterator> procIter;
00042 procIter = mCallGraph->getCalleeProcIter(call);
00043 for ( ; procIter->isValid(); ++(*procIter)) {
00044 ProcHandle proc = procIter->current();
00045 if (debug) {
00046 std::cout << "called proc = "
00047 << mIR->toString(proc) << std::endl;
00048 }
00049 if (proc != ProcHandle(0)) {
00050 callflag = true;
00051 }
00052 }
00053 }
00054 return callflag;
00055 }
00056
00057 StmtHandle
00058 ManagerICFGStandard::get_call_stmt(OA_ptr<CFG::Node> cfgNode)
00059 {
00060
00061 OA_ptr<StmtHandleIterator> stmtIter;
00062 stmtIter = cfgNode->getNodeStatementsIterator();
00063 for ( ; stmtIter->isValid(); (*stmtIter)++ ) {
00064 StmtHandle stmt = stmtIter->current();
00065 if ( stmt_has_call(stmt) ) {
00066 return stmt;
00067 }
00068 }
00069 return StmtHandle(0);
00070 }
00071
00072 OA_ptr<Node> ManagerICFGStandard::create_icfg_node(
00073 OA_ptr<ICFG> icfg, ProcHandle proc, NodeType pType,
00074 OA_ptr<CFG::Node> cfgNode)
00075 {
00076 OA_ptr<Node> icfgNode;
00077 icfgNode = new Node(icfg, proc, pType, cfgNode);
00078 icfg->addNode(icfgNode);
00079 mCFGNodeToICFGNode[cfgNode] = icfgNode;
00080 return icfgNode;
00081 }
00082
00086 OA_ptr<Node>
00087 ManagerICFGStandard::handle_call_node(OA_ptr<ICFG> icfg,
00088 ProcHandle proc, OA_ptr<CFG::Node> cfgNodeNew,
00089 OA_ptr<Node> prevICFGNode,
00090 OA_ptr<Node>& firstICFGNode,
00091 std::list<ProcHandle>& worklist)
00092 {
00093 OA_ptr<Node> callICFGNode;
00094 OA_ptr<Edge> icfgEdge;
00095 StmtHandle stmt = get_call_stmt(cfgNodeNew);
00096
00097
00098 firstICFGNode = callICFGNode
00099 = create_icfg_node(icfg,proc,CALL_NODE,cfgNodeNew);
00100
00101
00102 if (!prevICFGNode.ptrEqual(0)) {
00103 icfgEdge = new Edge(icfg,
00104 prevICFGNode, callICFGNode, CFLOW_EDGE, CallHandle(0));
00105 icfg->addEdge(icfgEdge);
00106 }
00107
00108
00109 OA_ptr<CFG::Node> emptyNode;
00110 emptyNode = new CFG::Node;
00111 prevICFGNode = create_icfg_node(icfg,proc,RETURN_NODE,emptyNode);
00112
00113
00114
00115
00116
00117
00118
00119
00120 OA_ptr<IRCallsiteIterator>
00121 callsiteIt = mIR->getCallsites(stmt);
00122 CallHandle call;
00123 for ( ; callsiteIt->isValid(); ++(*callsiteIt)) {
00124 call = callsiteIt->current();
00125 }
00126 icfgEdge = new Edge(icfg,
00127 callICFGNode, prevICFGNode, CALL_RETURN_EDGE, call);
00128 icfg->addEdge(icfgEdge);
00129
00130
00131
00132 OA_ptr<IRCallsiteIterator>
00133 callsiteItPtr = mIR->getCallsites(stmt);
00134 for ( ; callsiteItPtr->isValid(); ++(*callsiteItPtr)) {
00135 CallHandle call = callsiteItPtr->current();
00136 OA_ptr<ProcHandleIterator> procIter;
00137 procIter = mCallGraph->getCalleeProcIter(call);
00138 for ( ; procIter->isValid(); ++(*procIter)) {
00139 ProcHandle callee = procIter->current();
00140 if (callee==ProcHandle(0)) { continue; }
00141 worklist.push_back(callee);
00142
00143 OA_ptr<CFG::CFGInterface> calleeCFGInterface
00144 = mEachCFG->getCFGResults(callee);
00145 OA_ptr<CFG::CFG> calleeCFG
00146 = calleeCFGInterface.convert<CFG::CFG>();
00147
00148 OA_ptr<CFG::NodeInterface> temp
00149 = calleeCFG->getEntry();
00150 OA_ptr<CFG::Node> entryNode
00151 = temp.convert<CFG::Node>();
00152 temp = calleeCFG->getExit();
00153 OA_ptr<CFG::Node> exitNode
00154 = temp.convert<CFG::Node>();
00155
00156 if (mCFGNodeToICFGNode[entryNode].ptrEqual(0)) {
00157 mCFGNodeToICFGNode[entryNode]
00158 = new Node(icfg, callee, ENTRY_NODE, entryNode);
00159 icfg->addNode(mCFGNodeToICFGNode[entryNode]);
00160 }
00161 if (mCFGNodeToICFGNode[exitNode].ptrEqual(0)) {
00162 mCFGNodeToICFGNode[exitNode]
00163 = new Node(icfg, callee, EXIT_NODE, exitNode);
00164 icfg->addNode(mCFGNodeToICFGNode[exitNode]);
00165 }
00166
00167
00168 icfgEdge = new Edge(icfg, callICFGNode,
00169 mCFGNodeToICFGNode[entryNode],
00170 CALL_EDGE, call);
00171 icfg->addEdge(icfgEdge);
00172
00173
00174 icfgEdge = new Edge(icfg,
00175 mCFGNodeToICFGNode[exitNode],
00176 prevICFGNode, RETURN_EDGE, call);
00177 icfg->addEdge(icfgEdge);
00178
00179 }
00180
00181 }
00182
00183 return prevICFGNode;
00184 }
00185
00186 OA_ptr<std::list<OA_ptr<CFG::Node> > >
00187 ManagerICFGStandard::break_out_calls(OA_ptr<CFG::Node> cfgNode)
00188 {
00189 OA_ptr<std::list<OA_ptr<CFG::Node> > > retval;
00190 retval = new std::list<OA_ptr<CFG::Node> >;
00191
00192 OA_ptr<CFG::Node> prevNode;
00193 prevNode = new CFG::Node;
00194
00195
00196
00197
00198
00199 OA_ptr<StmtHandleIterator> stmtIter;
00200 stmtIter = cfgNode->getNodeStatementsIterator();
00201 for ( ; stmtIter->isValid(); (*stmtIter)++ ) {
00202 StmtHandle stmt = stmtIter->current();
00203 if ( stmt_has_call(stmt) ) {
00204 if (prevNode->size() > 0) {
00205 retval->push_back(prevNode);
00206 prevNode = new CFG::Node;
00207 }
00208 prevNode->add(stmt);
00209 retval->push_back(prevNode);
00210 prevNode = new CFG::Node;
00211 } else {
00212 prevNode->add(stmt);
00213 }
00214 }
00215 retval->push_back(prevNode);
00216
00217 return retval;
00218 }
00219
00223 OA_ptr<ICFG> ManagerICFGStandard::performAnalysis(
00224 OA_ptr<IRProcIterator> procIter,
00225 OA_ptr<CFG::EachCFGInterface> eachCFG,
00226 OA_ptr<CallGraph::CallGraphInterface> cGraph)
00227 {
00228 OA_ptr<Edge> icfgEdge;
00229 OA_ptr<ICFG> icfg; icfg = new ICFG();
00230
00231
00232 mEachCFG = eachCFG;
00233 mCallGraph = cGraph;
00234
00235
00236
00237
00238
00239 std::map<OA_ptr<Node>,
00240 std::set<OA_ptr<CFG::Node> > > edgeMap;
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266 std::list<ProcHandle> worklist;
00267 std::set<ProcHandle> alreadyVisited;
00268 for ( procIter->reset(); procIter->isValid(); (*procIter)++ ) {
00269 worklist.push_back(procIter->current());
00270 }
00271
00272
00273 while ( ! worklist.empty() ) {
00274
00275
00276 ProcHandle proc = worklist.front();
00277 worklist.pop_front();
00278 if (alreadyVisited.find(proc)!=alreadyVisited.end()) {
00279 continue;
00280 } else {
00281 alreadyVisited.insert(proc);
00282 }
00283
00284
00285 OA_ptr<CFG::CFGInterface> cfgInterface = eachCFG->getCFGResults(proc);
00286
00287
00288 OA_ptr<CFG::CFG> cfg = cfgInterface.convert<CFG::CFG>();
00289 if (debug) {
00290 std::cout << "\n\n\n--- cfg" << std::endl;
00291 cfg->output(*mIR);
00292
00293 OA::OA_ptr<OA::OutputBuilder> outBuild;
00294 outBuild = new OA::OutputBuilderDOT;
00295 cfg->configOutput(outBuild);
00296 cfg->output(*mIR);
00297 std::cout << "\n\n\n";
00298
00299
00300
00301 }
00302
00303
00304 OA_ptr<DGraph::NodesIteratorInterface> cfgNodeIter
00305 = cfg->getNodesIterator();
00306 for ( ; cfgNodeIter->isValid(); (*cfgNodeIter)++ ) {
00307 OA_ptr<DGraph::NodeInterface> dNode = cfgNodeIter->current();
00308 OA_ptr<CFG::Node> cfgNode = dNode.convert<CFG::Node>();
00309
00310 if (debug) {
00311 std::cout << "cfgNode = ";
00312
00313 }
00314
00315
00316 OA_ptr<StmtHandleIterator> stmtIter;
00317 stmtIter = cfgNode->getNodeStatementsIterator();
00318 bool callflag = false;
00319 for ( ; stmtIter->isValid(); (*stmtIter)++ ) {
00320 StmtHandle stmt = stmtIter->current();
00321 if (debug) { std::cout << "stmt = "
00322 << mIR->toString(stmt) << std::endl;}
00323 if ( stmt_has_call(stmt) ) {
00324 callflag = true;
00325 if (debug) { std::cout << "\tcallflag = true" << std::endl;}
00326 }
00327 }
00328
00329
00330 if (callflag) {
00331
00332
00333 OA_ptr<std::list<OA_ptr<CFG::Node> > > newCFGList
00334 = break_out_calls(cfgNode);
00335 std::list<OA_ptr<CFG::Node> >::iterator newCFGNodeIter;
00336 newCFGNodeIter = newCFGList->begin();
00337
00338
00339
00340 OA_ptr<CFG::Node> firstCFGNode = *newCFGNodeIter;
00341 if (debug) {
00342 std::cout << "firstCFGNode = ";
00343
00344 }
00345 OA_ptr<Node> firstICFGNode, prevICFGNode;
00346
00347 if ( get_call_stmt(firstCFGNode) != StmtHandle(0) ) {
00348 prevICFGNode = handle_call_node(icfg, proc, firstCFGNode,
00349 prevICFGNode, firstICFGNode,
00350 worklist);
00351
00352 } else if (firstCFGNode->size() > 0) {
00353 firstICFGNode = create_icfg_node(icfg,proc,CFLOW_NODE,
00354 firstCFGNode);
00355
00356 prevICFGNode = firstICFGNode;
00357 }
00358
00359 if (debug) {
00360 std::cout << "firstICFGNode = ";
00361
00362 }
00363
00364
00365 OA_ptr<DGraph::NodesIteratorInterface> predIter
00366 = cfgNode->getSourceNodesIterator();
00367 for ( ; predIter->isValid(); (*predIter)++ ) {
00368 OA_ptr<DGraph::NodeInterface> dNode = predIter->current();
00369 OA_ptr<CFG::Node> predNode = dNode.convert<CFG::Node>();
00370
00371
00372 edgeMap[firstICFGNode].insert(predNode);
00373 }
00374
00375
00376 newCFGNodeIter++;
00377 for ( ; newCFGNodeIter!=newCFGList->end(); newCFGNodeIter++ )
00378 {
00379 OA_ptr<CFG::Node> cfgNodeNew = *newCFGNodeIter;
00380
00381
00382 if ( get_call_stmt(cfgNodeNew) != StmtHandle(0) ) {
00383 prevICFGNode = handle_call_node(icfg, proc, cfgNodeNew,
00384 prevICFGNode, firstICFGNode,
00385 worklist);
00386
00387
00388 } else if (cfgNodeNew->size() > 0) {
00389
00390 OA_ptr<Node> currICFGNode;
00391 currICFGNode
00392 = create_icfg_node(icfg,proc,CFLOW_NODE,cfgNodeNew);
00393
00394
00395 icfgEdge = new Edge(icfg,
00396 prevICFGNode, currICFGNode, CFLOW_EDGE,
00397 CallHandle(0));
00398 icfg->addEdge(icfgEdge);
00399
00400 prevICFGNode = currICFGNode;
00401 }
00402
00403 }
00404
00405
00406
00407
00408 mCFGNodeToICFGNode[cfgNode] = prevICFGNode;
00409
00410
00411 } else {
00412 OA_ptr<Node> icfgNode;
00413 if (mCFGNodeToICFGNode[cfgNode].ptrEqual(0)) {
00414 if (cfg->getEntry() == cfgNode) {
00415 icfgNode = create_icfg_node(icfg,proc,ENTRY_NODE,cfgNode);
00416 } else if (cfg->getExit() == cfgNode) {
00417 icfgNode = create_icfg_node(icfg,proc,EXIT_NODE,cfgNode);
00418 } else {
00419 icfgNode = create_icfg_node(icfg,proc,CFLOW_NODE,cfgNode);
00420 }
00421 } else {
00422 icfgNode = mCFGNodeToICFGNode[cfgNode];
00423 }
00424
00425 OA_ptr<DGraph::NodesIteratorInterface> predIter
00426 = cfgNode->getSourceNodesIterator();
00427 for ( ; predIter->isValid(); (*predIter)++ ) {
00428 OA_ptr<DGraph::NodeInterface> dNode = predIter->current();
00429 OA_ptr<CFG::Node> predNode = dNode.convert<CFG::Node>();
00430
00431
00432 edgeMap[icfgNode].insert(predNode);
00433 }
00434 }
00435
00436 }
00437
00438
00439 }
00440
00441
00442 std::map<OA_ptr<Node>,
00443 std::set<OA_ptr<CFG::Node> > >::iterator mapIter;
00444 for (mapIter=edgeMap.begin(); mapIter!=edgeMap.end(); mapIter++ ) {
00445 OA_ptr<Node> icfgNode = mapIter->first;
00446 std::set<OA_ptr<CFG::Node> >& nodeSet = mapIter->second;
00447 std::set<OA_ptr<CFG::Node> >::iterator nodeIter;
00448 for (nodeIter=nodeSet.begin(); nodeIter!=nodeSet.end(); nodeIter++) {
00449 icfgEdge = new Edge(icfg,
00450 mCFGNodeToICFGNode[*nodeIter],
00451 icfgNode, CFLOW_EDGE, CallHandle(0));
00452 icfg->addEdge(icfgEdge);
00453 }
00454 }
00455
00456 return icfg;
00457 }
00458
00459
00460 }
00461 }