int main(int argc, char* argv[]) { cout << "INIT: Parsing and creating AST."<<endl; SgProject* sageProject = frontend(argc,argv); VariableIdMapping variableIdMapping; variableIdMapping.computeVariableSymbolMapping(sageProject); Labeler labeler(sageProject,&variableIdMapping); CFAnalyzer cfanalyzer(&labeler); RDAnalyzer rdAnalyzer(&cfanalyzer); rdAnalyzer.initialize(); rdAnalyzer.run(); return 0; }
void checkLargeSets() { VariableIdMapping variableIdMapping; VariableId var_x=variableIdMapping.createUniqueTemporaryVariableId("x"); AType::ConstIntLattice i; using namespace AType; set<CppCapsuleConstIntLattice> cilSet; cilSet.insert(CppCapsuleConstIntLattice(ConstIntLattice(Bot()))); cilSet.insert(CppCapsuleConstIntLattice(ConstIntLattice(Top()))); for(int i=-10;i<10;i++) { cilSet.insert(CppCapsuleConstIntLattice(ConstIntLattice(i))); } check("integer set: bot,-10, ... ,+10,top",cilSet.size()==22); // 1+20+1 }
void printCodeStatistics(SgNode* root) { SgProject* project=isSgProject(root); VariableIdMapping variableIdMapping; variableIdMapping.computeVariableSymbolMapping(project); VariableIdSet setOfUsedVars=AnalysisAbstractionLayer::usedVariablesInsideFunctions(project,&variableIdMapping); DeadCodeElimination dce; cout<<"----------------------------------------------------------------------"<<endl; cout<<"Statistics:"<<endl; cout<<"Number of empty if-statements: "<<dce.listOfEmptyIfStmts(root).size()<<endl; cout<<"Number of functions : "<<SgNodeHelper::listOfFunctionDefinitions(project).size()<<endl; cout<<"Number of global variables : "<<SgNodeHelper::listOfGlobalVars(project).size()<<endl; cout<<"Number of used variables : "<<setOfUsedVars.size()<<endl; cout<<"----------------------------------------------------------------------"<<endl; cout<<"VariableIdMapping-size : "<<variableIdMapping.getVariableIdSet().size()<<endl; cout<<"----------------------------------------------------------------------"<<endl; }
VariableValuePair FIConstAnalysis::analyzeVariableDeclaration(SgVariableDeclaration* decl,VariableIdMapping& varIdMapping) { SgNode* initName0=decl->get_traversalSuccessorByIndex(1); // get-InitializedName if(initName0) { if(SgInitializedName* initName=isSgInitializedName(initName0)) { SgSymbol* initDeclVar=initName->search_for_symbol_from_symbol_table(); assert(initDeclVar); VariableId initDeclVarId=varIdMapping.variableId(initDeclVar); SgInitializer* initializer=initName->get_initializer(); SgAssignInitializer* assignInitializer=0; if(initializer && (assignInitializer=isSgAssignInitializer(initializer))) { if(detailedOutput) cout << "initializer found:"<<endl; SgExpression* rhs=assignInitializer->get_operand_i(); assert(rhs); return VariableValuePair(initDeclVarId,analyzeAssignRhs(rhs)); } else { if(detailedOutput) cout << "no initializer (OK)."<<endl; return VariableValuePair(initDeclVarId,AType::Top()); } } else { cerr << "Error: in declaration (@initializedName) no variable found ... bailing out."<<endl; exit(1); } } else { cerr << "Error: in declaration: no variable found ... bailing out."<<endl; exit(1); } }
VariableIdSet AnalysisAbstractionLayer::astSubTreeVariables(SgNode* node, VariableIdMapping& vidm) { VariableIdSet vset; RoseAst ast(node); for(RoseAst::iterator i=ast.begin();i!=ast.end();++i) { VariableId vid; // default creates intentionally an invalid id. if(SgVariableDeclaration* varDecl=isSgVariableDeclaration(*i)) { vid=vidm.variableId(varDecl); } else if(SgVarRefExp* varRefExp=isSgVarRefExp(*i)) { vid=vidm.variableId(varRefExp); } else if(SgInitializedName* initName=isSgInitializedName(*i)) { vid=vidm.variableId(initName); } if(vid.isValid()) vset.insert(vid); } return vset; }
void DefUseVarsInfo::addAllArrayElements(SgInitializedName* array_name, VariableIdMapping& vidm, bool def) { assert(array_name); VariableId array_var_id = vidm.variableId(array_name); SgArrayType* array_type = isSgArrayType(array_name->get_type()); if (!array_type) return; int elements = vidm.getArrayElementCount(array_type); if (!elements) elements = vidm.getArrayDimensionsFromInitializer(isSgAggregateInitializer(array_name->get_initializer())); VarsInfo& info = (def ? def_vars_info : use_vars_info); VariableIdTypeInfo sgn_type_info_elem = getVariableIdTypeInfo(array_var_id, vidm); for (int e = 0; e < elements; e++) { VariableId element_id = vidm.variableIdOfArrayElement(array_var_id, e); info.first.insert(VariableIdInfo(element_id, sgn_type_info_elem)); } }
bool FIConstAnalysis::determineVariable(SgNode* node, VariableId& varId, VariableIdMapping& _variableIdMapping) { assert(node); if(SgVarRefExp* varref=isSgVarRefExp(node)) { // found variable //assert(_variableIdMapping); #if 1 SgSymbol* sym=varref->get_symbol(); ROSE_ASSERT(sym); varId=_variableIdMapping.variableId(sym); #else // MS: to investigate: even with the new var-sym-only case this does not work // MS: investigage getSymbolOfVariable varId=_variableIdMapping.variableId(varref); #endif return true; } else { VariableId defaultVarId; varId=defaultVarId; return false; } }
std::string SPRAY::VariableIdSetPrettyPrint::str(VariableIdSet& vset, VariableIdMapping& vidm) { std::ostringstream ostr; ostr << "["; VariableIdSet::iterator it = vset.begin(); for( ; it != vset.end(); ) { ostr << "<" << (*it).toString() << ", " << vidm.variableName(*it) << ">"; it++; if(it != vset.end()) ostr << ", "; } ostr << "]"; return ostr.str(); }
VarConstSetMap FIConstAnalysis::computeVarConstValues(SgProject* project, SgFunctionDefinition* mainFunctionRoot, VariableIdMapping& variableIdMapping) { VarConstSetMap varConstIntMap; VariableIdSet varIdSet=AnalysisAbstractionLayer::usedVariablesInsideFunctions(project,&variableIdMapping); // initialize map such that it is resized to number of variables of interest for(VariableIdSet::iterator i=varIdSet.begin(); i!=varIdSet.end(); ++i) { set<CppCapsuleConstIntLattice> emptySet; varConstIntMap[*i]=emptySet; } cout<<"STATUS: Initialized const map for "<<varConstIntMap.size()<< " variables."<<endl; cout << "STATUS: Number of global variables: "; list<SgVariableDeclaration*> globalVars=SgNodeHelper::listOfGlobalVars(project); cout << globalVars.size()<<endl; VariableIdSet setOfUsedVars=AnalysisAbstractionLayer::usedVariablesInsideFunctions(project,&variableIdMapping); cout << "STATUS: Number of used variables: "<<setOfUsedVars.size()<<endl; #if 0 int filteredVars=0; set<CppCapsuleConstIntLattice> emptySet; for(list<SgVariableDeclaration*>::iterator i=globalVars.begin(); i!=globalVars.end(); ++i) { VariableId globalVarId=variableIdMapping.variableId(*i); if(setOfUsedVars.find(globalVarId)!=setOfUsedVars.end()) { VariableValuePair p=analyzeVariableDeclaration(*i,variableIdMapping); ConstIntLattice varValue=p.varValue; varConstIntMap[p.varId]=emptySet; // create mapping varConstIntMap[p.varId].insert(CppCapsuleConstIntLattice(varValue)); variablesOfInterest.insert(p.varId); //set<CppCapsuleConstIntLattice>& myset=varConstIntMap[p.varId]; } else { filteredVars++; } } cout << "STATUS: Number of filtered variables for initial state: "<<filteredVars<<endl; #endif variablesOfInterest=setOfUsedVars; if(mainFunctionRoot!=0) { determineVarConstValueSet(mainFunctionRoot,variableIdMapping,varConstIntMap); } else { // compute value-sets for entire program (need to cover all functions without inlining) determineVarConstValueSet(project,variableIdMapping,varConstIntMap); } return varConstIntMap; }
VariableIdTypeInfo getVariableIdTypeInfo(VariableId vid, VariableIdMapping& vidm) { SgSymbol* symb = vidm.getSymbol(vid); ROSE_ASSERT(symb); SgType* sgn_type = symb->get_type(); VariableIdTypeInfo sgn_type_info; if(isSgArrayType(sgn_type)) sgn_type_info = arrayType; else if(isSgPointerType(sgn_type)) sgn_type_info = pointerType; else if(isSgReferenceType(sgn_type)) sgn_type_info = referenceType; else if(isSgClassType(sgn_type)) sgn_type_info = classType; else sgn_type_info = variableType; return sgn_type_info; }
std::string DefUseVarsInfo::varsInfoPrettyPrint(VarsInfo& vars_info, VariableIdMapping& vidm) { std::ostringstream oss; oss << "[" << (vars_info.second? "true" : "false") << ", "; oss << "{"; VariableIdInfoMap::iterator it = vars_info.first.begin(); for( ; it != vars_info.first.end(); ) { // oss << "<" << (*it).first.toString() << ", " << vidm.variableName((*it).first) << ", "; oss << "<" << vidm.uniqueShortVariableName((*it).first) << ", " << variableIdTypeInfoToString((*it).second); oss <<">"; it++; if(it != vars_info.first.end()) oss << ", "; } oss << "}"; oss <<"]"; return oss.str(); }
void printResult(VariableIdMapping& variableIdMapping, VarConstSetMap& map) { cout<<"Result:"<<endl; VariableConstInfo vci(&variableIdMapping, &map); for(VarConstSetMap::iterator i=map.begin();i!=map.end();++i) { VariableId varId=(*i).first; //string variableName=variableIdMapping.uniqueShortVariableName(varId); string variableName=variableIdMapping.variableName(varId); set<ConstIntLattice> valueSet=(*i).second; stringstream setstr; setstr<<"{"; for(set<ConstIntLattice>::iterator i=valueSet.begin();i!=valueSet.end();++i) { if(i!=valueSet.begin()) setstr<<","; setstr<<(*i).toString(); } setstr<<"}"; cout<<variableName<<"="<<setstr.str()<<";"; #if 1 cout<<"Range:"<<VariableConstInfo::createVariableValueRangeInfo(varId,map).toString(); cout<<" width: "<<VariableConstInfo::createVariableValueRangeInfo(varId,map).width().toString(); cout<<" top: "<<VariableConstInfo::createVariableValueRangeInfo(varId,map).isTop(); cout<<endl; #endif cout<<" isAny:"<<vci.isAny(varId) <<" isUniqueConst:"<<vci.isUniqueConst(varId) <<" isMultiConst:"<<vci.isMultiConst(varId); if(vci.isUniqueConst(varId)||vci.isMultiConst(varId)) { cout<<" width:"<<vci.width(varId); } else { cout<<" width:unknown"; } cout<<" Test34:"<<vci.isInConstSet(varId,34); cout<<endl; } cout<<"---------------------"<<endl; }
int main( int argc, char * argv[] ) { // If we want this translator to take specific options (beyond those defined // by ROSE) then insert command line processing for new options here. // To better support the stencil specification that might benifit from constant // folding, I have turned this ON is hte frontend. By default it is OFF so that // we can preserve source code as much as possible (original expression trees). // The Stencil DSL can be made to work in eithr setting, but this make sure that // dimension dependent processing of the stencil coeficients will be evaluated // to constants. I will turn this off (and thus use a less blunt axe) when the new // constant expression evaluation in ROSE is fixed to support more general types // than integer expresion (should be done by JP later today). // bool frontendConstantFolding = true; bool frontendConstantFolding = false; // Generate the ROSE AST. SgProject* project = frontend(argc,argv,frontendConstantFolding); ROSE_ASSERT(project != NULL); try { variableIdMapping.computeVariableSymbolMapping(project); } catch(char* str) { cout << "*Exception raised: " << str << endl; } catch(const char* str) { cout << "Exception raised: " << str << endl; } catch(string str) { cout << "Exception raised: " << str << endl; } // variableIdMapping.toStream(cout); #if 1 printf ("variableIdMapping.getVariableIdSet().size() = %zu \n",variableIdMapping.getVariableIdSet().size()); ROSE_ASSERT(variableIdMapping.getVariableIdSet().size() > 0); #endif #if 0 printf ("Exiting as a test after calling variableIdMapping.computeVariableSymbolMapping(project) \n"); ROSE_ASSERT(false); #endif #if 0 printf ("Calling constant folding \n"); ConstantFolding::constantFoldingOptimization(project,false); #if 0 printf ("Exiting as a test after calling ConstantFolding::constantFoldingOptimization() \n"); ROSE_ASSERT(false); #endif #endif // DQ (2/8/2015): Find the associated SgFile so we can restrict processing to the current file. ROSE_ASSERT(project->get_fileList().empty() == false); SgFile* firstFile = project->get_fileList()[0]; ROSE_ASSERT(firstFile != NULL); #if DEBUG_USING_DOT_GRAPHS // generateDOTforMultipleFile(*project); // generateDOT(*project,"_before_transformation"); AstDOTGeneration astdotgen; astdotgen.generateWithinFile(firstFile,DOTGeneration<SgNode*>::TOPDOWNBOTTOMUP,"_before_transformation"); #endif #if DEBUG_USING_DOT_GRAPHS && 1 const int MAX_NUMBER_OF_IR_NODES_TO_GRAPH_FOR_WHOLE_GRAPH = 12000; #endif #if DEBUG_USING_DOT_GRAPHS && 1 // Output an optional graph of the AST (the whole graph, of bounded complexity, when active) generateAstGraph(project,MAX_NUMBER_OF_IR_NODES_TO_GRAPH_FOR_WHOLE_GRAPH,"_before"); #endif // Build the inherited attribute Detection_InheritedAttribute inheritedAttribute; // Define the traversal DetectionTraversal shiftCalculus_DetectionTraversal; #if 1 printf ("Call the Detection traversal starting at the project (root) node of the AST \n"); #endif // Call the traversal starting at the project (root) node of the AST // Detection_SynthesizedAttribute result = shiftCalculus_DetectionTraversal.traverse(project,inheritedAttribute); Detection_SynthesizedAttribute result = shiftCalculus_DetectionTraversal.traverseWithinFile(firstFile,inheritedAttribute); #if 0 printf ("Stencil Operator was transformed: %s \n",result.get_stencilOperatorTransformed() ? "true" : "false"); #endif ROSE_ASSERT(result.get_stencilOperatorTransformed() == false); #if 1 printf ("DONE: Call the Detection traversal starting at the project (root) node of the AST \n"); #endif #if 0 shiftCalculus_DetectionTraversal.display(); #endif #if DEBUG_USING_DOT_GRAPHS // generateDOTforMultipleFile(*project); // generateDOT(*project,"_before_transformation"); AstDOTGeneration astdotgen_2; astdotgen_2.generateWithinFile(firstFile,DOTGeneration<SgNode*>::TOPDOWNBOTTOMUP,"_after_DSL_detection"); #endif #if 0 printf ("Exiting after the initial traversal to detect the stencil useage. \n"); ROSE_ASSERT(false); #endif // Build the inherited attribute StencilEvaluation_InheritedAttribute inheritedAttribute_stencilEval; // Define the traversal // StencilEvaluationTraversal shiftCalculus_StencilEvaluationTraversal(shiftCalculus_DetectionTraversal); StencilEvaluationTraversal shiftCalculus_StencilEvaluationTraversal; #if 1 printf ("Call the StencilEvaluation traversal starting at the project (root) node of the AST \n"); #endif // Call the traversal starting at the project (root) node of the AST // StencilEvaluation_SynthesizedAttribute result_stencilEval = shiftCalculus_StencilEvaluationTraversal.traverse(project,inheritedAttribute_stencilEval); StencilEvaluation_SynthesizedAttribute result_stencilEval = shiftCalculus_StencilEvaluationTraversal.traverseWithinFile(firstFile,inheritedAttribute_stencilEval); #if 0 printf ("Stencil Evaluation was transformed: %s \n",result_stencilEval.get_stencilOperatorTransformed() ? "true" : "false"); #endif ROSE_ASSERT(result_stencilEval.get_stencilOperatorTransformed() == false); #if 1 printf ("DONE: Call the StencilEvaluation traversal starting at the project (root) node of the AST \n"); #endif #if 1 shiftCalculus_StencilEvaluationTraversal.displayStencil("After evaluation of stencil"); #endif #if DEBUG_USING_DOT_GRAPHS // generateDOTforMultipleFile(*project); // generateDOT(*project,"_before_transformation"); AstDOTGeneration astdotgen_3; astdotgen_3.generateWithinFile(firstFile,DOTGeneration<SgNode*>::TOPDOWNBOTTOMUP,"_after_DSL_evaluation"); #endif #if 1 printf ("Call generateStencilCode to generate example code \n"); #endif #if 0 printf ("Exiting after the second traversal to evaluate the stencils. \n"); ROSE_ASSERT(false); #endif // Generate code from stencil data structure. bool generateLowlevelCode = true; generateStencilCode(shiftCalculus_StencilEvaluationTraversal,generateLowlevelCode); #if 1 printf ("DONE: Call generateStencilCode to generate example code \n"); #endif #if 0 printf ("Exiting after call to generateStencilCode() \n"); ROSE_ASSERT(false); #endif // AST consistency tests (optional for users, but this enforces more of our tests) AstTests::runAllTests(project); #if DEBUG_USING_DOT_GRAPHS printf ("Write out the DOT file after the transformation \n"); // generateDOTforMultipleFile(*project,"after_transformation"); generateDOT(*project,"_after_transformation"); printf ("DONE: Write out the DOT file after the transformation \n"); #endif #if DEBUG_USING_DOT_GRAPHS && 0 // Output an optional graph of the AST (the whole graph, of bounded complexity, when active) // const int MAX_NUMBER_OF_IR_NODES_TO_GRAPH_FOR_WHOLE_GRAPH = 10000; generateAstGraph(project,MAX_NUMBER_OF_IR_NODES_TO_GRAPH_FOR_WHOLE_GRAPH,"_after"); #endif // Regenerate the source code but skip the call the to the vendor compiler. return backend(project); }
void checkTypes() { VariableIdMapping variableIdMapping; PState s1; cout << "RUNNING CHECKS:"<<endl; { // check temporary variables (create and delete) VariableId var_tmp=variableIdMapping.createUniqueTemporaryVariableId("tmp"); variableIdMapping.deleteUniqueTemporaryVariableId(var_tmp); } { cout << "------------------------------------------"<<endl; cout << "RUNNING CHECKS FOR BOOLLATTICE TYPE:"<<endl; AType::BoolLattice a; a=true; check("a=true => isTrue",a.isTrue()); AType::BoolLattice b; b=false; check("b=false => isFalse",b.isFalse()); AType::BoolLattice c=a||b; check("c=a||b => c isTrue ",c.isTrue()); AType::Top e; AType::BoolLattice d; d=e; check("Top e; d=e => d isTop",d.isTop()); c=c||d; check("c=c||d: true",c.isTrue()); AType::BoolLattice f=AType::Bot(); d=AType::Bot(); check("d=bot: bot",d.isBot()); check("f=bot: bot",f.isBot()); a=d&&f; check("a=d&&f => a isBot",a.isBot()); f=false; check("f=false => f isFalse",f.isFalse()); a=d&&f; check("a=d&&f: a isFalse (we define it this way)",a.isFalse()); } { cout << "RUNNING CHECKS FOR CONSTINT LATTICE TYPE:"<<endl; AType::ConstIntLattice a; a=true; check("a=true => isTrue",a.isTrue()); check("a=true => !isFalse",!a.isFalse()); AType::ConstIntLattice b; b=false; check("b=false => isFalse",b.isFalse()); check("b=false => !isTrue",!b.isTrue()); AType::ConstIntLattice c=a.operatorOr(b); check("c=a.operatorOr(b): ",c.isTrue()); AType::Top e; AType::ConstIntLattice d; d=e; check("Top e; d=e; d isTop ",d.isTop()); c=c.operatorOr(d); check("c=c.operatorOr(d) => c isTrue ",c.isTrue()); AType::ConstIntLattice f=AType::Bot(); d=AType::Bot(); a=d.operatorAnd(f); check("d=bot;f=bot;a=d.operatorAnd(f); => a isBot",a.isBot()); f=false; a=d.operatorAnd(f); check("f=false; a=d.operatorAnd(f); => a isFalse",a.isFalse()); a=5; check("a=5; a.isTrue()==true",a.isTrue()==true); check("a=5; a.isFalse()==false",a.isFalse()==false); a=0; check("a=0; a.isTrue()==false",a.isTrue()==false); check("a=0; a.isFalse())==true",a.isFalse()==true); } { cout << "------------------------------------------"<<endl; cout << "RUNNING CHECKS FOR CONSTRAINT TYPE:"<<endl; VariableId var_x=variableIdMapping.createUniqueTemporaryVariableId("x"); VariableId var_y=variableIdMapping.createUniqueTemporaryVariableId("y"); cout << "P1"<<endl; Constraint c1(Constraint::EQ_VAR_CONST,var_x,1); cout << "P2"<<endl; Constraint c2(Constraint::NEQ_VAR_CONST,var_y,2); cout << "P3"<<endl; Constraint c3=DISEQUALITYCONSTRAINT; cout << "P4"<<endl; Constraint c4=Constraint(Constraint::EQ_VAR_CONST,var_y,2); cout << "P5"<<endl; ConstraintSet cs; cout << "P6"<<endl; cs.addConstraint(c1); cout << "P7"<<endl; cout << "CS1:"<<cs.toString()<<endl; cs.addConstraint(c2); cout << "CS2:"<<cs.toString()<<endl; check("inserted 2 different constraints, size of constraint set == 3",cs.size()==2); check("c1:constraintExists(EQ_VAR_CONST,x,1) == true",cs.constraintExists(Constraint::EQ_VAR_CONST,var_x,1)); check("c1:constraintExists(NEQ_VAR_CONST,x,1) == false",!cs.constraintExists(Constraint::NEQ_VAR_CONST,var_x,1)); check("c2:constraintExists(NEQ_VAR_CONST,y,2) == true",cs.constraintExists(Constraint::NEQ_VAR_CONST,var_y,2)); check("c3:isDisequality==false",cs.disequalityExists()==false); cout << "CS3:"<<cs.toString()<<endl; cs.addConstraint(c4); cout << "CS4:"<<cs.toString()<<endl; cout << "P8"<<endl; //cout << "CS:"<<cs.toString()<<endl; check("insert y==2; => disequalityExists() == true",cs.disequalityExists()); cout << "P9"<<endl; cs.addConstraint(c3); check("added disequality => disequalityExists() == true",cs.disequalityExists()); check("Disequality exists <=> size()==1",cs.size()==1); check("c1!=c2",c1!=c2); check("c1!=c3",c1!=c3); check("c2!=c3",c2!=c3); { // check for equalities { Constraint c1(Constraint::EQ_VAR_CONST,var_x,1); Constraint c2=Constraint(Constraint::EQ_VAR_CONST,var_y,2); ConstraintSet cs1; cs1.addConstraint(c1); cs1.addConstraint(c2); Constraint c5(Constraint::EQ_VAR_VAR,var_x,var_y); cs1.addConstraint(c5); check("cs1.disequalityExists()==true",cs1.disequalityExists()); } { Constraint c1(Constraint::NEQ_VAR_CONST,var_x,1); Constraint c2=Constraint(Constraint::NEQ_VAR_CONST,var_x,2); Constraint c3=Constraint(Constraint::NEQ_VAR_CONST,var_y,3); ConstraintSet cs1; cs1.addConstraint(c1); cs1.addConstraint(c2); cs1.addConstraint(c3); Constraint c5(Constraint::EQ_VAR_VAR,var_x,var_y); cs1.addConstraint(c5); check("c5:constraintExists(EQ_VAR_VAR,x,y) == true",cs1.constraintExists(Constraint(Constraint::EQ_VAR_VAR,var_x,var_y))); check("c1:constraintExists(EQ_VAR_CONST,x,1) == false",cs1.constraintExists(Constraint::EQ_VAR_CONST,var_x,1)==false); check("c1:constraintExists(NEQ_VAR_CONST,x,1) == true",cs1.constraintExists(Constraint::NEQ_VAR_CONST,var_x,1)==true); check("c1:constraintExists(EQ_VAR_CONST,y,2) == false",cs1.constraintExists(Constraint::EQ_VAR_CONST,var_y,2)==false); check("c1:constraintExists(NEQ_VAR_CONST,y,2) == true",cs1.constraintExists(Constraint::NEQ_VAR_CONST,var_y,2)==true); cs1.removeAllConstraintsOfVar(var_x); cs1.removeAllConstraintsOfVar(var_y); cs1.removeAllConstraintsOfVar(var_x); } } ConstraintSet cs1; cs1.addConstraint(c1); ConstraintSet cs2; cs2.addConstraint(c2); check("cs1!=cs2)",cs1!=cs2); { Constraint c1(Constraint::NEQ_VAR_CONST,var_y,1); Constraint c2(Constraint::NEQ_VAR_CONST,var_y,3); Constraint c3(Constraint::NEQ_VAR_CONST,var_y,5); Constraint c4a(Constraint::EQ_VAR_CONST,var_y,6); Constraint c4b(Constraint::EQ_VAR_CONST,var_y,3); ConstraintSet cs1; ConstraintSet cs2; PState s; cs1.addConstraint(c1); cs1.addConstraint(c2); cs1.addConstraint(c3); cs2.addConstraint(c1); cs2.addConstraint(c3); check("cs1!=cs2",cs1!=cs2); check("!(cs1==cs2)",!(cs1==cs2)); check("!(cs1<cs2)",!(cs1<cs2)); check("cs1>cs2",(cs2<cs1)); EStateSet es; EState es1=EState(1,&s,&cs1); es.processNewOrExisting(es1); EState es2=EState(1,&s,&cs2); es.processNewOrExisting(es2); check("es.size()==2",es.size()==2); { Constraint c5(Constraint::EQ_VAR_CONST,var_y,10); cs1.addConstraint(c5); check("constraintExists(NEQ_VAR_CONST,y,1) == false",cs1.constraintExists(Constraint::NEQ_VAR_CONST,var_y,1)==false); check("constraintExists(NEQ_VAR_CONST,y,3) == false",cs1.constraintExists(Constraint::NEQ_VAR_CONST,var_y,3)==false); check("constraintExists(NEQ_VAR_CONST,y,5) == false",cs1.constraintExists(Constraint::NEQ_VAR_CONST,var_y,5)==false); check("cs1.size()==1",cs1.size()==1); } } } { cout << "------------------------------------------"<<endl; cout << "RUNNING CHECKS FOR CONSTINTLATTICE (formerly CPPCAPSULE):"<<endl; AType::ConstIntLattice cint1(1); check("cint1 == 1",cint1.getIntValue()==1); AType::ConstIntLattice cint2=AType::Top(); AType::ConstIntLattice cint3; cint3=AType::Top(); check("cint2 isTop",cint2.isTop()); check("cint3 isTop",cint3.isTop()); check("!(cint1 == cint3)",!(cint1==cint3)); // strictly weak ordering test check("cint2 == cint3",cint2==cint3); // strictly weak ordering test } { cout << "------------------------------------------"<<endl; cout << "RUNNING CHECKS FOR PSTATE AND PSTATESET:"<<endl; VariableIdMapping variableIdMapping; EState es1; EState es2; PState s0; PState s1; PState s2; PState s3; PState s5; AValue valtop=AType::Top(); AValue val1=500; AValue val2=501; PStateSet pstateSet; VariableId x=variableIdMapping.createUniqueTemporaryVariableId("x"); VariableId y=variableIdMapping.createUniqueTemporaryVariableId("y"); check("var x not in pstate1",s1.varExists(x)==false); check("var y not in pstate2",s2.varExists(y)==false); s1[x]=val1; s2[y]=val2; s3[x]=val2; s5[x]=valtop; s5[y]=valtop; check("var x exists in pstate s1",s1.varExists(x)==true); check("var x==500",((s1[x].operatorEq(val1)).isTrue())==true); check("var y exists in pstate s2",s2.varExists(y)==true); check("var y==501",((s2[y].operatorEq(val2)).isTrue())==true); //check("s0 < s1",(s0<s1)==true); //check("s0 < s2",(s0<s2)==true); check("!(s1 == s2)",(s1==s2)==false); check("s1<s2 xor s2<s1)",(s1<s2)^(s2<s1)); check("var x in pstate s3",s3.varExists(x)==true); check("s3[x]==501",((s3[x].operatorEq(val2)).isTrue())==true); check("!(s1==s2)",(!(s1==s2))==true); check("!(s1==s3)",(!(s1==s3))==true); check("!(s2==s3)",(!(s2==s3))==true); PState s4=s1; check("s1==s4",(s1==s4)==true); s1[x]=val2; check("s1.size()==1",s1.size()==1); pstateSet.process(s0); check("empty pstate s0 inserted in pstateSet => size of pstateSet == 1",pstateSet.size()==1); pstateSet.process(s1); check("s1 inserted in pstateSet => size of pstateSet == 2",pstateSet.size()==2); pstateSet.process(s1); check("s1 reinserted in pstateSet => size remains the same",pstateSet.size()==2); pstateSet.process(s2); check("s2 inserted => size of pstateSet == 3",pstateSet.size()==3); const PState* pstateptr0=pstateSet.processNewOrExisting(s0); // version 1 check("obtain pointer to s0 from pstateSet and check !=0",pstateptr0!=0); check("check pointer refers indeed to s0 (operator==)",(*pstateptr0)==s0); const PState* pstateptr1=pstateSet.processNewOrExisting(s1); // version 1 check("obtain pointer to s1 from pstateSet and check !=0",pstateptr1!=0); const PState* pstateptr2=pstateSet.processNewOrExisting(s2); // version 1 check("obtain pointer to s2 from pstateSet and check !=0",pstateptr2!=0); check("check pstate.exists(s0)",pstateSet.exists(s0)); check("check pstate.exists(s1)",pstateSet.exists(s1)); check("check pstate.exists(s2)",pstateSet.exists(s2)); check("check !pstate.exists(s5) [s5 does not exist]",!pstateSet.exists(s5)); check("constint-strictWeak-equality-1",strictWeakOrderingIsEqual(val1,val2)==false); check("constint-strictWeak-smaller-1",strictWeakOrderingIsSmaller(val1,val2)==true); s4[x]=valtop; check("created s4; inserted x=top; s4[x].isTop",s4[x].isTop()); pstateSet.processNewOrExisting(s4); check("inserted s4 => size of pstateSet == 4",pstateSet.size()==4); const PState* pstateptr4=pstateSet.processNewOrExisting(s4); // version 1 check("obtain pointer to s4 from pstateSet and check !=0",pstateptr4!=0); #if 1 EStateSet eStateSet; EState es3; ConstraintSetMaintainer csm; ConstraintSet cs1; cs1.addConstraint(Constraint(Constraint::NEQ_VAR_CONST,x,1)); const ConstraintSet* cs1ptr=csm.processNewOrExisting(cs1); es1=EState(1,pstateptr1,cs1ptr); ConstraintSet cs2; cs2.addConstraint(Constraint(Constraint::EQ_VAR_CONST,x,1)); const ConstraintSet* cs2ptr=csm.processNewOrExisting(cs2); es2=EState(1,pstateptr1,cs2ptr); ConstraintSet cs3; cs3.addConstraint(Constraint(Constraint::NEQ_VAR_CONST,x,1)); const ConstraintSet* cs3ptr=csm.processNewOrExisting(cs3); es3=EState(3,pstateptr4,cs3ptr); check("check es1 does not exist in eStateSet",eStateSet.exists(es1)==0); check("check es2 does not exist in eStateSet",eStateSet.exists(es2)==0); check("check es3 does not exist in eStateSet",eStateSet.exists(es3)==0); check("es1!=es2",es1!=es2); check("es2!=es3",es1!=es3); check("es1!=es3",es2!=es3); #ifdef ESTATE_MAINTAINER_LIST nocheck("es1<es2",es2<es1); nocheck("!(es2<es1)",!(es1<es2)); #endif #ifdef ESTATE_MAINTAINER_SET check("es1<es2",es1<es2); check("!(es2<es1)",!(es2<es1)); #endif check("!(es1==es2)",!(es1==es2)); #ifdef ESTATE_MAINTAINER_LIST nocheck("es1<es3",es1<es3); nocheck("es2<es3",es2<es3); #endif #ifdef ESTATE_MAINTAINER_SET check("es1<es3",es1<es3); check("es2<es3",es2<es3); #endif check("es2==es2",es2==es2); check("=> eStateSet.size() == 0",eStateSet.size() == 0); check("es1 does not exist in eStateSet",!eStateSet.exists(es2)); eStateSet.processNewOrExisting(es1); const EState* estateptr1=eStateSet.processNewOrExisting(es1); check("add es1 and obtain pointer to es1 from eStateSet and check !=0",estateptr1!=0); check("es1 exists in eStateSet",eStateSet.exists(es1)); check("=> eStateSet.size() == 1",eStateSet.size() == 1); check("es2 does not exist in eStateSet",!eStateSet.exists(es2)); eStateSet.processNewOrExisting(es2); const EState* estateptr2=eStateSet.processNewOrExisting(es2); check("add es2 and obtain pointer to es2 from eStateSet and check !=0",estateptr2!=0); check("es2 exists in eStateSet",eStateSet.exists(es2)); check("=> eStateSet.size() == 2",eStateSet.size() == 2); check("es3 does not exist in eStateSet",!eStateSet.exists(es3)); eStateSet.processNewOrExisting(es3); const EState* estateptr3=eStateSet.processNewOrExisting(es3); check("add es3 and obtain pointer to es3 from eStateSet and check !=0",estateptr3!=0); check("es3 exists in eStateSet",eStateSet.exists(es3)); check("=> eStateSet.size() == 3",eStateSet.size() == 3); checkLargeSets(); #endif } #if 0 // MS: TODO: rewrite the following test to new check format { cout << "------------------------------------------"<<endl; cout << "RUNNING CHECKS FOR COMBINED TYPES:"<<endl; EState es1; EState es2; cout << "EState created. "<<endl; cout << "empty EState: "<<es1.toString()<<endl; es1.setLabel(1); VariableId var_x=variableIdMapping.createUniqueTemporaryVariableId("x"); es1.constraints.addConstraint(Constraint(Constraint::EQ_VAR_CONST,var_x,1)); es2.setLabel(1); es2.constraints.addConstraint(Constraint(Constraint::NEQ_VAR_CONST,var_x,1)); cout << "empty EState with label and constraint es1: "<<es1.toString()<<endl; cout << "empty EState with label and constraint es2: "<<es2.toString()<<endl; PState s; es1.setPState(&s); es2.setPState(&s); cout << "empty EState with label, empty pstate, and constraint es1: "<<es1.toString()<<endl; cout << "empty EState with label, empty pstate, and constraint es2: "<<es2.toString()<<endl; bool testres=(es1==es2); if(testres) cout << "es1==es2: "<<testres<< "(not as expected: FAIL)"<<endl; else cout << "es1==es2: "<<testres<< "(as expected: PASS)"<<endl; } #endif // check stream operators { cout << "------------------------------------------"<<endl; cout << "RUNNING CHECKS FOR INPUT/OUTPUT STREAM OPs"<<endl; stringstream ss2; ss2<<"test1"; check("Parse: Testing test2 on test1.",!SPRAY::Parse::checkWord("test2",ss2)); //cout << "Remaing stream: "<<ss2.str()<<endl; stringstream ss3; ss3<<"test1"; check("Parse: Testing test1 on test1.",SPRAY::Parse::checkWord("test1",ss3)); //cout << "Remaing stream: "<<ss3.str()<<endl; CodeThorn::AType::ConstIntLattice x; stringstream ss4; ss4<<"top"; x.fromStream(ss4); check("ConstIntLattice: streaminput: top",x.toString()=="top"); stringstream ss5; ss5<<"12"; x.fromStream(ss5); check("ConstIntLattice: streaminput: 12",x.toString()=="12"); stringstream ss6; ss6<<"15top16"; ss6>>x; check("ConstIntLattice: streaminput: 15",x.toString()=="15"); ss6>>x; check("ConstIntLattice: streaminput: top",x.toString()=="top"); ss6>>x; check("ConstIntLattice: streaminput: 16",x.toString()=="16"); { PState ps; stringstream ss1; string pstateString="{}"; ss1<<pstateString; ps.fromStream(ss1); string checkString=(string("stream input PState: ")+pstateString); bool checkresult=(ps.toString()==pstateString); check(checkString,checkresult); if(checkresult==false) { cout << "Error: input stream result: "<<ps.toString()<<endl; } } { PState ps; stringstream ss0; string pstateString="{(V0,5),(V1,top),(V2,bot)}"; ss0<<pstateString; ss0>>ps; string checkString=(string("stream input PState: ")+pstateString); bool checkresult=(ps.toString()==pstateString); check(checkString,checkresult); if(checkresult==false) { cout << "pstateString :"<<pstateString<<":"<<endl; cout << "ps.toString():"<<ps.toString()<<":"<<endl; } } { stringstream ss; string s="aaabbb"; ss<<s; string parseString="aaa"; SPRAY::Parse::parseString(parseString,ss); // throws exception if it fails char next; ss>>next; check(string("Parsing: ")+parseString+" from:"+s+" Next:"+next,true); } { Constraint cs; stringstream ss; stringstream ssout; string cstring="V1==V2"; ss<<cstring; cs.fromStream(ss); cs.toStream(ssout); check("Stream I/O constraint: "+cstring,ssout.str()==cstring); } { Constraint cs; stringstream ss; stringstream ssout; string cstring="V3!=4"; ss<<cstring; cs.fromStream(ss); cs.toStream(ssout); check("Stream I/O constraint: "+cstring,ssout.str()==cstring); } { Constraint cs; cs=DISEQUALITYCONSTRAINT; stringstream ss; stringstream ssout; string cstring=cs.toString(); ss<<cstring; cs.fromStream(ss); cs.toStream(ssout); check("Stream I/O DEQ constraint: "+cstring,ssout.str()==cstring); } #ifndef EXCLUDE_RDANALYSIS { RDLattice a; VariableId var1; var1.setIdCode(1); VariableId var2; var2.setIdCode(2); a.insertPair(1,var1); RDLattice b; b.insertPair(1,var1); b.insertPair(2,var2); //a.toStream(cout);cout<<endl; //b.toStream(cout);cout<<endl; check("a ApproximatedBy b",a.approximatedBy(b)==true); check("not (b ApproximatedBy a)",b.approximatedBy(a)==false); } #endif } // end of stream operator checks }
int main(int argc, char* argv[]) { try { if(argc==1) { cout << "Error: wrong command line options."<<endl; exit(1); } #if 0 if(argc==3) { csvAssertFileName=argv[2]; argc=2; // don't confuse ROSE command line cout<< "INIT: CSV-output file: "<<csvAssertFileName<<endl; } #endif // Command line option handling. namespace po = boost::program_options; po::options_description desc ("Woodpecker V0.1\n" "Written by Markus Schordan\n" "Supported options"); desc.add_options() ("help,h", "produce this help message.") ("rose-help", "show help for compiler frontend options.") ("version,v", "display the version.") ("stats", "display code statistics.") ("normalize", po::value< string >(), "normalize code (eliminate compound assignment operators).") ("inline",po::value< string >(), "perform inlining ([yes]|no).") ("eliminate-empty-if",po::value< string >(), "eliminate if-statements with empty branches in main function ([yes]/no).") ("eliminate-dead-code",po::value< string >(), "eliminate dead code (variables and expressions) ([yes]|no).") ("csv-const-result",po::value< string >(), "generate csv-file [arg] with const-analysis data.") ("generate-transformed-code",po::value< string >(), "generate transformed code with prefix rose_ ([yes]|no).") ("verbose",po::value< string >(), "print detailed output during analysis and transformation (yes|[no]).") ("generate-conversion-functions","generate code for conversion functions between variable names and variable addresses.") ("csv-assert",po::value< string >(), "name of csv file with reachability assert results'") ("enable-multi-const-analysis",po::value< string >(), "enable multi-const analysis.") ("transform-thread-variable", "transform code to use additional thread variable.") ; // ("int-option",po::value< int >(),"option info") po::store(po::command_line_parser(argc, argv). options(desc).allow_unregistered().run(), args); po::notify(args); if (args.count("help")) { cout << "woodpecker <filename> [OPTIONS]"<<endl; cout << desc << "\n"; return 0; } if (args.count("rose-help")) { argv[1] = strdup("--help"); } if (args.count("version")) { cout << "Woodpecker version 0.1\n"; cout << "Written by Markus Schordan 2013\n"; return 0; } if (args.count("csv-assert")) { csvAssertFileName=args["csv-assert"].as<string>().c_str(); } if (args.count("csv-const-result")) { csvConstResultFileName=args["csv-const-result"].as<string>().c_str(); } boolOptions.init(argc,argv); // temporary fake optinos boolOptions.registerOption("arith-top",false); // temporary boolOptions.registerOption("semantic-fold",false); // temporary boolOptions.registerOption("post-semantic-fold",false); // temporary // regular options boolOptions.registerOption("normalize",false); boolOptions.registerOption("inline",true); boolOptions.registerOption("eliminate-empty-if",true); boolOptions.registerOption("eliminate-dead-code",true); boolOptions.registerOption("generate-transformed-code",true); boolOptions.registerOption("enable-multi-const-analysis",false); boolOptions.registerOption("verbose",false); boolOptions.processOptions(); if(boolOptions["verbose"]) detailedOutput=1; // clean up string-options in argv for (int i=1; i<argc; ++i) { if (string(argv[i]) == "--csv-assert" || string(argv[i]) == "--csv-const-result" ) { // do not confuse ROSE frontend argv[i] = strdup(""); assert(i+1<argc); argv[i+1] = strdup(""); } } global_option_multiconstanalysis=boolOptions["enable-multi-const-analysis"]; #if 0 if(global_option_multiconstanalysis) { cout<<"INFO: Using flow-insensitive multi-const-analysis."<<endl; } else { cout<<"INFO: Using flow-insensitive unique-const-analysis."<<endl; } #endif cout << "INIT: Parsing and creating AST started."<<endl; SgProject* root = frontend(argc,argv); // AstTests::runAllTests(root); // inline all functions cout << "INIT: Parsing and creating AST finished."<<endl; if(args.count("stats")) { printCodeStatistics(root); exit(0); } VariableIdMapping variableIdMapping; variableIdMapping.computeVariableSymbolMapping(root); if(args.count("transform-thread-variable")) { Threadification* threadTransformation=new Threadification(&variableIdMapping); threadTransformation->transform(root); root->unparse(0,0); delete threadTransformation; cout<<"STATUS: generated program with introduced thread-variable."<<endl; exit(0); } SgFunctionDefinition* mainFunctionRoot=0; if(boolOptions["inline"]) { cout<<"STATUS: eliminating non-called trivial functions."<<endl; // inline functions TrivialInlining tin; tin.setDetailedOutput(detailedOutput); tin.inlineFunctions(root); DeadCodeElimination dce; // eliminate non called functions int numEliminatedFunctions=dce.eliminateNonCalledTrivialFunctions(root); cout<<"STATUS: eliminated "<<numEliminatedFunctions<<" functions."<<endl; } else { cout<<"INFO: Inlining: turned off."<<endl; } if(boolOptions["eliminate-empty-if"]) { DeadCodeElimination dce; cout<<"STATUS: Eliminating empty if-statements."<<endl; size_t num=0; size_t numTotal=num; do { num=dce.eliminateEmptyIfStmts(root); cout<<"INFO: Number of if-statements eliminated: "<<num<<endl; numTotal+=num; } while(num>0); cout<<"STATUS: Total number of empty if-statements eliminated: "<<numTotal<<endl; } if(boolOptions["normalize"]) { cout <<"STATUS: Normalization started."<<endl; RewriteSystem rewriteSystem; rewriteSystem.resetStatistics(); rewriteSystem.rewriteCompoundAssignmentsInAst(root,&variableIdMapping); cout <<"STATUS: Normalization finished."<<endl; } cout<<"STATUS: performing flow-insensitive const analysis."<<endl; VarConstSetMap varConstSetMap; VariableIdSet variablesOfInterest; FIConstAnalysis fiConstAnalysis(&variableIdMapping); fiConstAnalysis.setOptionMultiConstAnalysis(global_option_multiconstanalysis); fiConstAnalysis.setDetailedOutput(detailedOutput); fiConstAnalysis.runAnalysis(root, mainFunctionRoot); variablesOfInterest=fiConstAnalysis.determinedConstantVariables(); cout<<"INFO: variables of interest: "<<variablesOfInterest.size()<<endl; if(detailedOutput) printResult(variableIdMapping,varConstSetMap); if(csvConstResultFileName) { VariableIdSet setOfUsedVarsInFunctions=AnalysisAbstractionLayer::usedVariablesInsideFunctions(root,&variableIdMapping); VariableIdSet setOfUsedVarsGlobalInit=AnalysisAbstractionLayer::usedVariablesInGlobalVariableInitializers(root,&variableIdMapping); VariableIdSet setOfAllUsedVars = setOfUsedVarsInFunctions; setOfAllUsedVars.insert(setOfUsedVarsGlobalInit.begin(), setOfUsedVarsGlobalInit.end()); cout<<"INFO: number of used vars inside functions: "<<setOfUsedVarsInFunctions.size()<<endl; cout<<"INFO: number of used vars in global initializations: "<<setOfUsedVarsGlobalInit.size()<<endl; cout<<"INFO: number of vars inside functions or in global inititializations: "<<setOfAllUsedVars.size()<<endl; fiConstAnalysis.filterVariables(setOfAllUsedVars); fiConstAnalysis.writeCvsConstResult(variableIdMapping, string(csvConstResultFileName)); } if(args.count("generate-conversion-functions")) { string conversionFunctionsFileName="conversionFunctions.C"; ConversionFunctionsGenerator gen; set<string> varNameSet; std::list<SgVariableDeclaration*> globalVarDeclList=SgNodeHelper::listOfGlobalVars(root); for(std::list<SgVariableDeclaration*>::iterator i=globalVarDeclList.begin();i!=globalVarDeclList.end();++i) { SgInitializedNamePtrList& initNamePtrList=(*i)->get_variables(); for(SgInitializedNamePtrList::iterator j=initNamePtrList.begin();j!=initNamePtrList.end();++j) { SgInitializedName* initName=*j; if ( true || isSgArrayType(initName->get_type()) ) { // optional filter (array variables only) SgName varName=initName->get_name(); string varNameString=varName; // implicit conversion varNameSet.insert(varNameString); } } } string code=gen.generateCodeForGlobalVarAdressMaps(varNameSet); ofstream myfile; myfile.open(conversionFunctionsFileName.c_str()); myfile<<code; myfile.close(); } VariableConstInfo vci=*(fiConstAnalysis.getVariableConstInfo()); DeadCodeElimination dce; if(boolOptions["eliminate-dead-code"]) { cout<<"STATUS: performing dead code elimination."<<endl; dce.setDetailedOutput(detailedOutput); dce.setVariablesOfInterest(variablesOfInterest); dce.eliminateDeadCodePhase1(root,&variableIdMapping,vci); cout<<"STATUS: Eliminated "<<dce.numElimVars()<<" variable declarations."<<endl; cout<<"STATUS: Eliminated "<<dce.numElimAssignments()<<" variable assignments."<<endl; cout<<"STATUS: Replaced "<<dce.numElimVarUses()<<" uses of variables with constant."<<endl; cout<<"STATUS: Eliminated "<<dce.numElimVars()<<" dead variables."<<endl; cout<<"STATUS: Dead code elimination phase 1: finished."<<endl; cout<<"STATUS: Performing condition const analysis."<<endl; } else { cout<<"STATUS: Dead code elimination: turned off."<<endl; } if(csvAssertFileName) { cout<<"STATUS: performing flow-insensensitive condition-const analysis."<<endl; Labeler labeler(root); fiConstAnalysis.performConditionConstAnalysis(&labeler); cout<<"INFO: Number of true-conditions : "<<fiConstAnalysis.getTrueConditions().size()<<endl; cout<<"INFO: Number of false-conditions : "<<fiConstAnalysis.getFalseConditions().size()<<endl; cout<<"INFO: Number of non-const-conditions: "<<fiConstAnalysis.getNonConstConditions().size()<<endl; cout<<"STATUS: performing flow-insensensitive reachability analysis."<<endl; ReachabilityAnalysis ra; PropertyValueTable reachabilityResults=ra.fiReachabilityAnalysis(labeler, fiConstAnalysis); cout<<"STATUS: generating file "<<csvAssertFileName<<endl; reachabilityResults.writeFile(csvAssertFileName,true); } #if 0 rdAnalyzer->determineExtremalLabels(startFunRoot); rdAnalyzer->run(); #endif cout << "INFO: Remaining functions in program: "<<numberOfFunctions(root)<<endl; if(boolOptions["generate-transformed-code"]) { cout << "STATUS: generating transformed source code."<<endl; root->unparse(0,0); } std::list<int> fakelist; fakelist.push_back(1); std::list<int>::iterator myit=fakelist.begin(); fakelist.erase(myit); cout<< "STATUS: finished."<<endl; // main function try-catch } catch(char* str) { cerr << "*Exception raised: " << str << endl; return 1; } catch(const char* str) { cerr << "Exception raised: " << str << endl; return 1; } catch(string str) { cerr << "Exception raised: " << str << endl; return 1; } return 0; }
void runAnalyses(SgProject* root, Labeler* labeler, VariableIdMapping* variableIdMapping) { SPRAY::DFAnalysisBase::normalizeProgram(root); if(option_fi_constanalysis) { VarConstSetMap varConstSetMap; FIConstAnalysis fiConstAnalysis(variableIdMapping); fiConstAnalysis.runAnalysis(root); fiConstAnalysis.attachAstAttributes(labeler,"const-analysis-inout"); // not iolabeler if(csvConstResultFileName) { cout<<"INFO: generating const CSV file "<<option_prefix+csvConstResultFileName<<endl; fiConstAnalysis.writeCvsConstResult(*variableIdMapping, option_prefix+csvConstResultFileName); } cout << "INFO: annotating analysis results as comments."<<endl; AstAnnotator ara(labeler); ara.annotateAstAttributesAsCommentsBeforeStatements(root, "const-analysis-inout"); ara.annotateAstAttributesAsCommentsAfterStatements(root, "const-analysis-inout"); } if(option_at_analysis) { cout<<"STATUS: running address taken analysis."<<endl; cout << "STATUS: computing variable and function mappings."<<endl; // compute variableId mappings VariableIdMapping variableIdMapping; variableIdMapping.computeVariableSymbolMapping(root); // Compute function id mappings: FunctionIdMapping functionIdMapping; functionIdMapping.computeFunctionSymbolMapping(root); if(option_trace) { std::cout << std::endl << "TRACE: Variable Id Mapping:" << std::endl; variableIdMapping.toStream(std::cout); std::cout << std::endl << "TRACE: Function Id Mapping:" << std::endl; functionIdMapping.toStream(std::cout); } cout << "STATUS: computing address taken sets."<<endl; SPRAY::FIPointerAnalysis fipa(&variableIdMapping, &functionIdMapping, root); fipa.initialize(); fipa.run(); //cout << "STATUS: computed address taken sets:"<<endl; //fipa.getFIPointerInfo()->printInfoSets(); bool createCsv = false; ofstream addressTakenCsvFile; if(csvAddressTakenResultFileName) { std::string addressTakenCsvFileName = option_prefix; addressTakenCsvFileName += csvAddressTakenResultFileName; addressTakenCsvFile.open(addressTakenCsvFileName.c_str()); createCsv = true; } cout << "INFO: annotating declarations of address taken variables and functions."<<endl; // Annotate declarations/definitions of variables from which the address was taken: VariableIdSet addressTakenVariableIds = fipa.getAddressTakenVariables(); for(VariableIdSet::const_iterator idIter = addressTakenVariableIds.begin(); idIter != addressTakenVariableIds.end(); ++idIter) { // Determine the variable declaration/definition: SgLocatedNode* decl = variableIdMapping.getVariableDeclaration(*idIter); if(!decl) { // The current variable is presumably a function parameter: Try to get the initialized name: SgVariableSymbol* varSymbol = isSgVariableSymbol(variableIdMapping.getSymbol(*idIter)); ROSE_ASSERT(varSymbol); SgInitializedName* paramDecl = isSgInitializedName(varSymbol->get_declaration()); // We should not have a real variable declaration for the parameter: ROSE_ASSERT(isSgFunctionParameterList(paramDecl->get_declaration())); // Use the InitializedName: decl = paramDecl; } if(decl) { // Create the comment: ostringstream commentStream; commentStream << "/* Address of \"" << variableIdMapping.variableName(*idIter) << "\" is " << "presumably taken.*/"; // Annotate first declaration: insertComment(commentStream.str(), PreprocessingInfo::before, decl); // TODO: Annotate other declarations too! // Annotate definition if available (e.g. not available in case of parameter): if(SgDeclarationStatement* variableDeclaration = isSgDeclarationStatement(decl)) { if(SgDeclarationStatement* definingDeclaration = variableDeclaration->get_definingDeclaration()) { insertComment(commentStream.str(), PreprocessingInfo::before, definingDeclaration); } } if(createCsv) { // Write variable info to csv: addressTakenCsvFile << VariableId::idKindIndicator << "," // The id of the variable (id codes are influenced by the used system headers // and are therefore not stable/portable): << (option_csv_stable ? string("<unstable>") : int_to_string((*idIter).getIdCode())) << "," // Name of the variable: << variableIdMapping.variableName(*idIter) << "," // TODO: Mangled scope and type are currently not stable/portable // (see comments in getScopeAsMangledStableString(...)) // Mangled type of the variable (non-mangled type may contain commas (e.g. "A<int,bool>"): << (option_csv_stable ? string("<unstable>") : variableIdMapping.getType(*idIter)->get_mangled().getString()) << "," // Mangled scope of the variable: << (option_csv_stable ? string("<unstable>") : getScopeAsMangledStableString(decl)) << "," // Is the address taken? (currently only address taken variables are output to csv) << "1" << endl; } } else { cout << "ERROR: No declaration for " << variableIdMapping.uniqueShortVariableName(*idIter) << " available." << endl; ROSE_ASSERT(false); } } // Annotate declarations and definitions of functions from which the address was taken: FunctionIdSet addressTakenFunctionIds = fipa.getAddressTakenFunctions(); for(FunctionIdSet::const_iterator idIter = addressTakenFunctionIds.begin(); idIter != addressTakenFunctionIds.end(); ++idIter) { if(SgFunctionDeclaration* decl = functionIdMapping.getFunctionDeclaration(*idIter)) { // Create the comment: ostringstream commentStream; commentStream << "/* Address of \"" << functionIdMapping.getFunctionNameFromFunctionId(*idIter) << "(...)\" is " << "presumably taken.*/"; // Annotate first declaration: insertComment(commentStream.str(), PreprocessingInfo::before, decl); // TODO: Annotate other declarations too! // Annotate definition if available: if(SgDeclarationStatement* definingDeclaration = decl->get_definingDeclaration()) { insertComment(commentStream.str(), PreprocessingInfo::before, definingDeclaration); } if(createCsv) { addressTakenCsvFile << FunctionId::idKindIndicator << "," // The id of the function (id codes are influenced by the used system headers // and are therefore not stable/portable): << (option_csv_stable ? string("<unstable>") : int_to_string((*idIter).getIdCode())) << "," // Name of the function: << functionIdMapping.getFunctionNameFromFunctionId(*idIter) << "," // TODO: Mangled scope and type are currently not stable/portable // (see comments in getScopeAsMangledStableString(...)) // Mangled type of the function (non-mangled type may contain commas (e.g. "void (A<int,bool>)"): << (option_csv_stable ? string("<unstable>") : functionIdMapping.getTypeFromFunctionId(*idIter)->get_mangled().getString()) << "," // Mangled scope of the function: << (option_csv_stable ? string("<unstable>") :getScopeAsMangledStableString(decl)) << "," // Is the address taken? (currently only address taken functions are output to csv) << "1" << endl; } } else { cout << "ERROR: No declaration for " << functionIdMapping.getUniqueShortNameFromFunctionId(*idIter) << " available." << endl; ROSE_ASSERT(false); } } if(createCsv) { addressTakenCsvFile.close(); } #if 0 VariableIdSet vidset=fipa.getModByPointer(); cout<<"mod-set: "<<SPRAY::VariableIdSetPrettyPrint::str(vidset,variableIdMapping)<<endl; #endif } if(option_interval_analysis) { cout << "STATUS: creating interval analyzer."<<endl; SPRAY::IntervalAnalysis* intervalAnalyzer=new SPRAY::IntervalAnalysis(); cout << "STATUS: initializing interval analyzer."<<endl; intervalAnalyzer->setNoTopologicalSort(option_no_topological_sort); intervalAnalyzer->initialize(root); cout << "STATUS: running pointer analysis."<<endl; ROSE_ASSERT(intervalAnalyzer->getVariableIdMapping()); SPRAY::FIPointerAnalysis* fipa=new FIPointerAnalysis(intervalAnalyzer->getVariableIdMapping(), intervalAnalyzer->getFunctionIdMapping(), root); fipa->initialize(); fipa->run(); intervalAnalyzer->setPointerAnalysis(fipa); cout << "STATUS: initializing interval transfer functions."<<endl; intervalAnalyzer->initializeTransferFunctions(); cout << "STATUS: initializing interval global variables."<<endl; intervalAnalyzer->initializeGlobalVariables(root); intervalAnalyzer->setSolverTrace(option_trace); std::string funtofind="main"; RoseAst completeast(root); SgFunctionDefinition* startFunRoot=completeast.findFunctionByName(funtofind); intervalAnalyzer->determineExtremalLabels(startFunRoot); intervalAnalyzer->run(); #if 0 intervalAnalyzer->attachInInfoToAst("iv-analysis-in"); intervalAnalyzer->attachOutInfoToAst("iv-analysis-out"); AstAnnotator ara(intervalAnalyzer->getLabeler(),intervalAnalyzer->getVariableIdMapping()); ara.annotateAstAttributesAsCommentsBeforeStatements(root, "iv-analysis-in"); ara.annotateAstAttributesAsCommentsAfterStatements(root, "iv-analysis-out"); #else AnalysisAstAnnotator ara(intervalAnalyzer->getLabeler(),intervalAnalyzer->getVariableIdMapping()); ara.annotateAnalysisPrePostInfoAsComments(root,"iv-analysis",intervalAnalyzer); #endif if(option_check_static_array_bounds) { checkStaticArrayBounds(root,intervalAnalyzer); } // schroder3 (2016-08-08): Generate csv-file that contains unreachable statements: if(csvDeadCodeUnreachableFileName) { // Generate file name and open file: std::string deadCodeCsvFileName = option_prefix; deadCodeCsvFileName += csvDeadCodeUnreachableFileName; ofstream deadCodeCsvFile; deadCodeCsvFile.open(deadCodeCsvFileName.c_str()); // Iteratate over all CFG nodes/ labels: for(Flow::const_node_iterator i = intervalAnalyzer->getFlow()->nodes_begin(); i != intervalAnalyzer->getFlow()->nodes_end(); ++i) { const Label& label = *i; // Do not output a function call twice (only the function call label and not the function call return label): if(!intervalAnalyzer->getLabeler()->isFunctionCallReturnLabel(label)) { /*const*/ IntervalPropertyState& intervalsLattice = *static_cast<IntervalPropertyState*>(intervalAnalyzer->getPreInfo(label.getId())); if(intervalsLattice.isBot()) { // Unreachable statement found: const SgNode* correspondingNode = intervalAnalyzer->getLabeler()->getNode(label); ROSE_ASSERT(correspondingNode); // Do not output scope statements ({ }, ...) if(!isSgScopeStatement(correspondingNode)) { deadCodeCsvFile << correspondingNode->get_file_info()->get_line() << "," << SPRAY::replace_string(correspondingNode->unparseToString(), ",", "/*comma*/") << endl; } } } } deadCodeCsvFile.close(); } delete fipa; } if(option_lv_analysis) { cout << "STATUS: creating LV analysis."<<endl; SPRAY::LVAnalysis* lvAnalysis=new SPRAY::LVAnalysis(); cout << "STATUS: initializing LV analysis."<<endl; lvAnalysis->setBackwardAnalysis(); lvAnalysis->setNoTopologicalSort(option_no_topological_sort); lvAnalysis->initialize(root); cout << "STATUS: running pointer analysis."<<endl; ROSE_ASSERT(lvAnalysis->getVariableIdMapping()); SPRAY::FIPointerAnalysis* fipa = new FIPointerAnalysis(lvAnalysis->getVariableIdMapping(), lvAnalysis->getFunctionIdMapping(), root); fipa->initialize(); fipa->run(); lvAnalysis->setPointerAnalysis(fipa); cout << "STATUS: initializing LV transfer functions."<<endl; lvAnalysis->initializeTransferFunctions(); cout << "STATUS: initializing LV global variables."<<endl; lvAnalysis->initializeGlobalVariables(root); std::string funtofind="main"; RoseAst completeast(root); SgFunctionDefinition* startFunRoot=completeast.findFunctionByName(funtofind); cout << "generating icfg_backward.dot."<<endl; write_file("icfg_backward.dot", lvAnalysis->getFlow()->toDot(lvAnalysis->getLabeler())); lvAnalysis->determineExtremalLabels(startFunRoot); lvAnalysis->run(); cout << "INFO: attaching LV-data to AST."<<endl; #if 0 lvAnalysis->attachInInfoToAst("lv-analysis-in"); lvAnalysis->attachOutInfoToAst("lv-analysis-out"); AstAnnotator ara(lvAnalysis->getLabeler(),lvAnalysis->getVariableIdMapping()); ara.annotateAstAttributesAsCommentsBeforeStatements(root, "lv-analysis-in"); ara.annotateAstAttributesAsCommentsAfterStatements(root, "lv-analysis-out"); #else AnalysisAstAnnotator ara(lvAnalysis->getLabeler(),lvAnalysis->getVariableIdMapping()); ara.annotateAnalysisPrePostInfoAsComments(root,"lv-analysis",lvAnalysis); #endif // schroder3 (2016-08-15): Generate csv-file that contains dead assignments/ initializations: if(csvDeadCodeDeadStoreFileName) { // Generate file name and open file: std::string deadCodeCsvFileName = option_prefix; deadCodeCsvFileName += csvDeadCodeDeadStoreFileName; ofstream deadCodeCsvFile; deadCodeCsvFile.open(deadCodeCsvFileName.c_str()); if(option_trace) { cout << "TRACE: checking for dead stores." << endl; } // Iteratate over all CFG nodes/ labels: for(Flow::const_node_iterator labIter = lvAnalysis->getFlow()->nodes_begin(); labIter != lvAnalysis->getFlow()->nodes_end(); ++labIter) { const Label& label = *labIter; // Do not output a function call twice (only the function call return label and not the function call label): if(!lvAnalysis->getLabeler()->isFunctionCallLabel(label)) { /*const*/ SgNode* correspondingNode = lvAnalysis->getLabeler()->getNode(label); ROSE_ASSERT(correspondingNode); if(/*const*/ SgExprStatement* exprStmt = isSgExprStatement(correspondingNode)) { correspondingNode = exprStmt->get_expression(); } /*const*/ SgNode* association = 0; // Check if the corresponding node is an assignment or an initialization: if(isSgAssignOp(correspondingNode)) { association = correspondingNode; } else if(SgVariableDeclaration* varDecl = isSgVariableDeclaration(correspondingNode)) { SgInitializedName* initName = SgNodeHelper::getInitializedNameOfVariableDeclaration(varDecl); ROSE_ASSERT(initName); // Check whether there is an initialization that can be eliminated (reference initialization can not be eliminated). if(!SgNodeHelper::isReferenceType(initName->get_type()) && initName->get_initializer()) { association = correspondingNode; } } if(association) { if(option_trace) { cout << endl << "association: " << association->unparseToString() << endl; } VariableIdSet assignedVars = AnalysisAbstractionLayer::defVariables(association, *lvAnalysis->getVariableIdMapping(), fipa); /*const*/ LVLattice& liveVarsLattice = *static_cast<LVLattice*>(lvAnalysis->getPreInfo(label.getId())); if(option_trace) { cout << "live: " << liveVarsLattice.toString(lvAnalysis->getVariableIdMapping()) << endl; cout << "assigned: " << endl; } bool minOneIsLive = false; for(VariableIdSet::const_iterator assignedVarIter = assignedVars.begin(); assignedVarIter != assignedVars.end(); ++assignedVarIter) { if(option_trace) { cout << (*assignedVarIter).toString(*lvAnalysis->getVariableIdMapping()) << endl; } if(liveVarsLattice.exists(*assignedVarIter)) { minOneIsLive = true; break; } } if(!minOneIsLive) { if(option_trace) { cout << "association is dead." << endl; } // assignment to only dead variables found: deadCodeCsvFile << correspondingNode->get_file_info()->get_line() << "," << SPRAY::replace_string(correspondingNode->unparseToString(), ",", "/*comma*/") << endl; } } } } deadCodeCsvFile.close(); } delete lvAnalysis; } if(option_rd_analysis) { cout << "STATUS: creating RD analyzer."<<endl; SPRAY::RDAnalysis* rdAnalysis=new SPRAY::RDAnalysis(); cout << "STATUS: initializing RD analyzer."<<endl; rdAnalysis->setNoTopologicalSort(option_no_topological_sort); rdAnalysis->initialize(root); cout << "STATUS: initializing RD transfer functions."<<endl; rdAnalysis->initializeTransferFunctions(); cout << "STATUS: initializing RD global variables."<<endl; rdAnalysis->initializeGlobalVariables(root); cout << "generating icfg_forward.dot."<<endl; write_file("icfg_forward.dot", rdAnalysis->getFlow()->toDot(rdAnalysis->getLabeler())); std::string funtofind="main"; RoseAst completeast(root); SgFunctionDefinition* startFunRoot=completeast.findFunctionByName(funtofind); rdAnalysis->determineExtremalLabels(startFunRoot); rdAnalysis->run(); cout << "INFO: attaching RD-data to AST."<<endl; rdAnalysis->attachInInfoToAst("rd-analysis-in"); rdAnalysis->attachOutInfoToAst("rd-analysis-out"); //printAttributes<RDAstAttribute>(rdAnalysis->getLabeler(),rdAnalysis->getVariableIdMapping(),"rd-analysis-in"); cout << "INFO: annotating analysis results as comments."<<endl; ROSE_ASSERT(rdAnalysis->getVariableIdMapping()); #if 0 AstAnnotator ara(rdAnalysis->getLabeler(),rdAnalysis->getVariableIdMapping()); ara.annotateAstAttributesAsCommentsBeforeStatements(root, "rd-analysis-in"); ara.annotateAstAttributesAsCommentsAfterStatements(root, "rd-analysis-out"); #else AnalysisAstAnnotator ara(rdAnalysis->getLabeler(),rdAnalysis->getVariableIdMapping()); ara.annotateAnalysisPrePostInfoAsComments(root,"rd-analysis",rdAnalysis); #endif #if 0 cout << "INFO: substituting uses with rhs of defs."<<endl; substituteUsesWithAvailableExpRhsOfDef("ud-analysis", root, rdAnalysis->getLabeler(), rdAnalysis->getVariableIdMapping()); #endif if(option_ud_analysis) { ROSE_ASSERT(option_rd_analysis); cout << "INFO: generating and attaching UD-data to AST."<<endl; createUDAstAttributeFromRDAttribute(rdAnalysis->getLabeler(),"rd-analysis-in", "ud-analysis"); Flow* flow=rdAnalysis->getFlow(); cout<<"Flow label-set size: "<<flow->nodeLabels().size()<<endl; CFAnalysis* cfAnalyzer0=rdAnalysis->getCFAnalyzer(); int red=cfAnalyzer0->reduceBlockBeginNodes(*flow); cout<<"INFO: eliminated "<<red<<" block-begin nodes in ICFG."<<endl; #if 0 cout << "INFO: computing program statistics."<<endl; ProgramStatistics ps(rdAnalysis->getVariableIdMapping(), rdAnalysis->getLabeler(), rdAnalysis->getFlow(), "ud-analysis"); ps.computeStatistics(); //ps.printStatistics(); cout << "INFO: generating resource usage visualization."<<endl; ps.setGenerateWithSource(false); ps.generateResourceUsageICFGDotFile("resourceusageicfg.dot"); flow->resetDotOptions(); #endif cout << "INFO: generating visualization data."<<endl; // generate ICFG visualization cout << "generating icfg.dot."<<endl; write_file("icfg.dot", flow->toDot(rdAnalysis->getLabeler())); // cout << "INFO: generating control dependence graph."<<endl; //Flow cdg=rdAnalysis->getCFAnalyzer()->controlDependenceGraph(*flow); cout << "generating datadependencegraph.dot."<<endl; DataDependenceVisualizer ddvis0(rdAnalysis->getLabeler(), rdAnalysis->getVariableIdMapping(), "ud-analysis"); //printAttributes<UDAstAttribute>(rdAnalysis->getLabeler(),rdAnalysis->getVariableIdMapping(),"ud-analysis"); //ddvis._showSourceCode=false; // for large programs ddvis0.generateDefUseDotGraph(root,"datadependencegraph.dot"); flow->resetDotOptions(); cout << "generating icfgdatadependencegraph.dot."<<endl; DataDependenceVisualizer ddvis1(rdAnalysis->getLabeler(), rdAnalysis->getVariableIdMapping(), "ud-analysis"); ddvis1.includeFlowGraphEdges(flow); ddvis1.generateDefUseDotGraph(root,"icfgdatadependencegraph.dot"); flow->resetDotOptions(); cout << "generating icfgdatadependencegraph_clustered.dot."<<endl; DataDependenceVisualizer ddvis2(rdAnalysis->getLabeler(), rdAnalysis->getVariableIdMapping(), "ud-analysis"); ddvis2.generateDotFunctionClusters(root,rdAnalysis->getCFAnalyzer(),"icfgdatadependencegraph_clustered.dot",true); cout << "generating icfg_clustered.dot."<<endl; DataDependenceVisualizer ddvis3(rdAnalysis->getLabeler(), rdAnalysis->getVariableIdMapping(), "ud-analysis"); ddvis3.generateDotFunctionClusters(root,rdAnalysis->getCFAnalyzer(),"icfg_clustered.dot",false); } } }
int main(int argc, char* argv[]) { try { if(argc==1) { cout << "Error: wrong command line options."<<endl; exit(1); } // Command line option handling. namespace po = boost::program_options; po::options_description desc ("analyterix V0.2\n" "Written by Markus Schordan\n" "Supported options"); desc.add_options() ("help,h", "produce this help message.") ("rose-help", "show help for compiler frontend options.") ("version,v", "display the version.") ("stats", "display code statistics.") ("fi-constanalysis", "perform flow-insensitive constant analysis.") ("csv-fi-constanalysis",po::value< string >(), "generate csv-file [arg] with const-analysis data.") ("rd-analysis", "perform reaching definitions analysis.") ("rose-rd-analysis", "perform rose reaching definitions analysis.") ("lv-analysis", "perform live variables analysis.") ("ud-analysis", "use-def analysis.") ("at-analysis", "address-taken analysis.") ("icfg-dot", "generates the ICFG as dot file.") ("interval-analysis", "perform interval analysis.") ("trace", "show operations as performed by selected solver.") ("print-varidmapping", "prints variableIdMapping") ("print-varidmapping-array", "prints variableIdMapping with array element varids.") ("prefix",po::value< string >(), "set prefix for all generated files.") ; // ("int-option",po::value< int >(),"option info") po::store(po::command_line_parser(argc, argv).options(desc).allow_unregistered().run(), args); po::notify(args); if (args.count("help")) { cout << "analyterix <filename> [OPTIONS]"<<endl; cout << desc << "\n"; return 0; } if (args.count("version")) { cout << "analyterix version 0.1\n"; cout << "Written by Markus Schordan 2014\n"; return 0; } if (args.count("rose-help")) { argv[1] = strdup("--help"); } if (args.count("prefix")) { option_prefix=args["prefix"].as<string>().c_str(); } if (args.count("trace")) { option_trace=true; } if(args.count("stats")) { option_stats=true; } if(args.count("rd-analysis")) { option_rd_analysis=true; } if(args.count("lv-analysis")) { option_lv_analysis=true; } if(args.count("interval-analysis")) { option_interval_analysis=true; } if(args.count("ud-analysis")) { option_rd_analysis=true; // required option_ud_analysis=true; } if(args.count("rose-rd-analysis")) { option_rose_rd_analysis=true; } if(args.count("fi-constanalysis")) { option_fi_constanalysis=true; } if (args.count("csv-fi-constanalysis")) { csvConstResultFileName=args["csv-fi-constanalysis"].as<string>().c_str(); option_fi_constanalysis=true; } if(args.count("at-analysis")) { option_at_analysis=true; } // clean up string-options in argv for (int i=1; i<argc; ++i) { if (string(argv[i]) == "--prefix" || string(argv[i]) == "--csv-const-result" ) { // do not confuse ROSE frontend argv[i] = strdup(""); assert(i+1<argc); argv[i+1] = strdup(""); } } cout << "INIT: Parsing and creating AST."<<endl; boolOptions.registerOption("semantic-fold",false); // temporary boolOptions.registerOption("post-semantic-fold",false); // temporary SgProject* root = frontend(argc,argv); // AstTests::runAllTests(root); if(option_stats) { SPRAY::ProgramStatistics::printBasicCodeInfo(root); } cout<<"STATUS: computing variableid mapping"<<endl; VariableIdMapping variableIdMapping; if (args.count("print-varidmapping-array")) { variableIdMapping.setModeVariableIdForEachArrayElement(true); } variableIdMapping.computeVariableSymbolMapping(root); cout<<"VariableIdMapping size: "<<variableIdMapping.getVariableIdSet().size()<<endl; Labeler* labeler=new Labeler(root); //cout<<"Labelling:\n"<<labeler->toString()<<endl; #if 0 IOLabeler* iolabeler=new IOLabeler(root,&variableIdMapping); //cout<<"IOLabelling:\n"<<iolabeler->toString()<<endl; #endif if (args.count("print-varidmapping")||args.count("print-varidmapping-array")) { variableIdMapping.toStream(cout); } runAnalyses(root, labeler, &variableIdMapping); cout << "INFO: generating annotated source code."<<endl; root->unparse(0,0); if(option_rose_rd_analysis) { Experimental::RoseRDAnalysis::generateRoseRDDotFiles(labeler,root); } cout<< "STATUS: finished."<<endl; // main function try-catch } catch(char* str) { cerr << "*Exception raised: " << str << endl; return 1; } catch(const char* str) { cerr << "Exception raised: " << str << endl; return 1; } catch(string str) { cerr << "Exception raised: " << str << endl; return 1; } return 0; }
int main( int argc, char * argv[] ) { // If we want this translator to take specific options (beyond those defined // by ROSE) then insert command line processing for new options here. // To better support the stencil specification that might benifit from constant // folding, I have turned this ON is hte frontend. By default it is OFF so that // we can preserve source code as much as possible (original expression trees). // The Stencil DSL can be made to work in eithr setting, but this make sure that // dimension dependent processing of the stencil coeficients will be evaluated // to constants. I will turn this off (and thus use a less blunt axe) when the new // constant expression evaluation in ROSE is fixed to support more general types // than integer expresion (should be done by JP later today). // bool frontendConstantFolding = true; bool frontendConstantFolding = false; // Liao, support a flag to control if CUDA code should be generated // ./shiftCalculusCompiler -rose:dslcompiler:cuda -c input_file std::vector <std::string> argvList (argv, argv + argc); if (CommandlineProcessing::isOption (argvList,"-rose:dslcompiler:","cuda",true)) { std::cout<<"Turning on CUDA code generation ..."<<std::endl; b_gen_cuda = true; // avoid invoking the built in lowering, just create AST //argvList.push_back("-rose:openmp:ast_only"); //argvList.push_back("-rose:openmp:lowering"); //OmpSupport::enable_accelerator = true; } else b_gen_cuda = false; // Pei-Hung, enable loop collapsing if (CommandlineProcessing::isOption (argvList,"-rose:dslcompiler:","collapse",true)) { std::cout<<"Turning on OpenMP loop collapsing ..."<<std::endl; b_enable_collapse = true; // argvList.push_back("-rose:openmp:lowering"); } else b_enable_collapse = false; // Pei-Hung, code generation to fulfill polyopt if (CommandlineProcessing::isOption (argvList,"-rose:dslcompiler:","polyopt",true)) { std::cout<<"Generating code for PolyOpt ..."<<std::endl; b_enable_polyopt = true; // argvList.push_back("-rose:openmp:lowering"); } else b_enable_polyopt = false; // Pei-Hung, code generation to vectorization if (CommandlineProcessing::isOption (argvList,"-rose:dslcompiler:","vectorization",true)) { std::cout<<"Generating code for vectorization ..."<<std::endl; b_gen_vectorization = true; // argvList.push_back("-rose:openmp:lowering"); } else b_gen_vectorization = false; // If MPI code generation is turned on if (CommandlineProcessing::isOption (argvList,"-rose:dslcompiler:","mpi",true)) { std::cout<<"Turning on MPI code generation ..."<<std::endl; b_gen_mpi = true; // argvList.push_back("-rose:openmp:lowering"); } else b_gen_mpi = false; // Generate the ROSE AST. //SgProject* project = frontend(argc,argv,frontendConstantFolding); SgProject* project = frontend(argvList,frontendConstantFolding); ROSE_ASSERT(project != NULL); try { variableIdMapping.computeVariableSymbolMapping(project); } catch(char* str) { cout << "*Exception raised: " << str << endl; } catch(const char* str) { cout << "Exception raised: " << str << endl; } catch(string str) { cout << "Exception raised: " << str << endl; } // variableIdMapping.toStream(cout); #if 1 printf ("variableIdMapping.getVariableIdSet().size() = %zu \n",variableIdMapping.getVariableIdSet().size()); ROSE_ASSERT(variableIdMapping.getVariableIdSet().size() > 0); #endif #if 0 printf ("Exiting as a test after calling variableIdMapping.computeVariableSymbolMapping(project) \n"); ROSE_ASSERT(false); #endif #if 0 printf ("Calling constant folding \n"); ConstantFolding::constantFoldingOptimization(project,false); #if 0 printf ("Exiting as a test after calling ConstantFolding::constantFoldingOptimization() \n"); ROSE_ASSERT(false); #endif #endif // DQ (2/8/2015): Find the associated SgFile so we can restrict processing to the current file. ROSE_ASSERT(project->get_fileList().empty() == false); SgFile* firstFile = project->get_fileList()[0]; ROSE_ASSERT(firstFile != NULL); #if DEBUG_USING_DOT_GRAPHS // generateDOTforMultipleFile(*project); // generateDOT(*project,"_before_transformation"); AstDOTGeneration astdotgen; astdotgen.generateWithinFile(firstFile,DOTGeneration<SgNode*>::TOPDOWNBOTTOMUP,"_before_transformation"); #endif #if DEBUG_USING_DOT_GRAPHS && 1 const int MAX_NUMBER_OF_IR_NODES_TO_GRAPH_FOR_WHOLE_GRAPH = 12000; #endif #if DEBUG_USING_DOT_GRAPHS && 1 // Output an optional graph of the AST (the whole graph, of bounded complexity, when active) generateAstGraph(project,MAX_NUMBER_OF_IR_NODES_TO_GRAPH_FOR_WHOLE_GRAPH,"_before"); #endif // Build the inherited attribute Detection_InheritedAttribute inheritedAttribute; // Define the traversal DetectionTraversal shiftCalculus_DetectionTraversal; #if 1 printf ("Call the Detection traversal starting at the project (root) node of the AST \n"); #endif // Call the traversal starting at the project (root) node of the AST // Detection_SynthesizedAttribute result = shiftCalculus_DetectionTraversal.traverse(project,inheritedAttribute); Detection_SynthesizedAttribute result = shiftCalculus_DetectionTraversal.traverseWithinFile(firstFile,inheritedAttribute); #if 0 printf ("Stencil Operator was transformed: %s \n",result.get_stencilOperatorTransformed() ? "true" : "false"); #endif ROSE_ASSERT(result.get_stencilOperatorTransformed() == false); #if 1 printf ("DONE: Call the Detection traversal starting at the project (root) node of the AST \n"); #endif #if 0 shiftCalculus_DetectionTraversal.display(); #endif #if DEBUG_USING_DOT_GRAPHS // generateDOTforMultipleFile(*project); // generateDOT(*project,"_before_transformation"); AstDOTGeneration astdotgen_2; astdotgen_2.generateWithinFile(firstFile,DOTGeneration<SgNode*>::TOPDOWNBOTTOMUP,"_after_DSL_detection"); #endif #if 0 printf ("Exiting after the initial traversal to detect the stencil useage. \n"); ROSE_ASSERT(false); #endif // Build the inherited attribute StencilEvaluation_InheritedAttribute inheritedAttribute_stencilEval; // Define the traversal // StencilEvaluationTraversal shiftCalculus_StencilEvaluationTraversal(shiftCalculus_DetectionTraversal); StencilEvaluationTraversal shiftCalculus_StencilEvaluationTraversal; #if 1 printf ("Call the StencilEvaluation traversal starting at the project (root) node of the AST \n"); #endif // Call the traversal starting at the project (root) node of the AST // StencilEvaluation_SynthesizedAttribute result_stencilEval = shiftCalculus_StencilEvaluationTraversal.traverse(project,inheritedAttribute_stencilEval); StencilEvaluation_SynthesizedAttribute result_stencilEval = shiftCalculus_StencilEvaluationTraversal.traverseWithinFile(firstFile,inheritedAttribute_stencilEval); #if 0 printf ("Stencil Evaluation was transformed: %s \n",result_stencilEval.get_stencilOperatorTransformed() ? "true" : "false"); #endif ROSE_ASSERT(result_stencilEval.get_stencilOperatorTransformed() == false); #if 1 printf ("DONE: Call the StencilEvaluation traversal starting at the project (root) node of the AST \n"); #endif #if 1 shiftCalculus_StencilEvaluationTraversal.displayStencil("After evaluation of stencil"); #endif #if DEBUG_USING_DOT_GRAPHS // generateDOTforMultipleFile(*project); // generateDOT(*project,"_before_transformation"); AstDOTGeneration astdotgen_3; astdotgen_3.generateWithinFile(firstFile,DOTGeneration<SgNode*>::TOPDOWNBOTTOMUP,"_after_DSL_evaluation"); #endif #if 1 printf ("Call generateStencilCode to generate example code \n"); #endif #if 0 printf ("Exiting after the second traversal to evaluate the stencils. \n"); ROSE_ASSERT(false); #endif // Generate code from stencil data structure. bool generateLowlevelCode = true; generateStencilCode(shiftCalculus_StencilEvaluationTraversal,generateLowlevelCode); #if 1 printf ("DONE: Call generateStencilCode to generate example code \n"); #endif ROSE_ASSERT (project->get_fileList().size() ==1); SgFile * cur_file = project->get_fileList()[0]; // Generate MPI specific code if (b_gen_mpi) { //#include "mpi.h" SageInterface::insertHeader (isSgSourceFile(cur_file), "libxomp_mpi.h", false); SageInterface::insertHeader (isSgSourceFile(cur_file), "mpi.h", false); SgFunctionDeclaration* main_decl = findMain(cur_file); ROSE_ASSERT (main_decl != NULL); SgFunctionDefinition* main_def = main_decl->get_definition(); ROSE_ASSERT (main_def != NULL); SgBasicBlock* func_body = main_def->get_body(); ROSE_ASSERT (func_body != NULL); // Setup MPI SgStatement* decl_rank = buildStatementFromString("int _xomp_rank;", func_body); prependStatement(decl_rank, func_body); SgStatement* decl_nprocs= buildStatementFromString("int _xomp_nprocs;", func_body); prependStatement(decl_nprocs, func_body); // xomp_init_mpi (&argc, &argv, &_xomp_rank, &_xomp_nprocs); SgExprListExp * para_list = buildExprListExp (buildAddressOfOp (buildVarRefExp("argc", func_body)), buildAddressOfOp (buildVarRefExp("argv", func_body)), buildAddressOfOp (buildVarRefExp("_xomp_rank", func_body)), buildAddressOfOp (buildVarRefExp("_xomp_nprocs", func_body)) ); SgExprStatement* mpi_init_stmt = buildFunctionCallStmt ("xomp_init_mpi", buildIntType(), para_list, func_body); // SgStatement* last_decl = findLastDeclarationStatement (func_body); insertStatementAfter (decl_rank, mpi_init_stmt); } // Further generate CUDA code if requested if (b_gen_cuda) { // We only process one single input file at a time OmpSupport::enable_accelerator = true; cur_file->set_openmp_lowering(true); cur_file->set_openmp(true); cur_file->set_openmp_parse_only(false); // process OpenMP directives, including omp target // This will translate inserted pragmas again OmpSupport::processOpenMP(isSgSourceFile(cur_file)); #if 0 // use rose:output instead to control this // rename output file to have .cu suffice // change .c suffix to .cu suffix std::string orig_name = cur_file->get_file_info()->get_filenameString(); std::string file_suffix = StringUtility::fileNameSuffix(orig_name); // We only allow C file to be compatible with nvcc CUDA compiler //ROSE_ASSERT (CommandlineProcessing::isCFileNameSuffix(file_suffix)); orig_name = StringUtility::stripPathFromFileName(orig_name); std::string naked_name = StringUtility::stripFileSuffixFromFileName(orig_name); cur_file->set_unparse_output_filename("rose_"+naked_name+".cu"); #endif } #if 0 printf ("Exiting after call to generateStencilCode() \n"); ROSE_ASSERT(false); #endif // AST consistency tests (optional for users, but this enforces more of our tests) AstTests::runAllTests(project); #if DEBUG_USING_DOT_GRAPHS printf ("Write out the DOT file after the transformation \n"); // generateDOTforMultipleFile(*project,"after_transformation"); generateDOT(*project,"_after_transformation"); printf ("DONE: Write out the DOT file after the transformation \n"); #endif #if DEBUG_USING_DOT_GRAPHS && 0 // Output an optional graph of the AST (the whole graph, of bounded complexity, when active) // const int MAX_NUMBER_OF_IR_NODES_TO_GRAPH_FOR_WHOLE_GRAPH = 10000; generateAstGraph(project,MAX_NUMBER_OF_IR_NODES_TO_GRAPH_FOR_WHOLE_GRAPH,"_after"); #endif // Regenerate the source code but skip the call the to the vendor compiler. return backend(project); }
/* format: varname, isAny, isUniqueconst, isMultiConst, width(>=1 or 0 or -1 (for any)), min, max, numBits, "{...}" */ void FIConstAnalysis::writeCvsConstResult(VariableIdMapping& variableIdMapping, string filename) { ofstream myfile; myfile.open(filename.c_str()); // cout<<"Result:"<<endl; //VariableConstInfo vci(&variableIdMapping, &map); for(VarConstSetMap::iterator i=_varConstSetMap.begin(); i!=_varConstSetMap.end(); ++i) { VariableId varId=(*i).first; //string variableName=variableIdMapping.uniqueShortVariableName(varId); string variableName=variableIdMapping.variableName(varId); myfile<<variableName; myfile<<","; myfile<<global_variableConstInfo->isAny(varId); myfile<<","; myfile<<global_variableConstInfo->isUniqueConst(varId); myfile<<","; myfile<<global_variableConstInfo->isMultiConst(varId); myfile<<","; if(global_variableConstInfo->isUniqueConst(varId)||global_variableConstInfo->isMultiConst(varId)) { myfile<<global_variableConstInfo->minConst(varId); myfile<<","; myfile<<global_variableConstInfo->maxConst(varId); size_t mywidth=global_variableConstInfo->width(varId); assert(mywidth==(size_t)global_variableConstInfo->maxConst(varId)-global_variableConstInfo->minConst(varId)+1); int mylog2=log2(mywidth); // compute upper whole number int bits=-1; // casts on pow args to ensure that the correct overloaded C++ cmath function is selected if(mywidth==static_cast<size_t>(pow(2.0,(double)mylog2))) { if(mylog2==0) bits=1; else bits=mylog2; } else { bits=mylog2+1; } assert(bits!=-1); myfile<<","; myfile<<bits; } else { myfile<<INT_MIN <<"," <<INT_MAX <<"," <<sizeof(int)*8; } myfile<<","; // TODO: print array size // myfile<<","; SgType* varType=variableIdMapping.getType(varId); if(isSgArrayType(varType)) myfile<<"CA_ARRAY"; else if(isSgPointerType(varType)) myfile<<"CA_PTR"; else if(isSgTypeInt(varType)) myfile<<"CA_INT"; else myfile<<"CA_UNKNOWN"; myfile<<","; //myfile<<arraySize<<","; #if 1 set<CppCapsuleConstIntLattice> valueSet=(*i).second; stringstream setstr; myfile<<"{"; for(set<CppCapsuleConstIntLattice>::iterator i=valueSet.begin(); i!=valueSet.end(); ++i) { if(i!=valueSet.begin()) myfile<<","; myfile<<(*i).getValue().toString(); } myfile<<"}"; #endif myfile<<endl; } myfile.close(); }
void runAnalyses(SgProject* root, Labeler* labeler, VariableIdMapping* variableIdMapping) { SPRAY::DFAnalysisBase::normalizeProgram(root); if(option_fi_constanalysis) { VarConstSetMap varConstSetMap; FIConstAnalysis fiConstAnalysis(variableIdMapping); fiConstAnalysis.runAnalysis(root); fiConstAnalysis.attachAstAttributes(labeler,"const-analysis-inout"); // not iolabeler if(csvConstResultFileName) { cout<<"INFO: generating const CSV file "<<option_prefix+csvConstResultFileName<<endl; fiConstAnalysis.writeCvsConstResult(*variableIdMapping, option_prefix+csvConstResultFileName); } cout << "INFO: annotating analysis results as comments."<<endl; AstAnnotator ara(labeler); ara.annotateAstAttributesAsCommentsBeforeStatements(root, "const-analysis-inout"); ara.annotateAstAttributesAsCommentsAfterStatements(root, "const-analysis-inout"); } if(option_at_analysis) { cout<<"STATUS: running address taken analysis."<<endl; // compute variableId mappings VariableIdMapping variableIdMapping; variableIdMapping.computeVariableSymbolMapping(root); SPRAY::FIPointerAnalysis fipa(&variableIdMapping,root); fipa.initialize(); fipa.run(); #if 0 VariableIdSet vidset=fipa.getModByPointer(); cout<<"mod-set: "<<SPRAY::VariableIdSetPrettyPrint::str(vidset,variableIdMapping)<<endl; #endif } if(option_interval_analysis) { cout << "STATUS: creating interval analyzer."<<endl; SPRAY::IntervalAnalysis* intervalAnalyzer=new SPRAY::IntervalAnalysis(); cout << "STATUS: initializing interval analyzer."<<endl; intervalAnalyzer->initialize(root); cout << "STATUS: initializing interval transfer functions."<<endl; intervalAnalyzer->initializeTransferFunctions(); cout << "STATUS: initializing interval global variables."<<endl; intervalAnalyzer->initializeGlobalVariables(root); intervalAnalyzer->setSolverTrace(option_trace); std::string funtofind="main"; RoseAst completeast(root); SgFunctionDefinition* startFunRoot=completeast.findFunctionByName(funtofind); intervalAnalyzer->determineExtremalLabels(startFunRoot); intervalAnalyzer->run(); #if 0 intervalAnalyzer->attachInInfoToAst("iv-analysis-in"); intervalAnalyzer->attachOutInfoToAst("iv-analysis-out"); AstAnnotator ara(intervalAnalyzer->getLabeler(),intervalAnalyzer->getVariableIdMapping()); ara.annotateAstAttributesAsCommentsBeforeStatements(root, "iv-analysis-in"); ara.annotateAstAttributesAsCommentsAfterStatements(root, "iv-analysis-out"); #else AnalysisAstAnnotator ara(intervalAnalyzer->getLabeler(),intervalAnalyzer->getVariableIdMapping()); ara.annotateAnalysisPrePostInfoAsComments(root,"iv-analysis",intervalAnalyzer); #endif } if(option_lv_analysis) { cout << "STATUS: creating LV analysis."<<endl; SPRAY::LVAnalysis* lvAnalysis=new SPRAY::LVAnalysis(); cout << "STATUS: initializing LV analysis."<<endl; lvAnalysis->setBackwardAnalysis(); lvAnalysis->initialize(root); cout << "STATUS: initializing LV transfer functions."<<endl; lvAnalysis->initializeTransferFunctions(); cout << "STATUS: initializing LV global variables."<<endl; lvAnalysis->initializeGlobalVariables(root); std::string funtofind="main"; RoseAst completeast(root); SgFunctionDefinition* startFunRoot=completeast.findFunctionByName(funtofind); cout << "generating icfg_backward.dot."<<endl; write_file("icfg_backward.dot", lvAnalysis->getFlow()->toDot(lvAnalysis->getLabeler())); lvAnalysis->determineExtremalLabels(startFunRoot); lvAnalysis->run(); cout << "INFO: attaching LV-data to AST."<<endl; #if 0 lvAnalysis->attachInInfoToAst("lv-analysis-in"); lvAnalysis->attachOutInfoToAst("lv-analysis-out"); AstAnnotator ara(lvAnalysis->getLabeler(),lvAnalysis->getVariableIdMapping()); ara.annotateAstAttributesAsCommentsBeforeStatements(root, "lv-analysis-in"); ara.annotateAstAttributesAsCommentsAfterStatements(root, "lv-analysis-out"); #else AnalysisAstAnnotator ara(lvAnalysis->getLabeler(),lvAnalysis->getVariableIdMapping()); ara.annotateAnalysisPrePostInfoAsComments(root,"lv-analysis",lvAnalysis); #endif delete lvAnalysis; } if(option_rd_analysis) { cout << "STATUS: creating RD analyzer."<<endl; SPRAY::RDAnalysis* rdAnalysis=new SPRAY::RDAnalysis(); cout << "STATUS: initializing RD analyzer."<<endl; rdAnalysis->initialize(root); cout << "STATUS: initializing RD transfer functions."<<endl; rdAnalysis->initializeTransferFunctions(); cout << "STATUS: initializing RD global variables."<<endl; rdAnalysis->initializeGlobalVariables(root); cout << "generating icfg_forward.dot."<<endl; write_file("icfg_forward.dot", rdAnalysis->getFlow()->toDot(rdAnalysis->getLabeler())); std::string funtofind="main"; RoseAst completeast(root); SgFunctionDefinition* startFunRoot=completeast.findFunctionByName(funtofind); rdAnalysis->determineExtremalLabels(startFunRoot); rdAnalysis->run(); cout << "INFO: attaching RD-data to AST."<<endl; rdAnalysis->attachInInfoToAst("rd-analysis-in"); rdAnalysis->attachOutInfoToAst("rd-analysis-out"); //printAttributes<RDAstAttribute>(rdAnalysis->getLabeler(),rdAnalysis->getVariableIdMapping(),"rd-analysis-in"); cout << "INFO: annotating analysis results as comments."<<endl; ROSE_ASSERT(rdAnalysis->getVariableIdMapping()); #if 0 AstAnnotator ara(rdAnalysis->getLabeler(),rdAnalysis->getVariableIdMapping()); ara.annotateAstAttributesAsCommentsBeforeStatements(root, "rd-analysis-in"); ara.annotateAstAttributesAsCommentsAfterStatements(root, "rd-analysis-out"); #else AnalysisAstAnnotator ara(rdAnalysis->getLabeler(),rdAnalysis->getVariableIdMapping()); ara.annotateAnalysisPrePostInfoAsComments(root,"rd-analysis",rdAnalysis); #endif #if 0 cout << "INFO: substituting uses with rhs of defs."<<endl; substituteUsesWithAvailableExpRhsOfDef("ud-analysis", root, rdAnalysis->getLabeler(), rdAnalysis->getVariableIdMapping()); #endif if(option_ud_analysis) { ROSE_ASSERT(option_rd_analysis); cout << "INFO: generating and attaching UD-data to AST."<<endl; createUDAstAttributeFromRDAttribute(rdAnalysis->getLabeler(),"rd-analysis-in", "ud-analysis"); Flow* flow=rdAnalysis->getFlow(); cout<<"Flow label-set size: "<<flow->nodeLabels().size()<<endl; CFAnalysis* cfAnalyzer0=rdAnalysis->getCFAnalyzer(); int red=cfAnalyzer0->reduceBlockBeginNodes(*flow); cout<<"INFO: eliminated "<<red<<" block-begin nodes in ICFG."<<endl; #if 0 cout << "INFO: computing program statistics."<<endl; ProgramStatistics ps(rdAnalysis->getVariableIdMapping(), rdAnalysis->getLabeler(), rdAnalysis->getFlow(), "ud-analysis"); ps.computeStatistics(); //ps.printStatistics(); cout << "INFO: generating resource usage visualization."<<endl; ps.setGenerateWithSource(false); ps.generateResourceUsageICFGDotFile("resourceusageicfg.dot"); flow->resetDotOptions(); #endif cout << "INFO: generating visualization data."<<endl; // generate ICFG visualization cout << "generating icfg.dot."<<endl; write_file("icfg.dot", flow->toDot(rdAnalysis->getLabeler())); // cout << "INFO: generating control dependence graph."<<endl; //Flow cdg=rdAnalysis->getCFAnalyzer()->controlDependenceGraph(*flow); cout << "generating datadependencegraph.dot."<<endl; DataDependenceVisualizer ddvis0(rdAnalysis->getLabeler(), rdAnalysis->getVariableIdMapping(), "ud-analysis"); //printAttributes<UDAstAttribute>(rdAnalysis->getLabeler(),rdAnalysis->getVariableIdMapping(),"ud-analysis"); //ddvis._showSourceCode=false; // for large programs ddvis0.generateDefUseDotGraph(root,"datadependencegraph.dot"); flow->resetDotOptions(); cout << "generating icfgdatadependencegraph.dot."<<endl; DataDependenceVisualizer ddvis1(rdAnalysis->getLabeler(), rdAnalysis->getVariableIdMapping(), "ud-analysis"); ddvis1.includeFlowGraphEdges(flow); ddvis1.generateDefUseDotGraph(root,"icfgdatadependencegraph.dot"); flow->resetDotOptions(); cout << "generating icfgdatadependencegraph_clustered.dot."<<endl; DataDependenceVisualizer ddvis2(rdAnalysis->getLabeler(), rdAnalysis->getVariableIdMapping(), "ud-analysis"); ddvis2.generateDotFunctionClusters(root,rdAnalysis->getCFAnalyzer(),"icfgdatadependencegraph_clustered.dot",true); cout << "generating icfg_clustered.dot."<<endl; DataDependenceVisualizer ddvis3(rdAnalysis->getLabeler(), rdAnalysis->getVariableIdMapping(), "ud-analysis"); ddvis3.generateDotFunctionClusters(root,rdAnalysis->getCFAnalyzer(),"icfg_clustered.dot",false); } } }
string VariableId::toString(VariableIdMapping& vim) const { return vim.uniqueShortVariableName(*this); }