123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161(**************************************************************************)(* *)(* This file is part of Frama-C. *)(* *)(* Copyright (C) 2007-2025 *)(* CEA (Commissariat à l'énergie atomique et aux énergies *)(* alternatives) *)(* *)(* you can redistribute it and/or modify it under the terms of the GNU *)(* Lesser General Public License as published by the Free Software *)(* Foundation, version 2.1. *)(* *)(* It is distributed in the hope that it will be useful, *)(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)(* GNU Lesser General Public License for more details. *)(* *)(* See the GNU Lesser General Public License version 2.1 *)(* for more details (enclosed in the file licenses/LGPLv2.1). *)(* *)(**************************************************************************)openCil_typesletpretty_with_indirectfmtv=letdeps=Functionwise.getvinFrom_memory.pretty_with_type_indirect(Kernel_function.get_typev)fmtdepsletdisplayfmtopt=Option.iter(funfmt->Format.fprintffmt"@[<v>")fmtopt;Callgraph.Uses.iter_in_rev_order(funkf->ifEva.Results.is_calledkfthenletheaderfmt=Format.fprintffmt"Function %a:"Kernel_function.prettykfinletpretty=ifFrom_parameters.ShowIndirectDeps.get()thenpretty_with_indirectelseFunctionwise.prettyinmatchfmtoptwith|None->From_parameters.printf~header"@[ %a@]"prettykf|Somefmt->Format.fprintffmt"@[%t@]@ @[ %a]"headerprettykf);Option.iter(funfmt->Format.fprintffmt"@]")fmtoptmoduleSortCalls=structtypet=stmt(* Sort first by original source code location, then by sid *)letcompares1s2=letr=Cil_datatype.Location.compare(Cil_datatype.Stmt.locs1)(Cil_datatype.Stmt.locs2)inifr=0thenCil_datatype.Stmt.compares1s2(* This is not really stable, but no
good criterion is left *)elserendmoduleMapStmtCalls=Map.Make(SortCalls)letiter_callwise_calls_sortedf=lethkf=Kernel_function.Hashtbl.create17inletkglobal=refNoneinCallwise.iter(funkid->matchkiwith|Kglobal->kglobal:=Somed|Kstmts->letkf=Kernel_function.find_englobing_kfsinletm=tryKernel_function.Hashtbl.findhkfkfwithNot_found->MapStmtCalls.emptyinletm=MapStmtCalls.addsdminKernel_function.Hashtbl.replacehkfkfm);Callgraph.Uses.iter_in_rev_order(funkf->tryletm=Kernel_function.Hashtbl.findhkfkfinMapStmtCalls.iter(funsd->f(Kstmts)d)mwithNot_found->());match!kglobalwith|None->()|Somed->fKglobaldletprint_deps()=From_parameters.feedback"====== DEPENDENCIES COMPUTED ======@\n\
These dependencies hold at termination for the executions that terminate:";displayNone;From_parameters.feedback"====== END OF DEPENDENCIES ======"letprint_calldeps()=lettreat_callsfuntype=letcaller=Kernel_function.find_englobing_kfsinletf,typ_f=ifnot(Eva.Analysis.save_resultscaller)then"<unknown>",funtypeelsematchEva.Results.calleeswith|kf::_->Pretty_utils.to_stringKernel_function.prettykf,Kernel_function.get_typekf|[]->From_parameters.fatal~source:(fst(Cil_datatype.Stmt.locs))"Invalid call %a@."Printer.pp_stmtsin(funfmt->Format.fprintffmt"@[call to %s at %a (by %a)%t:@]"fCil_datatype.Location.pretty(Cil_datatype.Stmt.locs)Kernel_function.prettycaller(funfmt->ifFrom_parameters.debug_atleast1thenFormat.fprintffmt" <sid %d>"s.Cil_types.sid)),typ_finFrom_parameters.feedback"====== DISPLAYING CALLWISE DEPENDENCIES ======";iter_callwise_calls_sorted(funkid->letheader,typ=matchkiwith|Kglobal->(funfmt->Format.fprintffmt"@[entry point:@]"),Kernel_function.get_type(fst(Globals.entry_point()))|Kstmt({skind=Instr(Call(_,ekf,_,_))}ass)->treat_calls(Cil.typeOfekf)|Kstmt({skind=Instr(Local_init(_,ConsInit(f,_,_),_))}ass)->treat_callsf.vtype|_->assertfalse(* Not a call *)inFrom_parameters.printf~header"@[ %a@]"((ifFrom_parameters.ShowIndirectDeps.get()thenFrom_memory.pretty_with_type_indirectelseFrom_memory.pretty_with_type)typ)d);From_parameters.feedback"====== END OF CALLWISE DEPENDENCIES ======"letmain()=letnot_quiet=From_parameters.verbose_atleast1inifFrom_parameters.ForceDeps.get()thenFrom_parameters.ForceDeps.output(fun()->Functionwise.compute_all();print_deps(););ifFrom_parameters.ForceCallDeps.get()thenFrom_parameters.ForceCallDeps.output(fun()->Callwise.compute_all_calldeps();ifnot_quietthenprint_calldeps();)let()=Boot.Main.extendmain