123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188(**************************************************************************)(* *)(* This file is part of Frama-C. *)(* *)(* Copyright (C) 2007-2023 *)(* 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_typesopenVisitoropenLocationsclassvirtualdo_it_=object(self)inherit[Zone.t]Cumulative_analysis.cumulative_visitorassupervalmutableouts=Zone.bottommethodbottom=Zone.bottommethodresult=outsmethod!vstmt_auxs=matchs.skindwith|UnspecifiedSequenceseq->List.iter(fun(stmt,_,_,_,_)->ignore(visitFramacStmt(self:>frama_c_visitor)stmt))seq;Cil.SkipChildren(* do not visit the additional lvals *)|_->super#vstmt_auxsmethodjoinnew_=outs<-Zone.joinnew_outs;(* For local initializations, counts the written variable as an output of the
function, even if it is const; thus, [for_writing] is false in this case. *)methodprivatedo_assign~for_writinglv=letki=self#current_kinstrinletbits_loc=Eva.Results.(before_kinstrki|>eval_address~for_writinglv|>as_zone)inself#joinbits_locmethod!vinsti=letstmt=Option.getself#current_stmtinifEva.Results.is_reachablestmtthen(* noassert needed for Eval.memoize. Not really satisfactory *)beginletassign_lvallval=letfor_writing=not(Cil.is_mutable_or_initializedlval)inself#do_assign~for_writinglvalinmatchiwith|Set(lv,_,_)->assign_lvallv|Call(lv_opt,exp,_,_)->beginOption.iterassign_lvallv_opt;letcallees=Eva.Results.(beforestmt|>eval_calleeexp)inmatchcalleeswith|Okcallees->letjoin_outputskf=letinout=Operational_inputs.get_external_aux~stmtkfinself#joininout.over_outputsinList.iterjoin_outputscallees|Error(Top|DisabledDomain)->self#joinZone.top|ErrorBottom->()end|Local_init(v,AssignIniti,_)->letrecauxlv=function|SingleInit_->self#do_assign~for_writing:falselv|CompoundInit(ct,initl)->(* Avoid folding the implicit zero-initializers of large arrays. *)ifCumulative_analysis.fold_implicit_initializerctthenletimplicit=trueinletdoinitoi_()=aux(Cil.addOffsetLvalolv)iinCil.foldLeftCompound~implicit~doinit~ct~initl~acc:()else(* For arrays of scalar elements, all the zone covered by the
array is written. For arrays of structs containing padding
bits, this is a sound over-approximation. *)self#do_assign~for_writing:falselvinaux(Cil.varv)i|Local_init(v,ConsInit(f,_,_),_)->ifCvalue.Model.is_topEva.Results.(beforestmt|>get_cvalue_model)thenself#joinZone.topelsebeginlet{Inout_type.over_outputs=z}=Operational_inputs.get_external_aux?stmt:self#current_stmt(Globals.Functions.getf)inself#do_assign~for_writing:false(Cil.varv);(* might be redundant with z in case f takes address of
v as first argument, but this shouldn't hurt. *)self#joinzend|Asm_|Skip_|Code_annot_->()end;Cil.SkipChildrenmethodclean_kf_resultkfr=Zone.filter_base(Eva.Logic_inout.accept_base~formals:true~locals:truekf)rmethodcompute_funspeckf=letstate=self#specialize_state_on_callkfinletbehaviors=Eva.Logic_inout.valid_behaviorskfstateinletassigns=Ast_info.merge_assignsbehaviorsinEva.Logic_inout.assigns_outputs_to_zonestate~result:NoneassignsendmoduleAnalysis=Cumulative_analysis.Make(structletanalysis_name="outputs"typet=Locations.Zone.tmoduleT=Locations.Zoneclassvirtualdo_it=do_it_end)letget_internal=Analysis.kernel_functionletexternalizekfx=Zone.filter_base(Eva.Logic_inout.accept_base~formals:false~locals:falsekf)xmoduleExternals=Kernel_function.Make_Table(Locations.Zone)(structletname="Inout.Outputs.Externals"letdependencies=[Analysis.Memo.self]letsize=17end)letget_external=Externals.memo(funkf->externalizekf(get_internalkf))letpretty_internalfmtkf=tryFormat.fprintffmt"@[Out (internal) for function %a:@\n@[<hov 2> %a@]@]@\n"Kernel_function.prettykfZone.pretty(get_internalkf)withNot_found->()letpretty_externalfmtkf=tryFormat.fprintffmt"@[Out (external) for function %a:@\n@[<hov 2> %a@]@]@\n"Kernel_function.prettykfZone.pretty(get_externalkf)withNot_found->()let()=Db.Outputs.self_internal:=Analysis.Memo.self;Db.Outputs.self_external:=Externals.self;Db.Outputs.get_internal:=get_internal;Db.Outputs.get_external:=get_external;Db.Outputs.compute:=(funkf->ignore(get_internalkf));Db.Outputs.display:=pretty_internal;Db.Outputs.display_external:=pretty_external;Db.Outputs.statement:=Analysis.statement(*
Local Variables:
compile-command: "make -C ../../.."
End:
*)