Flow CFAnalysis::WhileAndDoWhileLoopFlow(SgNode* node, Flow edgeSet, EdgeType edgeTypeParam1, EdgeType edgeTypeParam2) { if(!(isSgWhileStmt(node) || isSgDoWhileStmt(node))) { throw SPRAY::Exception("Error: WhileAndDoWhileLoopFlow: unsupported loop construct."); } SgNode* condNode=SgNodeHelper::getCond(node); Label condLabel=getLabel(condNode); SgNode* bodyNode=SgNodeHelper::getLoopBody(node); assert(bodyNode); Edge edge=Edge(condLabel,EDGE_TRUE,initialLabel(bodyNode)); edge.addType(edgeTypeParam1); Flow flowB=flow(bodyNode); LabelSet finalSetB=finalLabels(bodyNode); edgeSet+=flowB; edgeSet.insert(edge); // back edges in while (forward edges in do-while) for(LabelSet::iterator i=finalSetB.begin();i!=finalSetB.end();++i) { Edge e; if(SgNodeHelper::isCond(labeler->getNode(*i))) { e=Edge(*i,EDGE_FALSE,condLabel); e.addType(edgeTypeParam2); } else { e=Edge(*i,edgeTypeParam2,condLabel); } edgeSet.insert(e); } return edgeSet; }
void CFAnalyzer::intraInterFlow(Flow& flow, InterFlow& interFlow) { for(InterFlow::iterator i=interFlow.begin();i!=interFlow.end();++i) { if((*i).entry==Labeler::NO_LABEL && (*i).exit==Labeler::NO_LABEL) { Edge externalEdge=Edge((*i).call,EDGE_EXTERNAL,(*i).callReturn); flow.insert(externalEdge); } else { Edge callEdge=Edge((*i).call,EDGE_CALL,(*i).entry); Edge callReturnEdge=Edge((*i).exit,EDGE_CALLRETURN,(*i).callReturn); Edge localEdge=Edge((*i).call,EDGE_LOCAL,(*i).callReturn); flow.insert(callEdge); flow.insert(callReturnEdge); flow.insert(localEdge); } } }
Flow Flow::operator+(Flow& s2) { Flow result; result=*this; for(Flow::iterator i2=s2.begin();i2!=s2.end();++i2) result.insert(*i2); return result; }
SPRAY::Flow Flow::reverseFlow() { Flow reverseFlow; for(Flow::iterator i=begin();i!=end();++i) { reverseFlow.insert(Edge((*i).target,(*i).getTypes(),(*i).source)); } return reverseFlow; }
Flow CFAnalysis::controlDependenceGraph(Flow& controlFlow) { LabelSet condLabels=conditionLabels(controlFlow); LabelSet targetLabels; Flow controlDependenceEdges; for(LabelSet::iterator i=condLabels.begin();i!=condLabels.end();++i) { SgNode* condition=getLabeler()->getNode(*i); cerr<<"DEBUG: cond:"<<condition->class_name()<<endl; SgNode* stmt=SgNodeHelper::getParent(condition); cerr<<"DEBUG: stmt:"<<stmt->class_name()<<endl; // while/dowhile/for if(SgNodeHelper::isLoopCond(condition)) { SgNode* loopBody=SgNodeHelper::getLoopBody(stmt); cerr<<"DEBUG: loopBody:"<<loopBody->class_name()<<endl; LabelSet loopBodyInitLabels=setOfInitialLabelsOfStmtsInBlock(loopBody); targetLabels=loopBodyInitLabels; } // if if(isSgIfStmt(stmt)) { SgNode* trueBranch=SgNodeHelper::getTrueBranch(stmt); LabelSet trueBranchInitLabels=setOfInitialLabelsOfStmtsInBlock(trueBranch); SgNode* falseBranch=SgNodeHelper::getFalseBranch(stmt); LabelSet falseBranchInitLabels=setOfInitialLabelsOfStmtsInBlock(falseBranch); targetLabels=trueBranchInitLabels+falseBranchInitLabels; } for(LabelSet::iterator j=targetLabels.begin();j!=targetLabels.end();++j) { controlDependenceEdges.insert(Edge(*i,EDGE_FORWARD,*j)); } } return controlDependenceEdges; }
int CFAnalyzer::reduceBlockBeginNodes(Flow& flow) { LabelSet labs=flow.nodeLabels(); int cnt=0; for(LabelSet::iterator i=labs.begin();i!=labs.end();++i) { if(isSgBasicBlock(getNode(*i))) { cnt++; Flow inFlow=flow.inEdges(*i); Flow outFlow=flow.outEdges(*i); // multiple out-edges not supported yet assert(outFlow.size()<=1); /* description of essential operations: * inedges: (n_i,b) * outedge: (b,n2) * remove(n_i,b) * remove(b,n2) * insert(n1,n2) */ for(Flow::iterator initer=inFlow.begin();initer!=inFlow.end();++initer) { Edge e1=*initer; Edge e2=*outFlow.begin(); Edge newEdge=Edge(e1.source,e1.types(),e2.target); flow.erase(e1); flow.erase(e2); flow.insert(newEdge); } } } return cnt; }
int CFAnalysis::reduceNode(Flow& flow, Label lab) { Flow inFlow=flow.inEdges(lab); Flow outFlow=flow.outEdges(lab); /* description of essential operations: * inedges: (n_i,b) * outedge: (b,n2) * remove(n_i,b) * remove(b,n2) * insert(n1,n2) */ if(inFlow.size()==0 && outFlow.size()==0) return 0; if(inFlow.size()==0 || outFlow.size()==0) { Flow edges=inFlow+outFlow; flow.deleteEdges(edges); return 1; } for(Flow::iterator initer=inFlow.begin();initer!=inFlow.end();++initer) { for(Flow::iterator outiter=outFlow.begin();outiter!=outFlow.end();++outiter) { Edge e1=*initer; Edge e2=*outiter; Edge newEdge=Edge(e1.source,e1.types(),e2.target); flow.erase(e1); flow.erase(e2); flow.insert(newEdge); } } return 1; }
Flow Flow::edgesOfType(EdgeType edgeType) { Flow flow; for(Flow::iterator i=begin();i!=end();++i) { if((*i).isType(edgeType)) flow.insert(*i); } flow.setDotOptionDisplayLabel(_dotOptionDisplayLabel); flow.setDotOptionDisplayStmt(_dotOptionDisplayStmt); return flow; }
Flow Flow::inEdges(Label label) { Flow flow; for(Flow::iterator i=begin();i!=end();++i) { if((*i).target==label) flow.insert(*i); } flow.setDotOptionDisplayLabel(_dotOptionDisplayLabel); flow.setDotOptionDisplayStmt(_dotOptionDisplayStmt); return flow; }
Flow Flow::outEdges(Label label) { Flow flow; if(!_boostified) { for(Flow::iterator i=begin();i!=end();++i) { if((*i).source==label) flow.insert(*i); } } else { typedef graph_traits<FlowGraph> GraphTraits; // typename property_map<FlowGraph, vertex_index_t>::type // index = get(vertex_index, _flowGraph); GraphTraits::out_edge_iterator out_i, out_end; GraphTraits::edge_descriptor e; for (tie(out_i, out_end) = out_edges(label.getId(), _flowGraph); out_i != out_end; ++out_i) { e = *out_i; Label src = source(e, _flowGraph), targ = target(e, _flowGraph); flow.insert(Edge(src,_flowGraph[e],targ)); } } flow.setDotOptionDisplayLabel(_dotOptionDisplayLabel); flow.setDotOptionDisplayStmt(_dotOptionDisplayStmt); return flow; }
Flow* ParProTransitionGraph::toFlowEnumerateStates(NumberGenerator& numGen) { Flow* result = new Flow(); unordered_map<const ParProEState*, Label> eState2Label; for (EStateTransitionMap::iterator i=_outEdges.begin(); i!=_outEdges.end(); i++) { for (ParProTransitions::iterator k=i->second.begin(); k!=i->second.end(); k++) { const ParProEState* source = (*k).source; if (eState2Label.find(source) == eState2Label.end()) { eState2Label[source] = Label(numGen.next()); } const ParProEState* target = (*k).target; if (eState2Label.find(target) == eState2Label.end()) { eState2Label[target] = Label(numGen.next()); } Edge e(eState2Label[source], eState2Label[target]); e.setAnnotation(k->edge.getAnnotation()); result->insert(e); } } return result; }
int CFAnalysis::reduceBlockBeginNodes(Flow& flow) { LabelSet labs=flow.nodeLabels(); int cnt=0; for(LabelSet::iterator i=labs.begin();i!=labs.end();++i) { //cout<<"Checking label: "<<(*i)<<" node: "<<getNode(*i)<<" code:"<<getNode(*i)->unparseToString()<<endl; if(isSgBasicBlock(getNode(*i))) { #if 1 cnt+=reduceNode(flow,*i); #else cnt++; Flow inFlow=flow.inEdges(*i); Flow outFlow=flow.outEdges(*i); // multiple out-edges not supported yet assert(outFlow.size()<=1); /* description of essential operations: * inedges: (n_i,b) * outedge: (b,n2) * remove(n_i,b) * remove(b,n2) * insert(n1,n2) */ for(Flow::iterator initer=inFlow.begin();initer!=inFlow.end();++initer) { Edge e1=*initer; Edge e2=*outFlow.begin(); Edge newEdge=Edge(e1.source,e1.types(),e2.target); flow.erase(e1); flow.erase(e2); flow.insert(newEdge); } #endif } } return cnt; }
Flow CFAnalysis::flow(SgNode* node) { assert(node); Flow edgeSet; if(node==0) return edgeSet; if(isSgFunctionDeclaration(node)) { return edgeSet; } if(isSgProject(node)||isSgFileList(node)||isSgGlobal(node)||isSgSourceFile(node)) { RoseAst ast(node); Flow tmpEdgeSet; // search for all functions and union flow for all functions for(RoseAst::iterator i=ast.begin();i!=ast.end();++i) { // schroder3 (2016-07-29): Added " && !isSgTemplateFunctionDefinition(*i)" to prevent // SgTemplateFunctionDefinition nodes from being added to the ICFG. SgTemplateFunctionDefinitions // are never called because they are only used in template declarations (SgTemplateDeclaration) // (and not in template instantiation or specialization declarations (SgTemplateInstantiationFunctionDecl)). // Template instantiation/ specialization declarations have "normal" SgFunctionDefinition nodes as // corresponding definition. Even in case of an implicit instantiation of an implicit specialization ROSE // creates a SgTemplateInstantiationFunctionDecl and copies the body of the SgTemplateFunctionDefinition // to a new SgFunctionDefinition and uses the SgFunctionDefinition as definition. if(isSgFunctionDefinition(*i) && !isSgTemplateFunctionDefinition(*i)) { // schroder3 (2016-07-12): We can not skip the children of a function definition // because there might be a member function definition inside the function definition. // Example: // int main() { // class A { // public: // void mf() { // int i = 2; // } // }; // } // // i.skipChildrenOnForward(); //cout << "STATUS: Generating flow for function "<<SgNodeHelper::getFunctionName(*i)<<endl; tmpEdgeSet=flow(*i); edgeSet+=tmpEdgeSet; } } return edgeSet; } // special case of function call pattern if(SgNodeHelper::Pattern::matchFunctionCall(node)) { // we add the 'local' edge when intraInter flow is computed (it may also be an 'external' edge) #if 0 Label callLabel=labeler->functionCallLabel(node); Label callReturnLabel=labeler->functionCallReturnLabel(node); edgeSet.insert(Edge(callLabel,EDGE_LOCAL,callReturnLabel)); #endif // add special case edge for callReturn to returnNode SgReturnStmt(SgFunctionCallExp) // edge: SgFunctionCallExp.callReturn->init(SgReturnStmt) if(SgNodeHelper::Pattern::matchReturnStmtFunctionCallExp(node)) { Label callReturnLabel=labeler->functionCallReturnLabel(node); Label returnStmtLabel=labeler->functionCallReturnLabel(node)+1; edgeSet.insert(Edge(callReturnLabel,EDGE_FORWARD,returnStmtLabel)); } return edgeSet; } switch (node->variantT()) { case V_SgFunctionDefinition: { SgBasicBlock* body=isSgFunctionDefinition(node)->get_body(); Edge edge=Edge(labeler->functionEntryLabel(node),EDGE_FORWARD,initialLabel(body)); edgeSet.insert(edge); Flow bodyFlow=flow(body); edgeSet+=bodyFlow; /* add explicitly edge from last stmt of function to exit-node not that a return at the end of a function is *not* represented in a ROSE AST. if return does not exist, we need to add an explicit edge from end of function to exit since we create this edge with the computed final node a branch with returns in all branches is maintained properly. this edge is identical if we have some other branches. Because we maintain the edges as an edge-set this operation is always OK. */ #if 0 LabelSet funFinalLabels=finalLabels(node); #else LabelSet funFinalLabels=finalLabels(body); #endif for(LabelSet::iterator i=funFinalLabels.begin();i!=funFinalLabels.end();++i) { Edge explicitEdge=Edge(*i,EDGE_FORWARD,labeler->functionExitLabel(node)); if(SgNodeHelper::isLoopCond(labeler->getNode(*i))) { explicitEdge.addType(EDGE_FALSE); } if(SgNodeHelper::isCond(labeler->getNode(*i))) { if(SgIfStmt* ifStmt=isSgIfStmt(labeler->getNode(*i)->get_parent())) { if(!SgNodeHelper::getFalseBranch(ifStmt)) { // MS: 07/02/2014: in case of empty if-false branch (at end of function), FALSE must be added to explicit node (only if-false can be empty) explicitEdge.addType(EDGE_FALSE); } } } edgeSet.insert(explicitEdge); } return edgeSet; } case V_SgReturnStmt: { SgNode* funcDef=SgNodeHelper::correspondingSgFunctionDefinition(node); if(!funcDef) cerr << "Error: No corresponding function for ReturnStmt found."<<endl; assert(isSgFunctionDefinition(funcDef)); Edge edge=Edge(getLabel(node),EDGE_FORWARD,labeler->functionExitLabel(funcDef)); edgeSet.insert(edge); return edgeSet; } case V_SgBreakStmt: case V_SgInitializedName: case V_SgVariableDeclaration: case V_SgNullStatement: case V_SgPragmaDeclaration: case V_SgLabelStatement: case V_SgExprStatement: case V_SgDefaultOptionStmt: case V_SgCaseOptionStmt: case V_SgClassDeclaration: return edgeSet; case V_SgContinueStmt: { SgNode* loopStmt=correspondingLoopConstruct(node); if(isSgWhileStmt(loopStmt)) { // target is condition node SgNode* targetNode=SgNodeHelper::getCond(loopStmt); ROSE_ASSERT(targetNode); Edge edge=Edge(getLabel(node),EDGE_BACKWARD,getLabel(targetNode)); edgeSet.insert(edge); } else if(isSgDoWhileStmt(loopStmt)) { // target is condition node SgNode* targetNode=SgNodeHelper::getCond(loopStmt); ROSE_ASSERT(targetNode); Edge edge=Edge(getLabel(node),EDGE_FORWARD,getLabel(targetNode)); edgeSet.insert(edge); } else if(isSgForStatement(loopStmt)) { // target is increment expr SgExpression* incExp=SgNodeHelper::getForIncExpr(loopStmt); if(!incExp) throw SPRAY::Exception("CFAnalysis: for-loop: empty incExpr not supported."); SgNode* targetNode=incExp; ROSE_ASSERT(targetNode); Edge edge=Edge(getLabel(node),EDGE_FORWARD,getLabel(targetNode)); edgeSet.insert(edge); } else { throw SPRAY::Exception("CFAnalysis: continue in unknown loop construct (not while,do-while, or for)."); } return edgeSet; } case V_SgIfStmt: { SgNode* nodeC=SgNodeHelper::getCond(node); Label condLabel=getLabel(nodeC); SgNode* nodeTB=SgNodeHelper::getTrueBranch(node); Edge edgeTB=Edge(condLabel,EDGE_TRUE,initialLabel(nodeTB)); edgeTB.addType(EDGE_FORWARD); edgeSet.insert(edgeTB); Flow flowTB=flow(nodeTB); edgeSet+=flowTB; if(SgNode* nodeFB=SgNodeHelper::getFalseBranch(node)) { Flow flowFB=flow(nodeFB); Edge edgeFB=Edge(condLabel,EDGE_FALSE,initialLabel(nodeFB)); edgeFB.addType(EDGE_FORWARD); edgeSet.insert(edgeFB); edgeSet+=flowFB; } return edgeSet; } case V_SgGotoStatement: { SgGotoStatement* gotoStmt=isSgGotoStatement(node); SgLabelStatement* targetSgLabelStmt=gotoStmt->get_label(); ROSE_ASSERT(targetSgLabelStmt); // note that the target label is not an element of the finalLabels set. Label targetLabel=labeler->getLabel(targetSgLabelStmt); edgeSet.insert(Edge(initialLabel(node),EDGE_FORWARD,targetLabel)); return edgeSet; } case V_SgSwitchStatement: { SgNode* nodeC=SgNodeHelper::getCond(node); Label condLabel=getLabel(nodeC); SgSwitchStatement* switchStmt=isSgSwitchStatement(node); SgStatement* body=switchStmt->get_body(); SgBasicBlock* block=isSgBasicBlock(body); if(!block) { cerr<<"Error: CFAnalysis::flow: body of switch is not a basic block. Unknown structure."<<endl; exit(1); } SgStatementPtrList& stmtList=block->get_statements(); ROSE_ASSERT(stmtList.size()>0); SgStatement* prevCaseStmtBody=0; for(SgStatementPtrList::iterator i=stmtList.begin(); i!=stmtList.end(); ++i) { // TODO: revisit this case: this should work for all stmts in the body, when break has its own label as final label. //SgDefaultOptionStmt if(isSgCaseOptionStmt(*i)||isSgDefaultOptionStmt(*i)) { Label caseStmtLab=labeler->getLabel(*i); SgStatement* caseBody=getCaseOrDefaultBodyStmt(*i); ROSE_ASSERT(caseBody); Label caseBodyLab=labeler->getLabel(caseBody); edgeSet.insert(Edge(condLabel,EDGE_FORWARD,caseStmtLab)); edgeSet.insert(Edge(caseStmtLab,EDGE_FORWARD,initialLabel(caseBody))); Flow flowStmt=flow(caseBody); edgeSet+=flowStmt; { // create edges from other case stmts to the next case that have no break at the end. if(prevCaseStmtBody) { LabelSet finalBodyLabels=finalLabels(prevCaseStmtBody); for(LabelSet::iterator i=finalBodyLabels.begin();i!=finalBodyLabels.end();++i) { if(!isSgBreakStmt(labeler->getNode(*i))) { edgeSet.insert(Edge(*i,EDGE_FORWARD,caseBodyLab)); } } } } prevCaseStmtBody=caseBody; } else { cerr<<"Error: control flow: stmt in switch is not a case or default stmt. Not supported yet."<<endl; exit(1); } } return edgeSet; } case V_SgWhileStmt: return WhileAndDoWhileLoopFlow(node,edgeSet,EDGE_FORWARD,EDGE_BACKWARD); case V_SgDoWhileStmt: return WhileAndDoWhileLoopFlow(node,edgeSet,EDGE_BACKWARD,EDGE_FORWARD); case V_SgBasicBlock: { size_t len=node->get_numberOfTraversalSuccessors(); if(len==0) { // do not generate edge to blockEndLabel //Edge edge=Edge(labeler->blockBeginLabel(node),EDGE_FORWARD,labeler->blockEndLabel(node)); //edgeSet.insert(edge); return edgeSet; } else { if(len==1) { SgNode* onlyStmt=node->get_traversalSuccessorByIndex(0); Flow onlyFlow=flow(onlyStmt); edgeSet+=onlyFlow; } else { for(size_t i=0;i<len-1;++i) { SgNode* childNode1=node->get_traversalSuccessorByIndex(i); SgNode* childNode2=node->get_traversalSuccessorByIndex(i+1); Flow flow12=flow(childNode1,childNode2); edgeSet+=flow12; } } } SgNode* firstStmt=node->get_traversalSuccessorByIndex(0); Edge edge1=Edge(labeler->blockBeginLabel(node),EDGE_FORWARD,initialLabel(firstStmt)); edgeSet.insert(edge1); ROSE_ASSERT(len>=1); // do not generate edges to blockEndLabel #if 0 SgNode* lastStmt=node->get_traversalSuccessorByIndex(len-1); ROSE_ASSERT(isSgStatement(lastStmt)); LabelSet lastStmtFinalLabels=finalLabels(lastStmt); for(LabelSet::iterator i=lastStmtFinalLabels.begin();i!=lastStmtFinalLabels.end();++i) { Edge edge2=Edge(*i,EDGE_FORWARD,labeler->blockEndLabel(node)); edgeSet.insert(edge2); } #endif return edgeSet; } case V_SgForStatement: { SgStatementPtrList& stmtPtrList=SgNodeHelper::getForInitList(node); int len=stmtPtrList.size(); if(len==0) { // empty initializer list (hence, an initialization stmt cannot be initial stmt of for) cout << "INFO: for-stmt: initializer-list is empty."<<endl; cerr << "Error: empty for-stmt initializer not supported yet."<<endl; exit(1); } assert(len>0); SgNode* lastNode=0; if(len==1) { SgNode* onlyStmt=*stmtPtrList.begin(); Flow onlyFlow=flow(onlyStmt); edgeSet+=onlyFlow; lastNode=onlyStmt; } else { assert(stmtPtrList.size()>=2); for(SgStatementPtrList::iterator i=stmtPtrList.begin(); i!=stmtPtrList.end(); ++i) { SgNode* node1=*i; SgStatementPtrList::iterator i2=i; i2++; SgNode* node2=*i2; Flow flow12=flow(node1,node2); edgeSet+=flow12; i2++; if(i2==stmtPtrList.end()) { lastNode=node2; break; } } } SgNode* condNode=SgNodeHelper::getCond(node); if(!condNode) throw SPRAY::Exception("Error: for-loop: empty condition not supported yet."); Flow flowInitToCond=flow(lastNode,condNode); edgeSet+=flowInitToCond; Label condLabel=getLabel(condNode); SgNode* bodyNode=SgNodeHelper::getLoopBody(node); assert(bodyNode); Edge edge=Edge(condLabel,EDGE_TRUE,initialLabel(bodyNode)); edge.addType(EDGE_FORWARD); Flow flowB=flow(bodyNode); edgeSet+=flowB; edgeSet.insert(edge); // Increment Expression: SgExpression* incExp=SgNodeHelper::getForIncExpr(node); if(!incExp) throw SPRAY::Exception("Error: for-loop: empty incExpr not supported yet."); ROSE_ASSERT(incExp); Label incExpLabel=getLabel(incExp); ROSE_ASSERT(incExpLabel!=Labeler::NO_LABEL); // Edges from final labels of for body to the increment expression: LabelSet finalSetB=finalLabels(bodyNode); for(LabelSet::iterator i=finalSetB.begin();i!=finalSetB.end();++i) { Edge edgeToIncExpr=Edge(*i,EDGE_FORWARD,incExpLabel); if(SgNodeHelper::isCond(labeler->getNode(*i))) { edgeToIncExpr.addType(EDGE_FALSE); } edgeSet.insert(edgeToIncExpr); } // Edge from increment expression back to condition: Edge backwardEdge = Edge(incExpLabel,EDGE_BACKWARD,condLabel); edgeSet.insert(backwardEdge); return edgeSet; } default: throw SPRAY::Exception("Unknown node in CFAnalysis::flow: "+node->class_name()+" Problemnode: "+node->unparseToString()); } }
int CFAnalysis::reduceNode(Flow& flow, Label lab) { Flow inFlow=flow.inEdges(lab); Flow outFlow=flow.outEdges(lab); // edge type cleanup // if true and false edge exist, remove both (merging true and false branches to a single branch) // if forward and backward exist, remove forward (we are not removing the cycle) /* description of essential operations: * inedges: (n_i,b) * outedge: (b,n2) * remove(n_i,b) * remove(b,n2) * insert(n1,n2) */ if(inFlow.size()==0 && outFlow.size()==0) { return 0; } else if(inFlow.size()>0 && outFlow.size()>0) { set<Edge> toErase; set<Edge> toInsert; for(Flow::iterator initer=inFlow.begin();initer!=inFlow.end();++initer) { for(Flow::iterator outiter=outFlow.begin();outiter!=outFlow.end();++outiter) { Edge e1=*initer; Edge e2=*outiter; // preserve edge annotations of ingoing and outgoing edges EdgeTypeSet unionEdgeTypeSet; EdgeTypeSet edgeTypeSet1=(*initer).types(); unionEdgeTypeSet.insert(edgeTypeSet1.begin(),edgeTypeSet1.end()); EdgeTypeSet edgeTypeSet2=(*outiter).types(); // only copy an edge annotation in the outgoing edge if it is // not a true-annotation or a false-annotation for(EdgeTypeSet::iterator i=edgeTypeSet2.begin();i!=edgeTypeSet2.end();++i) { if(*i!=EDGE_TRUE && *i!=EDGE_FALSE) { unionEdgeTypeSet.insert(*i); } } if(unionEdgeTypeSet.find(EDGE_TRUE)!=unionEdgeTypeSet.end() && unionEdgeTypeSet.find(EDGE_FALSE)!=unionEdgeTypeSet.end()) { unionEdgeTypeSet.erase(EDGE_TRUE); unionEdgeTypeSet.erase(EDGE_FALSE); } if(unionEdgeTypeSet.find(EDGE_FORWARD)!=unionEdgeTypeSet.end() && unionEdgeTypeSet.find(EDGE_BACKWARD)!=unionEdgeTypeSet.end()) { unionEdgeTypeSet.erase(EDGE_FORWARD); // keep backward edge annotation } Edge newEdge=Edge(e1.source(),unionEdgeTypeSet,e2.target()); toErase.insert(e1); toErase.insert(e2); if(e1.source()!=e2.target()) { toInsert.insert(newEdge); } } } for(set<Edge>::iterator i=toErase.begin();i!=toErase.end();++i) { flow.erase(*i); } for(set<Edge>::iterator i=toInsert.begin();i!=toInsert.end();++i) { flow.insert(*i); } return 1; } else if(inFlow.size()>0) { for(Flow::iterator initer=inFlow.begin();initer!=inFlow.end();++initer) { Edge e1=*initer; flow.erase(e1); } return 1; } else if(outFlow.size()>0) { for(Flow::iterator outiter=outFlow.begin();outiter!=outFlow.end();++outiter) { Edge e2=*outiter; flow.erase(e2); } return 1; } return 0; }
Flow CFAnalyzer::flow(SgNode* node) { assert(node); Flow edgeSet; if(node==0) return edgeSet; if(isSgFunctionDeclaration(node)) { return edgeSet; } if(isSgProject(node)||isSgFileList(node)||isSgGlobal(node)||isSgSourceFile(node)) { RoseAst ast(node); Flow tmpEdgeSet; // search for all functions and union flow for all functions for(RoseAst::iterator i=ast.begin();i!=ast.end();++i) { if(isSgFunctionDefinition(*i)) { i.skipChildrenOnForward(); cout << "STATUS: Generating flow for function "<<SgNodeHelper::getFunctionName(*i)<<endl; tmpEdgeSet=flow(*i); edgeSet+=tmpEdgeSet; } } return edgeSet; } // special case of function call pattern if(SgNodeHelper::Pattern::matchFunctionCall(node)) { // we add the 'local' edge when intraInter flow is computed (it may also be an 'external' edge) #if 0 Label callLabel=labeler->functionCallLabel(node); Label callReturnLabel=labeler->functionCallReturnLabel(node); edgeSet.insert(Edge(callLabel,EDGE_LOCAL,callReturnLabel)); #endif // add special case edge for callReturn to returnNode SgReturnStmt(SgFunctionCallExp) // edge: SgFunctionCallExp.callReturn->init(SgReturnStmt) if(SgNodeHelper::Pattern::matchReturnStmtFunctionCallExp(node)) { Label callReturnLabel=labeler->functionCallReturnLabel(node); Label returnStmtLabel=labeler->functionCallReturnLabel(node)+1; edgeSet.insert(Edge(callReturnLabel,EDGE_FORWARD,returnStmtLabel)); } return edgeSet; } switch (node->variantT()) { case V_SgFunctionDefinition: { SgBasicBlock* body=isSgFunctionDefinition(node)->get_body(); Edge edge=Edge(labeler->functionEntryLabel(node),EDGE_FORWARD,initialLabel(body)); edgeSet.insert(edge); Flow bodyFlow=flow(body); edgeSet+=bodyFlow; /* add explicitly edge from last stmt of function to exit-node not that a return at the end of a function is *not* represented in a ROSE AST. if return does not exist, we need to add an explicit edge from end of function to exit since we create this edge with the computed final node a branch with returns in all branches is maintained properly. this edge is identical if we have some other branches. Because we maintain the edges as an edge-set this operation is always OK. */ LabelSet funFinalLabels=finalLabels(node); for(LabelSet::iterator i=funFinalLabels.begin();i!=funFinalLabels.end();++i) { Edge explicitEdge=Edge(*i,EDGE_FORWARD,labeler->functionExitLabel(node)); if(SgNodeHelper::isLoopCond(labeler->getNode(*i))) { explicitEdge.addType(EDGE_FALSE); } edgeSet.insert(explicitEdge); } return edgeSet; } case V_SgReturnStmt: { SgNode* funcDef=SgNodeHelper::correspondingSgFunctionDefinition(node); if(!funcDef) cerr << "Error: No corresponding function for ReturnStmt found."<<endl; assert(isSgFunctionDefinition(funcDef)); Edge edge=Edge(getLabel(node),EDGE_FORWARD,labeler->functionExitLabel(funcDef)); edgeSet.insert(edge); return edgeSet; } case V_SgBreakStmt: case V_SgInitializedName: case V_SgVariableDeclaration: case V_SgNullStatement: case V_SgLabelStatement: case V_SgExprStatement: return edgeSet; case V_SgIfStmt: { SgNode* nodeC=SgNodeHelper::getCond(node); Label condLabel=getLabel(nodeC); SgNode* nodeTB=SgNodeHelper::getTrueBranch(node); Edge edgeTB=Edge(condLabel,EDGE_TRUE,initialLabel(nodeTB)); edgeTB.addType(EDGE_FORWARD); edgeSet.insert(edgeTB); Flow flowTB=flow(nodeTB); edgeSet+=flowTB; if(SgNode* nodeFB=SgNodeHelper::getFalseBranch(node)) { Flow flowFB=flow(nodeFB); Edge edgeFB=Edge(condLabel,EDGE_FALSE,initialLabel(nodeFB)); edgeFB.addType(EDGE_FORWARD); edgeSet.insert(edgeFB); edgeSet+=flowFB; } return edgeSet; } case V_SgWhileStmt: return WhileAndDoWhileLoopFlow(node,edgeSet,EDGE_FORWARD,EDGE_BACKWARD); case V_SgDoWhileStmt: return WhileAndDoWhileLoopFlow(node,edgeSet,EDGE_BACKWARD,EDGE_FORWARD); case V_SgBasicBlock: { size_t len=node->get_numberOfTraversalSuccessors(); if(len==0) { return edgeSet; } else { if(len==1) { SgNode* onlyStmt=node->get_traversalSuccessorByIndex(0); Flow onlyFlow=flow(onlyStmt); edgeSet+=onlyFlow; } else { for(size_t i=0;i<len-1;++i) { SgNode* childNode1=node->get_traversalSuccessorByIndex(i); SgNode* childNode2=node->get_traversalSuccessorByIndex(i+1); Flow flow12=flow(childNode1,childNode2); edgeSet+=flow12; } } } SgNode* firstStmt=node->get_traversalSuccessorByIndex(0); Edge edge=Edge(getLabel(node),EDGE_FORWARD,initialLabel(firstStmt)); edgeSet.insert(edge); return edgeSet; } case V_SgForStatement: { SgStatementPtrList& stmtPtrList=SgNodeHelper::getForInitList(node); int len=stmtPtrList.size(); if(len==0) { // empty initializer list (hence, an initialization stmt cannot be initial stmt of for) cout << "INFO: for-stmt: initializer-list is empty."<<endl; cerr << "Error: empty for-stmt initializer not supported yet."<<endl; exit(1); } assert(len>0); SgNode* lastNode=0; if(len==1) { SgNode* onlyStmt=*stmtPtrList.begin(); Flow onlyFlow=flow(onlyStmt); edgeSet+=onlyFlow; lastNode=onlyStmt; } else { assert(stmtPtrList.size()>=2); for(SgStatementPtrList::iterator i=stmtPtrList.begin(); i!=stmtPtrList.end(); ++i) { SgNode* node1=*i; SgStatementPtrList::iterator i2=i; i2++; SgNode* node2=*i2; Flow flow12=flow(node1,node2); edgeSet+=flow12; i2++; if(i2==stmtPtrList.end()) { lastNode=node2; break; } } } SgNode* condNode=SgNodeHelper::getCond(node); if(!condNode) throw "Error: for-loop: empty condition not supported yet."; Flow flowInitToCond=flow(lastNode,condNode); edgeSet+=flowInitToCond; Label condLabel=getLabel(condNode); SgNode* bodyNode=SgNodeHelper::getLoopBody(node); assert(bodyNode); Edge edge=Edge(condLabel,EDGE_TRUE,initialLabel(bodyNode)); edge.addType(EDGE_FORWARD); Flow flowB=flow(bodyNode); LabelSet finalSetB=finalLabels(bodyNode); edgeSet+=flowB; edgeSet.insert(edge); // back edges for(LabelSet::iterator i=finalSetB.begin();i!=finalSetB.end();++i) { SgExpression* incExp=SgNodeHelper::getForIncExpr(node); if(!incExp) throw "Error: for-loop: empty incExpr not supported yet."; assert(incExp); Label incExpLabel=getLabel(incExp); assert(incExpLabel!=Labeler::NO_LABEL); Edge e1,e2; if(SgNodeHelper::isCond(labeler->getNode(*i))) { e1=Edge(*i,EDGE_FALSE,incExpLabel); e1.addType(EDGE_FORWARD); e2=Edge(incExpLabel,EDGE_BACKWARD,condLabel); } else { e1=Edge(*i,EDGE_FORWARD,incExpLabel); e2=Edge(incExpLabel,EDGE_BACKWARD,condLabel); } edgeSet.insert(e1); edgeSet.insert(e2); } return edgeSet; } default: cerr << "Error: Unknown node in CodeThorn::CFAnalyzer::flow: "<<node->sage_class_name()<<endl; cerr << "Problemnode: "<<node->unparseToString()<<endl; exit(1); } }
int CFAnalysis::reduceNode(Flow& flow, Label lab) { Flow inFlow=flow.inEdges(lab); Flow outFlow=flow.outEdges(lab); EdgeTypeSet unionEdgeTypeSets; for(Flow::iterator i=inFlow.begin();i!=inFlow.end();++i) { EdgeTypeSet edgeTypeSet=(*i).types(); unionEdgeTypeSets.insert(edgeTypeSet.begin(),edgeTypeSet.end()); } for(Flow::iterator i=outFlow.begin();i!=outFlow.end();++i) { EdgeTypeSet edgeTypeSet=(*i).types(); unionEdgeTypeSets.insert(edgeTypeSet.begin(),edgeTypeSet.end()); } // edge type cleanup // if true and false edge exist, remove both (merging true and false branches to a single branch) // if forward and backward exist, remove backward (we are removing a cycle) if(unionEdgeTypeSets.find(EDGE_TRUE)!=unionEdgeTypeSets.end() && unionEdgeTypeSets.find(EDGE_FALSE)!=unionEdgeTypeSets.end()) { unionEdgeTypeSets.erase(EDGE_TRUE); unionEdgeTypeSets.erase(EDGE_FALSE); } if(unionEdgeTypeSets.find(EDGE_FORWARD)!=unionEdgeTypeSets.end() && unionEdgeTypeSets.find(EDGE_BACKWARD)!=unionEdgeTypeSets.end()) { unionEdgeTypeSets.erase(EDGE_FORWARD); unionEdgeTypeSets.erase(EDGE_BACKWARD); } /* description of essential operations: * inedges: (n_i,b) * outedge: (b,n2) * remove(n_i,b) * remove(b,n2) * insert(n1,n2) */ if(inFlow.size()==0 && outFlow.size()==0) { return 0; } else if(inFlow.size()>0 && outFlow.size()>0) { for(Flow::iterator initer=inFlow.begin();initer!=inFlow.end();++initer) { for(Flow::iterator outiter=outFlow.begin();outiter!=outFlow.end();++outiter) { Edge e1=*initer; Edge e2=*outiter; // preserve edge annotations of ingoing and outgoing edges Edge newEdge=Edge(e1.source,unionEdgeTypeSets,e2.target); flow.erase(e1); flow.erase(e2); flow.insert(newEdge); } return 1; } } else if(inFlow.size()>0) { for(Flow::iterator initer=inFlow.begin();initer!=inFlow.end();++initer) { Edge e1=*initer; flow.erase(e1); } return 1; } else if(outFlow.size()>0) { for(Flow::iterator outiter=outFlow.begin();outiter!=outFlow.end();++outiter) { Edge e2=*outiter; flow.erase(e2); } return 1; } return 0; }