123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135(**************************************************************************)(* *)(* This file is part of the Frama-C's Lannotate plug-in. *)(* *)(* Copyright (C) 2012-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 LICENSE) *)(* *)(**************************************************************************)openCil_typesopenAst_constincludeAnnotators.Register(structletname="FC"lethelp="Function Coverage"(** A visitor that adds a label at the start of each function's body *)letvisitormk_label=objectinheritVisitor.frama_c_inplacemethod!vfuncdec=ifAnnotators.shouldInstrumentFundec.svarthenbeginletlabel=mk_label(Exp_builder.one())[]dec.svar.vdeclindec.sbody.bstmts<-label::dec.sbody.bstmts;end;Cil.SkipChildrenendletapplyfast=Visitor.visitFramacFileSameGlobals(visitorf)astend)moduleStringString=structtypet=string*stringletcompare=compareendmoduleHL=Set.Make(StringString)lethyperlabels=refHL.emptyletdisjunctions=Hashtbl.create100letcompute_hlcaller_callee=letdisj=String.concat"+"(List.rev(List.map(funi->"l"^string_of_inti)(Hashtbl.find_alldisjunctionscaller_callee)))inAnnotators.next_hl()^") <"^disj^"|; ;>,"letgen_hyperlabels_callcov=ref(fun()->letdata_filename=(Filename.chop_extension(Annotators.get_file_name()))^".hyperlabels"inOptions.feedback"write hyperlabel data (to %s)"data_filename;letout=open_out_gen[Open_creat;Open_append]0o644data_filenameinoutput_stringout(HL.fold(funelstr->str^(compute_hlel)^"\n")!hyperlabels"");close_outout)(** Call Coverage Visitor **)classvisitormk_label=object(self)inheritVisitor.frama_c_inplacevalmutablefname=""valmutablefloc=Cil_datatype.Location.unknownmethodprivatemk_callv=letnewStmt=mk_label(Exp_builder.one())[]flocinHashtbl.adddisjunctions(fname,v.vname)(Annotators.getCurrentLabelId());hyperlabels:=(HL.add(fname,v.vname)!hyperlabels);newStmtmethod!vfuncdec=ifAnnotators.shouldInstrumentFundec.svarthenbeginfname<-dec.svar.vname;floc<-dec.svar.vdecl;Cil.DoChildrenendelseCil.SkipChildrenmethod!vstmt_auxstmt=beginmatchstmt.skindwith|Instriwhennot(Utils.is_labeli)->beginmatchiwith|Call(_,{eid=_;enode=Lval(Varv,_);eloc=_},_,_)|Local_init(_,ConsInit(v,_,_),_)->letnewStmt=self#mk_callvinstmt.skind<-Block(Cil.mkBlock[newStmt;Stmt_builder.mkstmt.skind]);Cil.SkipChildren|_->Cil.DoChildrenend|_->Cil.DoChildrenendend(**
Call coverage annotator
*)moduleCallCov=Annotators.Register(structletname="FCC"lethelp="Function Call Coverage"letapplymk_labelfile=Visitor.visitFramacFileSameGlobals(newvisitormk_label:>Visitor.frama_c_visitor)file;!gen_hyperlabels_callcov()end)(** Nop Visitor **)classnopvisitor=object(_)inheritVisitor.frama_c_inplaceend(**
Call coverage annotator
*)moduleEmpty=Annotators.Register(structletname="Empty"lethelp="Process file but add no label"letapply_file=Visitor.visitFramacFileSameGlobals(newnopvisitor:>Visitor.frama_c_visitor)fileend)