123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655openCilopenCabs2cil(* Helper functions *)letis_equal_varname_varidvarinfonameid=ifString.comparevarinfo.vnamename=0||varinfo.vid=idthentrueelsefalseletrecdelete_elemlists=matchlistwith|x::xs->ifString.comparexs=0thendelete_elemxsselsex::delete_elemxss|[]->[]letrecdelete_duplicateslisttbl=matchlistwith|x::xs->(let_=tryHashtbl.findtblxwithNot_found->Hashtbl.addtblx1;1inx::delete_duplicatesxstbl)|[]->[]letmap_gfunf=functionGFun(dec,loc)->fdecloc|_->Noneletmap_gvarf=function|GVar(varinfo,initinfo,loc)->fvarinfoinitinfoloc|_->Noneletis_temporaryid=Inthash.memallTempVarsidletgenerate_func_loc_tablecilfile=BatList.filter_map(map_gfun(fundecloc->Some(dec.svar.vname,loc.line)))cilfile.globalsletgenerate_globalvar_listcilfile=BatList.filter_map(map_gvar(funvarinfo__->Somevarinfo.vname))cilfile.globalsletget_all_alphaconverted_in_funvarnamefunnamecilfile=letfun_loc_table=generate_func_loc_tablecilfileinletloc_start=snd@@List.find(functionx,_->String.comparexfunname=0)fun_loc_tableinletreciter_fun_loclist=matchlistwith|(fname,_)::xs->iffname=funnamethenmatchxswith(_,line)::_->line|[]->max_intelseiter_fun_locxs|[]->0inletloc_end=iter_fun_locfun_loc_tableinlettmp=BatList.filter_map(function|EnvVarvarinfo,locwhenloc.line>=loc_start&&loc.line<loc_end->Somevarinfo.vname|_->None)(Hashtbl.find_allenvironmentvarname)indelete_duplicates(tmp@ifList.exists(functionx->String.comparexvarname=0)(generate_globalvar_listcilfile)then[varname]else[])(Hashtbl.create30)classvar_search_in_exprvarnamevaridlocresultincludeCallTmp:nopCilVisitor=objectinheritnopCilVisitormethod!vvrblinfo=ifis_equal_varname_varidinfovarnamevarid&&(includeCallTmp||not(is_temporaryinfo.vid))thenresult:=!result@[(info.vname,loc,String.trim(Pretty.sprint~width:1(d_type()info.vtype)),info.vid);]else();SkipChildrenend(* Finds a variable in an expression *)letsearch_expressionexpnamelocvaridincludeCallTmp=letresult=ref[]inletvisitor=newvar_search_in_exprnamevaridlocresultincludeCallTmpinignore(visitCilExprvisitorexp);!result(* Finds a variable in a lhost *)letsearch_lhosthostnamelocvaridincludeCallTmp=matchhostwith|Varinfo->ifis_equal_varname_varidinfonamevarid&&(includeCallTmp||not(is_temporaryinfo.vid))then[(info.vname,loc,String.trim(Pretty.sprint~width:1(d_type()info.vtype)),info.vid);]else[]|Memexp->search_expressionexpnamelocvaridincludeCallTmpletrecsearch_offsetosnamelocvaridincludeCallTmp=matchoswith|NoOffset->[]|Field(_,offset)->search_offsetoffsetnamelocvaridincludeCallTmp|Index(exp,offset)->search_expressionexpnamelocvaridincludeCallTmp@search_offsetoffsetnamelocvaridincludeCallTmp(* Finds a variable in a list of expressions *)letrecsearch_expression_listlistnamelocvaridincludeCallTmp=matchlistwith|x::xs->search_expressionxnamelocvaridincludeCallTmp@search_expression_listxsnamelocvaridincludeCallTmp|[]->[](* Finds a variable in a list of instructions *)letrecsearch_instr_list_for_varlistnamevaridincludeCallTmp=matchlistwith|Set((lhost,offset),exp,loc)::xs->search_lhostlhostnamelocvaridincludeCallTmp@search_offsetoffsetnamelocvaridincludeCallTmp@search_expressionexpnamelocvaridincludeCallTmp@search_instr_list_for_varxsnamevaridincludeCallTmp|VarDecl(info,loc)::xs->(matchinfo.vtypewith|TArray(_,Someexp,_)->search_expressionexpnamelocvaridincludeCallTmp|_->[])@ifis_equal_varname_varidinfonamevarid&&(includeCallTmp||not(is_temporaryinfo.vid))then(info.vname,loc,String.trim(Pretty.sprint~width:1(d_type()info.vtype)),info.vid)::search_instr_list_for_varxsnamevaridincludeCallTmpelsesearch_instr_list_for_varxsnamevaridincludeCallTmp|Call(Some(lhost,offset),exp,exp_list,loc)::xs->search_lhostlhostnamelocvaridincludeCallTmp@search_offsetoffsetnamelocvaridincludeCallTmp@search_expressionexpnamelocvaridincludeCallTmp@search_expression_listexp_listnamelocvaridincludeCallTmp@search_instr_list_for_varxsnamevaridincludeCallTmp|Call(None,exp,exp_list,loc)::xs->search_expressionexpnamelocvaridincludeCallTmp@search_expression_listexp_listnamelocvaridincludeCallTmp@search_instr_list_for_varxsnamevaridincludeCallTmp(* Should I consider Asm too? *)|_::xs->search_instr_list_for_varxsnamevaridincludeCallTmp|[]->[](* Finds a variable in a list of statements *)letrecsearch_stmt_list_for_varlistnamevaridincludeCallTmp=matchlistwith|x::xs->(matchx.skindwith|Instrins_list->search_instr_list_for_varins_listnamevaridincludeCallTmp|Return(Someexp,loc)->search_expressionexpnamelocvaridincludeCallTmp|ComputedGoto(exp,loc)->search_expressionexpnamelocvaridincludeCallTmp|If(exp,b1,b2,loc)->search_expressionexpnamelocvaridincludeCallTmp@search_stmt_list_for_varb1.bstmtsnamevaridincludeCallTmp@search_stmt_list_for_varb2.bstmtsnamevaridincludeCallTmp|Switch(exp,_,stmt_list,loc)->search_expressionexpnamelocvaridincludeCallTmp@search_stmt_list_for_varstmt_listnamevaridincludeCallTmp|Loop(block,_,None,None)->search_stmt_list_for_varblock.bstmtsnamevaridincludeCallTmp|Loop(block,_,None,Somes2)->search_stmt_list_for_varblock.bstmtsnamevaridincludeCallTmp@search_stmt_list_for_var[s2]namevaridincludeCallTmp|Loop(block,_,Somes1,None)->search_stmt_list_for_varblock.bstmtsnamevaridincludeCallTmp@search_stmt_list_for_var[s1]namevaridincludeCallTmp|Loop(block,_,Somes1,Somes2)->search_stmt_list_for_varblock.bstmtsnamevaridincludeCallTmp@search_stmt_list_for_var[s1]namevaridincludeCallTmp@search_stmt_list_for_var[s2]namevaridincludeCallTmp|Blockblock->search_stmt_list_for_varblock.bstmtsnamevaridincludeCallTmp|TryFinally(b1,b2,_)->search_stmt_list_for_varb1.bstmtsnamevaridincludeCallTmp@search_stmt_list_for_varb2.bstmtsnamevaridincludeCallTmp|TryExcept(b1,(instr_list,exp),b2,loc)->search_stmt_list_for_varb1.bstmtsnamevaridincludeCallTmp@search_instr_list_for_varinstr_listnamevaridincludeCallTmp@search_expressionexpnamelocvaridincludeCallTmp@search_stmt_list_for_varb2.bstmtsnamevaridincludeCallTmp|_->[])@search_stmt_list_for_varxsnamevaridincludeCallTmp|[]->[](* Finds all uses of a variable in a function-body *)letfind_uses_in_fun_vardecnamevaridincludeCallTmpcilfile=ifvarid!=-1thensearch_stmt_list_for_vardec.sbody.bstmtsnamevaridincludeCallTmpelseletlist=get_all_alphaconverted_in_funnamedec.svar.vnamecilfileinList.flatten@@List.map(funx->search_stmt_list_for_vardec.sbody.bstmtsx(-1)includeCallTmp)list(* Finds the function in which a variable shall be found *)letfind_uses_in_fun_find_funlistnamevarnamevaridincludeCallTmpcilfile=letr=BatList.find_opt(function|GFun(dec,_)->String.comparedec.svar.vnamename=0|_->false)listinmatchrwith|Some(GFun(dec,_))->find_uses_in_fun_vardecvarnamevaridincludeCallTmpcilfile|_->[](* Finds all uses of a variable in a function *)letfind_uses_in_funvarnamevaridfunnamefileincludeCallTmp=find_uses_in_fun_find_funfile.globalsfunnamevarnamevaridincludeCallTmpfileletfind_all_glob_varslist=BatList.filter_map(map_gvar(funinfo__->Someinfo.vid))list(* Finds all uses of all global variables in a function *)letfind_uses_in_fun_all_globfunnamefileincludeCallTmp=letid_list=find_all_glob_varsfile.globalsinList.flatten@@List.map(funx->find_uses_in_fun""xfunnamefileincludeCallTmp)id_listletfind_fundecglobalsfunname=letr=BatList.find_opt(function|GFun(dec,_)->String.comparedec.svar.vnamefunname=0|_->false)globalsinmatchrwithSome(GFun(dec,_))->Somedec|_->None(* Finds all uses of all variables in a function *)letfind_uses_in_fun_allfunnamefileincludeCallTmp=letflatl=List.flatten@@List.map(funx->find_uses_in_fun""xfunnamefileincludeCallTmp)linmatchfind_fundecfile.globalsfunnamewith|None->[]|Somefundec->find_uses_in_fun_all_globfunnamefileincludeCallTmp@flat(List.map(funx->x.vid)fundec.sformals)@flat(List.map(funx->x.vid)fundec.slocals)letfind_var_in_globalsvarnamevaridlist=letr=BatList.find_opt(function|GVar(info,_,_)->is_equal_varname_varidinfovarnamevarid|_->false)listinmatchrwith|Some(GVar(info,_,loc))->[(info.vname,loc,String.trim(Pretty.sprint~width:1(d_type()info.vtype)),info.vid);]|_->[](* Find all uses of a variable in all functions *)letfind_usesvarnamevaridfileincludeCallTmp=letuses_in_all_fun=List.flatten@@BatList.filter_map(map_gfun(fundec_->Some(find_uses_in_funvarnamevariddec.svar.vnamefileincludeCallTmp)))file.globalsinfind_var_in_globalsvarnamevaridfile.globals@uses_in_all_fun(* Finds all uses of global variables in all functions *)letfind_uses_all_globfileincludeCallTmp=letres=List.flatten@@BatList.filter_map(map_gfun(fundec_->Some(find_uses_in_fun_all_globdec.svar.vnamefileincludeCallTmp)))file.globalsinList.flatten(List.map(funx->find_var_in_globals""xfile.globals)(find_all_glob_varsfile.globals))@res(* Finds uses of all variables in all functions *)letfind_uses_allfileincludeCallTmp=letres=List.flatten@@BatList.filter_map(map_gfun(fundec_->Some(find_uses_in_fun_alldec.svar.vnamefileincludeCallTmp)))file.globalsinList.flatten(List.map(funx->find_var_in_globals""xfile.globals)(find_all_glob_varsfile.globals))@resletreccond_search_uses_stmt_listlistvarnamevaridincludeCallTmp=matchlistwith|x::xs->(matchx.skindwith|If(exp,b1,b2,loc)->search_expressionexpvarnamelocvaridincludeCallTmp@cond_search_uses_stmt_list(b1.bstmts@b2.bstmts)varnamevaridincludeCallTmp|Switch(exp,block,_,loc)->search_expressionexpvarnamelocvaridincludeCallTmp@cond_search_uses_stmt_listblock.bstmtsvarnamevaridincludeCallTmp|Loop(block,_,None,None)->cond_search_uses_stmt_listblock.bstmtsvarnamevaridincludeCallTmp|Loop(block,_,None,Somes1)->cond_search_uses_stmt_list(s1::block.bstmts)varnamevaridincludeCallTmp|Loop(block,_,Somes2,None)->cond_search_uses_stmt_list(s2::block.bstmts)varnamevaridincludeCallTmp|Loop(block,_,Somes2,Somes1)->cond_search_uses_stmt_list(s2::s1::block.bstmts)varnamevaridincludeCallTmp|Blockblock->cond_search_uses_stmt_listblock.bstmtsvarnamevaridincludeCallTmp|TryFinally(b1,b2,_)->cond_search_uses_stmt_list(b1.bstmts@b2.bstmts)varnamevaridincludeCallTmp|TryExcept(b1,_,b2,_)->cond_search_uses_stmt_list(b1.bstmts@b2.bstmts)varnamevaridincludeCallTmp|_->[])@cond_search_uses_stmt_listxsvarnamevaridincludeCallTmp|[]->[](* Finds all uses of a variable in conditions of a function *)letfind_uses_in_cond_in_funvarnamevaridfunnamefileincludeCallTmp=matchfind_fundecfile.globalsfunnamewith|None->[]|Somefundec->ifvarid!=-1thencond_search_uses_stmt_listfundec.sbody.bstmtsvarnamevaridincludeCallTmpelseList.flatten@@List.map(funx->cond_search_uses_stmt_listfundec.sbody.bstmtsx(-1)includeCallTmp)(get_all_alphaconverted_in_funvarnamefunnamefile)(* Finds all uses of a variable in conditions in all functions *)letfind_uses_in_condvarnamevaridfileincludeCallTmp=letreciter_functionslist=matchlistwith|GFun(dec,_)::xs->find_uses_in_cond_in_funvarnamevariddec.svar.vnamefileincludeCallTmp@iter_functionsxs|_::xs->iter_functionsxs|[]->[]initer_functionsfile.globals(* Finds all uses of global variables in conditions in all functions *)letfind_uses_in_cond_all_globfileincludeCallTmp=letid_list=find_all_glob_varsfile.globalsinList.flatten@@List.map(funx->find_uses_in_cond""xfileincludeCallTmp)id_list(* Finds all uses of global variables in conditions in a function *)letfind_uses_in_cond_in_fun_all_globfunnamefileincludeCallTmp=letid_list=find_all_glob_varsfile.globalsinList.flatten@@List.map(funx->find_uses_in_cond_in_fun""xfunnamefileincludeCallTmp)id_list(* Finds all uses of variables in conditions in a function *)letfind_uses_in_cond_in_fun_allfunnamefileincludeCallTmp=letget_formals_localsdec=dec.sformals@dec.slocalsinletfundec_opt=find_fundecfile.globalsfunnameinmatchfundec_optwith|None->[]|Somefundec->find_uses_in_cond_in_fun_all_globfunnamefileincludeCallTmp@List.flatten@@List.map(funx->find_uses_in_cond_in_funx.vname(-1)funnamefileincludeCallTmp)(get_formals_localsfundec)(* Finds all uses of variables in conditions in all functions *)letfind_uses_in_cond_allfileincludeCallTmp=List.flatten@@BatList.filter_map(map_gfun(fundec_->Some(find_uses_in_cond_in_fun_alldec.svar.vnamefileincludeCallTmp)))file.globalsletrecremove_resultlistres=matchlistwith|x::xs->ifx=resthenremove_resultxsreselsex::remove_resultxsres|[]->[](* Finds all uses of a variable in non-conditions *)letfind_uses_in_noncondvarnamevaridfileincludeCallTmp=letno_struc_result=find_usesvarnamevaridfileincludeCallTmpinletcond_result=find_uses_in_condvarnamevaridfileincludeCallTmpinList.filter(funx->not(List.memxcond_result))no_struc_result(* Finds all uses of global variables in non-conditions *)letfind_uses_in_noncond_all_globfileincludeCallTmp=letid_list=find_all_glob_varsfile.globalsinList.flatten@@List.map(funx->find_uses_in_noncond""xfileincludeCallTmp)id_list(* Finds all uses of variables in non-conditions *)letfind_uses_in_noncond_allfileincludeCallTmp=letno_struc_result=find_uses_allfileincludeCallTmpinletcond_result=find_uses_in_cond_allfileincludeCallTmpinList.filter(funx->not(List.memxcond_result))no_struc_result(* Finds the declaration of a variable in a function *)letfind_decl_in_funvarnamevaridfunnamefile=letget_formals_localsdec=dec.sformals@dec.slocalsinletiter_list_namelistname=BatList.filter_map(funx->ifString.comparex.vnamename=0&¬(is_temporaryx.vid)thenSome(x.vname,x.vdecl,String.trim(Pretty.sprint~width:1(d_type()x.vtype)),x.vid)elseNone)listinletiter_namelistname_listvarinfo_list=List.flatten@@List.map(funx->iter_list_namevarinfo_listx)name_listinmatchfind_fundecfile.globalsfunnamewith|None->[]|Somefundec->ifvarid!=-1thenBatList.filter_map(funx->ifx.vid=varidthenSome(x.vname,x.vdecl,String.trim(Pretty.sprint~width:1(d_type()x.vtype)),x.vid)elseNone)(get_formals_localsfundec)elseiter_namelist(get_all_alphaconverted_in_funvarnamefunnamefile)(get_formals_localsfundec)(* Finds all declarations in a function *)letfind_decl_in_fun_allfunnamefile=matchfind_fundecfile.globalsfunnamewith|None->[]|Somefundec->List.map(funx->(x.vname,x.vdecl,String.trim(Pretty.sprint~width:1(d_type()x.vtype)),x.vid))(fundec.sformals@fundec.slocals)(* Finds all global variable declarations *)letfind_decl_all_globfile=BatList.filter_map(map_gvar(funinfo_loc->Some(info.vname,loc,String.trim(Pretty.sprint~width:1(d_type()info.vtype)),info.vid)))file.globals(* Finds the declarations of a variable globally and in all functions *)letfind_declvarnamevaridfile=letreciter_global_declsresult=matchresultwith|(name,loc,typ,id)::xs->ifString.comparevarnamename=0||id=varidthen[(name,loc,typ,id)]elseiter_global_declsxs|[]->[]inletreciter_functionsglobals=matchglobalswith|GFun(dec,_)::xs->find_decl_in_funvarnamevariddec.svar.vnamefile@iter_functionsxs|_::xs->iter_functionsxs|[]->[]initer_global_decls(find_decl_all_globfile)@iter_functionsfile.globals(* Finds all declaration globally and in all functions *)letfind_decl_allfile=letlist=List.flatten@@BatList.filter_map(map_gfun(fundec_->Some(find_decl_in_fun_alldec.svar.vnamefile)))file.globalsinfind_decl_all_globfile@listclassvar_find_def_in_funvarnamevaridfunnameresult:nopCilVisitor=objectinheritnopCilVisitormethod!vfuncfundec=ifString.comparefundec.svar.vnamefunname=0thenDoChildrenelseSkipChildrenmethod!vinstinstr=matchinstrwith|Set((Varinfo,_),_,loc)->ifis_equal_varname_varidinfovarnamevaridthen(result:=!result@[(info.vname,loc,String.trim(Pretty.sprint~width:1(d_type()info.vtype)),info.vid);];SkipChildren)elseSkipChildren|_->SkipChildrenend(* Finds definitions of a variable in a function *)letfind_defs_in_funvarnamevaridfunnamefile=letresult=ref[]inletvisitor=newvar_find_def_in_funvarnamevaridfunnameresultinifvarid!=-1then(visitCilFileSameGlobalsvisitorfile;!result)elseletlist=get_all_alphaconverted_in_funvarnamefunnamefileinList.iter(funx->visitCilFileSameGlobals(newvar_find_def_in_funx(-1)funnameresult)file)list;!result(* Finds definitions of all global variables in a function *)letfind_defs_in_fun_all_globfunnamefile=List.flatten@@BatList.filter_map(map_gvar(funinfo__->Some(find_defs_in_fun""info.vidfunnamefile)))file.globals(* Finds definitions of all variables in a functions *)letfind_defs_in_fun_allfunnamefile=letfundec_opt=find_fundecfile.globalsfunnameinletget_formals_localsdec=dec.sformals@dec.slocalsinmatchfundec_optwith|None->[]|Somefundec->find_defs_in_fun_all_globfunnamefile@List.flatten@@List.map(funx->find_defs_in_fun""x.vidfunnamefile)(get_formals_localsfundec)(* Finds definitions of a variable in all functions *)letfind_defsvarnamevaridfile=letr=List.flatten@@BatList.filter_map(map_gfun(fundec_->Some(find_defs_in_funvarnamevariddec.svar.vnamefile)))file.globalsinfind_var_in_globalsvarnamevaridfile.globals@r(* Finds definitions of all global variables in all functions *)letfind_defs_all_globfile=List.flatten(List.map(funx->find_var_in_globals""xfile.globals)(find_all_glob_varsfile.globals))@List.flatten@@BatList.filter_map(map_gfun(fundec_->Some(find_defs_in_fun_all_globdec.svar.vnamefile)))file.globals(* Finds definitions of all variables in all functions *)letfind_defs_allfile=List.flatten(List.map(funx->find_var_in_globals""xfile.globals)(find_all_glob_varsfile.globals))@List.flatten@@BatList.filter_map(map_gfun(fundec_->Some(find_defs_in_fun_alldec.svar.vnamefile)))file.globals