LabelSet Labeler::getLabelSet(set<SgNode*>& nodeSet) { LabelSet lset; for(set<SgNode*>::iterator i=nodeSet.begin();i!=nodeSet.end();++i) { lset.insert(getLabel(*i)); } return lset; }
LabelSet LabelSet::operator+(LabelSet& s2) { LabelSet result; result=*this; for(LabelSet::iterator i2=s2.begin();i2!=s2.end();++i2) result.insert(*i2); return result; }
LabelSet Flow::targetLabels() { LabelSet s; for(Flow::iterator i=begin();i!=end();++i) { Edge e=*i; s.insert(e.target); } return s; }
LabelSet Flow::sourceLabels() { LabelSet s; for(Flow::iterator i=begin();i!=end();++i) { Edge e=*i; s.insert(e.source); } return s; }
LabelSet TransitionGraph::labelSetOfIoOperations(InputOutput::OpType op) { LabelSet lset; // the target node records the effect of the edge-operation on the source node. for(TransitionGraph::iterator i=begin(); i!=end(); ++i) { if((*i)->target->io.op==op) { lset.insert((*i)->source->label()); } } return lset; }
LabelSet CFAnalysis::functionEntryLabels(Flow& flow) { LabelSet resultSet; LabelSet nodeLabels; nodeLabels=flow.nodeLabels(); for(LabelSet::iterator i=nodeLabels.begin();i!=nodeLabels.end();++i) { if(labeler->isFunctionEntryLabel(*i)) resultSet.insert(*i); } return resultSet; }
LabelSet CFAnalysis::setOfInitialLabelsOfStmtsInBlock(SgNode* node) { LabelSet ls; if(node==0) return ls; if(!isSgStatement(node)) { cerr<<"ERROR: "<<node->class_name()<<endl; } size_t len=node->get_numberOfTraversalSuccessors(); for(size_t i=0;i<len;++i) { SgNode* childNode=node->get_traversalSuccessorByIndex(i); ls.insert(initialLabel(childNode)); } return ls; }
// MS: will possibly be replaced with an implementation from the BOOST graph library LabelSet Flow::reachableNodesButNotBeyondTargetNode(Label start, Label target) { LabelSet reachableNodes; LabelSet toVisitSet=succ(start); size_t oldSize=0; size_t newSize=0; do { LabelSet newToVisitSet; for(LabelSet::iterator i=toVisitSet.begin();i!=toVisitSet.end();++i) { LabelSet succSet=succ(*i); for(LabelSet::iterator j=succSet.begin();j!=succSet.end();++j) { if(reachableNodes.find(*j)==reachableNodes.end()) newToVisitSet.insert(*j); } } toVisitSet=newToVisitSet; oldSize=reachableNodes.size(); reachableNodes+=toVisitSet; newSize=reachableNodes.size(); } while(oldSize!=newSize); return reachableNodes; }
LabelSet CFAnalysis::finalLabels(SgNode* node) { assert(node); assert(labeler->isLabelRelevantNode(node)); LabelSet finalSet; // special case of incExpr in SgForStatement if(SgNodeHelper::isForIncExpr(node)) { finalSet.insert(labeler->getLabel(node)); return finalSet; } // special case of function call if(SgNodeHelper::Pattern::matchFunctionCall(node)) { if(SgNodeHelper::Pattern::matchReturnStmtFunctionCallExp(node)) { finalSet.insert(labeler->functionCallReturnLabel(node)+1); // special case of function call in return-stmt } else { finalSet.insert(labeler->functionCallReturnLabel(node)); } return finalSet; } switch (node->variantT()) { // function declarations inside basic block case V_SgFunctionDeclaration: cerr<<"Error: icfg construction: function declarations are not associated with a label."<<endl; exit(1); //finalSet.insert(labeler->getLabel(node)); //return finalSet; case V_SgFunctionDefinition: { SgBasicBlock* body=isSgFunctionDefinition(node)->get_body(); return finalLabels(body); } case V_SgBreakStmt: case V_SgContinueStmt: return finalSet; case V_SgReturnStmt: return finalSet; case V_SgNullStatement: case V_SgPragmaDeclaration: case V_SgLabelStatement: case V_SgInitializedName: case V_SgVariableDeclaration: case V_SgDefaultOptionStmt: case V_SgCaseOptionStmt: case V_SgClassDeclaration: finalSet.insert(labeler->getLabel(node)); return finalSet; case V_SgExprStatement: { finalSet.insert(labeler->getLabel(node)); return finalSet; } case V_SgIfStmt: { SgNode* nodeTB=SgNodeHelper::getTrueBranch(node); LabelSet finalSetTB=finalLabels(nodeTB); finalSet+=finalSetTB; if(SgNode* nodeFB=SgNodeHelper::getFalseBranch(node)) { LabelSet finalSetFB=finalLabels(nodeFB); finalSet+=finalSetFB; } else { // in case of an empty else branch the cond node becomes the final node SgNode* condNode=SgNodeHelper::getCond(node); finalSet.insert(labeler->getLabel(condNode)); } return finalSet; } case V_SgForStatement: case V_SgDoWhileStmt: case V_SgWhileStmt: { SgNode* condNode=SgNodeHelper::getCond(node); finalSet.insert(labeler->getLabel(condNode)); set<SgNode*> breakNodes=SgNodeHelper::LoopRelevantBreakStmtNodes(node); LabelSet lset=labeler->getLabelSet(breakNodes); finalSet+=lset; //cout << finalSet.toString() << endl; return finalSet; } case V_SgBasicBlock: { #if 0 finalSet.insert(labeler->blockEndLabel(node)); return finalSet; #else if(SgNodeHelper::numChildren(node)>0) { SgNode* lastNode=SgNodeHelper::getLastOfBlock(node); LabelSet s=finalLabels(lastNode); finalSet+=s; } else { // empty basic block finalSet.insert(initialLabel(node)); } return finalSet; #endif } case V_SgFunctionCallExp: finalSet.insert(labeler->functionCallReturnLabel(node)); return finalSet; case V_SgGotoStatement: { // for the goto statement (as special case) the final set is empty. This allows all other functions // operate correctly even in the presence of gotos. The edge for 'goto label' is created as part // of the semantics of goto (and does not *require* the final labels). return finalSet; } case V_SgSwitchStatement: { // 1) add all break statements, 2) add final label of last stmt (emulating a break) set<SgNode*> breakNodes=SgNodeHelper::LoopRelevantBreakStmtNodes(node); LabelSet lset=labeler->getLabelSet(breakNodes); finalSet+=lset; //cout << finalSet.toString() << endl; // very last case in switch (not necessarily default), if it does not contain a break has still a final label. // if it is a break it will still be the last label. If it is a goto it will not have a final label (which is correct). SgSwitchStatement* switchStmt=isSgSwitchStatement(node); SgStatement* body=switchStmt->get_body(); SgBasicBlock* block=isSgBasicBlock(body); if(!block) { cerr<<"Error: CFAnalysis::finalLabels: body of switch is not a basic block. Unknown structure."<<endl; exit(1); } const SgStatementPtrList& stmtList=block->get_statements(); // TODO: revisit this case: this should work for all stmts in the body, when break has its own label as final label. if(stmtList.size()>0) { SgNode* lastStmt=stmtList.back(); SgStatement* lastStmt2=getCaseOrDefaultBodyStmt(lastStmt); LabelSet lsetLastStmt=finalLabels(lastStmt2); finalSet+=lsetLastStmt; } else { cerr<<"Error: CFAnalysis::finalLabels: body of switch is empty."<<endl; exit(1); } return finalSet; } default: cerr << "Error: Unknown node in CFAnalysis::finalLabels: "<<node->sage_class_name()<<endl; exit(1); } }
LabelSet CFAnalyzer::finalLabels(SgNode* node) { assert(node); assert(labeler->isLabelRelevantNode(node)); LabelSet finalSet; // special case of incExpr in SgForStatement if(SgNodeHelper::isForIncExpr(node)) { finalSet.insert(labeler->getLabel(node)); return finalSet; } // special case of function call if(SgNodeHelper::Pattern::matchFunctionCall(node)) { if(SgNodeHelper::Pattern::matchReturnStmtFunctionCallExp(node)) { finalSet.insert(labeler->functionCallReturnLabel(node)+1); // special case of function call in return-stmt } else { finalSet.insert(labeler->functionCallReturnLabel(node)); } return finalSet; } switch (node->variantT()) { // function declarations inside basic block case V_SgFunctionDeclaration: finalSet.insert(labeler->getLabel(node)); return finalSet; case V_SgFunctionDefinition: { SgBasicBlock* body=isSgFunctionDefinition(node)->get_body(); return finalLabels(body); } case V_SgBreakStmt: return finalSet; case V_SgReturnStmt: return finalSet; case V_SgNullStatement: case V_SgLabelStatement: case V_SgInitializedName: case V_SgVariableDeclaration: finalSet.insert(labeler->getLabel(node)); return finalSet; case V_SgExprStatement: { finalSet.insert(labeler->getLabel(node)); return finalSet; } case V_SgIfStmt: { SgNode* nodeTB=SgNodeHelper::getTrueBranch(node); LabelSet finalSetTB=finalLabels(nodeTB); finalSet+=finalSetTB; if(SgNode* nodeFB=SgNodeHelper::getFalseBranch(node)) { LabelSet finalSetFB=finalLabels(nodeFB); finalSet+=finalSetFB; } else { // in case of an empty else branch the cond node becomes the final node SgNode* condNode=SgNodeHelper::getCond(node); finalSet.insert(labeler->getLabel(condNode)); } return finalSet; } case V_SgForStatement: case V_SgDoWhileStmt: case V_SgWhileStmt: { SgNode* condNode=SgNodeHelper::getCond(node); finalSet.insert(labeler->getLabel(condNode)); set<SgNode*> breakNodes=SgNodeHelper::LoopRelevantBreakStmtNodes(node); LabelSet lset=labeler->getLabelSet(breakNodes); finalSet+=lset; cout << finalSet.toString() << endl; return finalSet; } case V_SgBasicBlock: { if(SgNodeHelper::numChildren(node)>0) { SgNode* lastNode=SgNodeHelper::getLastOfBlock(node); LabelSet s=finalLabels(lastNode); finalSet+=s; } else { // empty basic block finalSet.insert(initialLabel(node)); } return finalSet; } case V_SgFunctionCallExp: finalSet.insert(labeler->functionCallReturnLabel(node)); return finalSet; default: cerr << "Error: Unknown node in CodeThorn::CFAnalyzer::finalLabels: "<<node->sage_class_name()<<endl; exit(1); } }