123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454(**************************************************************************)(* *)(* This file is part of WP plug-in of Frama-C. *)(* *)(* Copyright (C) 2007-2023 *)(* CEA (Commissariat a l'energie atomique et aux energies *)(* 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_typesopenLayoutopenRegion(* -------------------------------------------------------------------------- *)(* --- Location Compiler --- *)(* -------------------------------------------------------------------------- *)typeaddr={addrof:Region.region;typeOfPointed:typ;shift:bool;}typevalue=|Pure|Read_atoftyp*region|Addr_ofofaddr[@@@warning"-32"]letpp_valuefmt=function|Pure->Format.pp_print_stringfmt"scalar"|Read_at(_,r)->Format.fprintffmt"read %a"R.prettyr|Addr_ofa->ifa.shiftthenFormat.fprintffmt"addr %a+"R.prettya.addrofelseFormat.fprintffmt"addr %a"R.prettya.addrof[@@@warning"+32"](* -------------------------------------------------------------------------- *)(* --- Strings --- *)(* -------------------------------------------------------------------------- *)letcc_stringmapexp=letcst=Pretty_utils.to_stringCil_datatype.Exp.prettyexpinletaddrof=Region.of_cstringmap~eid:exp.eid~cstin{addrof;typeOfPointed=Cil.charType;shift=false}(* -------------------------------------------------------------------------- *)(* --- Reading Values --- *)(* -------------------------------------------------------------------------- *)letreadacs=function|Pure->()|Addr_of_->()|Read_at(tr,r)->acs_derefr(Value,tr);acs_readracsletpoints_to=function{shift;addrof=pointed;typeOfPointed=typ}->acs_derefpointed((ifshiftthenArrayelseDeref),typ)letaddrofmap=function|Pure->failwith"Wp.Region: physical address"|Read_at(tr,r)->acs_derefr(Value,tr);{addrof=add_pointedmapr;typeOfPointed=Cil.typeOf_pointedtr;shift=false;}|Addr_ofaddr->addrletcasttyvalue=ifCil.isPointerTypetythenmatchvaluewith|Addr_ofaddr->Addr_of{addrwithtypeOfPointed=Cil.typeOf_pointedty}|Read_at(_,r)->Read_at(ty,r)|Pure->Pureelsevalueletis_pointer_value=function|Pure->false|Addr_of_->true|Read_at(tr,_)->Cil.isPointerTypetrletmerge_typett'=ifCil.isVoidTypetthent'elseifCil.isVoidTypet'thentelseifCil_datatype.Typ.equaltt'thentelsefailwith"Wp.Region: merge incompatible pointer types"letmerge_addrof(map:map)v1v2=ifnot(is_pointer_valuev1)thenv2elseifnot(is_pointer_valuev2)thenv1elseleta1=addrofmapv1inleta2=addrofmapv2inlettypeOfPointed=merge_typea1.typeOfPointeda2.typeOfPointedinletaddrof=Region.aliasmapa1.addrofa2.addrofinletshift=a1.shift||a2.shiftinAddr_of{addrof;typeOfPointed;shift}(* -------------------------------------------------------------------------- *)(* --- Expressions & L-values --- *)(* -------------------------------------------------------------------------- *)letreccc_exp(map:map)exp=matchexp.enodewith|BinOp((PlusPI|MinusPI),a,b,_)->cc_readmapb;let{addrof=pointed}asaddr=cc_addrmapainacs_shiftpointed(Evalexp);Addr_of{addrwithshift=true}|AddrOflv|StartOflv->Addr_of{addrof=cc_lvalmaplv;typeOfPointed=Cil.typeOfLvallv;shift=false;}|Lvallv->Read_at(Cil.typeOfLvallv,cc_lvalmaplv)|CastE(ty,e)->castty(cc_expmape)|Const(CStr_|CWStr_)->Addr_of(cc_stringmapexp)|Const(CInt64_|CChr_|CEnum_|CReal_)|SizeOf_|SizeOfE_|SizeOfStr_|AlignOf_|AlignOfE_->Pure|UnOp(_,e,ty)->assert(not(Cil.isPointerTypety));cc_readmape;Pure|BinOp(_,a,b,ty)->assert(not(Cil.isPointerTypety));cc_readmapa;cc_readmapb;Pureandcc_hostmap=function|Varx->of_cvarmapx,x.vtype|Meme->leta=cc_addrmapeinpoints_toa;(* deref, not read !*)a.addrof,a.typeOfPointedandcc_lvalmap(host,offset)=letr,ty=cc_hostmaphostincc_offsetmaprtyoffsetandcc_offsetmaprty=function|Cil_types.NoOffset->r|Cil_types.Field(fd,ofs)->letdf=Offset.fieldfdincc_offsetmap(add_offsetmaprdf)fd.ftypeofs|Cil_types.Index(e,ofs)->cc_readmape;letde=Offset.indextyinlette=Offset.typeofdeincc_offsetmap(add_offsetmaprde)teofsandcc_addrmapa=addrofmap(cc_expmapa)andcc_readmape=read(Evale)(cc_expmape)andcc_compmape=matchcc_expmapewith|Pure|Addr_of_->failwith"Wp.Region: comp expected"|Read_at(_,r)->rletcc_writesmapstmttgttype=acs_dereftgt(Value,typ);acs_writetgt(Assignedstmt);matchCil.unrollTypetypwith|TPtr_->leta=cc_addrmapeinpoints_toa;(* deref, not read! *)do_aliasmapa.addrof(add_pointedmaptgt)|TComp_->letsrc=cc_compmapeinacs_copy~src~tgt|_->cc_readmapeletcc_assignmapstmtlve=cc_writesmapstmt(cc_lvalmaplv)(Cil.typeOfLvallv)eletcc_returnmapstmte=cc_writesmapstmt(Region.of_returnmap)(Cil.typeOfe)e(* -------------------------------------------------------------------------- *)(* --- Stmt & Instructions --- *)(* -------------------------------------------------------------------------- *)letreccc_initmapstmtlv=function|SingleInite->cc_assignmapstmtlve|CompoundInit(_,content)->List.iter(fun(ofs,vi)->cc_initmapstmt(Cil.addOffsetLvalofslv)vi)contentletcc_local_initmapstmtx=function|AssignInitvi->cc_initmapstmt(Varx,NoOffset)vi|ConsInit_->failwith"Wp.Region: cons-init not implemented"letcc_instrmapstmt=function|Set(lv,e,_)->cc_assignmapstmtlve|Call_->failwith"Wp.Region: call not implemented"|Local_init(x,vi,_)->cc_local_initmapstmtxvi|Asm_|Skip_|Code_annot_->()letcc_skindmapstmt=matchstmt.skindwith|Instrinstr->cc_instrmapstmtinstr|Return(Someve,_)->cc_returnmapstmtve|If(e,_,_,_)->cc_readmape|Switch(e,_,_,_)->cc_readmape|Return(None,_)|Goto_|Break_|Continue_|Loop_|Block_|UnspecifiedSequence_|Throw_|TryCatch_|TryFinally_|TryExcept_->()(* -------------------------------------------------------------------------- *)(* --- ACSL Terms --- *)(* -------------------------------------------------------------------------- *)letreccc_termmapt=read(Tvalt)(cc_term_valuemapt)andcc_term_value(map:map)(term:term)=matchterm.term_nodewith|TLvallv->beginmatchcc_term_lvalmaplvwith|None->Pure|Some(ty,reg)->Read_at(ty,reg)end|TAddrOflv|TStartOflv->beginmatchcc_term_lvalmaplvwith|None->failwith"Wp.Region: pure term-value"|Some(ty,reg)->Addr_of{addrof=reg;typeOfPointed=ty;shift=false;}end|TBinOp((PlusPI|MinusPI),a,b)->begincc_termmapb;let{addrof=pointed}asaddr=cc_term_addrmapainacs_shiftpointed(Tvalterm);Addr_of{addrwithshift=true}end|Tnull->Addr_of{addrof=Region.of_nullmap;typeOfPointed=Cil.charType;shift=false;}|TUnOp(_,a)->cc_termmapa;Pure|TBinOp(_,a,b)->cc_termmapa;cc_termmapb;Pure|Tat(t,_)->cc_term_valuemapt|TCastE(ty,t)->castty@@cc_term_valuemapt|TLogic_coerce(Ctypety,t)->castty@@cc_term_valuemapt|TLogic_coerce(_,t)->cc_term_valuemapt|TConst_|TSizeOf_|TSizeOfE_|TSizeOfStr_|TAlignOf_|TAlignOfE_|Ttype_|Ttypeof_->Pure|TDataCons(_,ts)->List.iter(cc_termmap)ts;Pure|TUpdate(w,ofs,v)->cc_termmapw;cc_termmapv;cc_term_offset_readmapofs;Pure|Tbase_addr(_at,t)->castCil.voidPtrType@@cc_term_valuemapt|Tblock_length(_at,t)|Toffset(_at,t)->cc_termmapt;Pure|Tif(c,a,b)->cc_termmapc;merge_addrofmap(cc_term_valuemapa)(cc_term_valuemapb)|Tempty_set->Pure|Tunionts|Tinterts->List.fold_left(funvt->merge_addrofmapv(cc_term_valuemapt))Purets|Tcomprehension(t,_,None)->cc_term_valuemapt|Tcomprehension(t,_,Somep)->cc_predmapp;cc_term_valuemapt|Trange(a,b)->cc_term_optionmapa;cc_term_optionmapb;Pure|Tlet_|Tlambda_|Tapp_->failwith"Wp.Region: unsupported logic functions and bindings"andcc_term_lvalmap(lhost,loffset)=matchlhostwith|TResulttyp->Some(typ,of_returnmap)|TVarlvar->beginmatchlvar.lv_originwith|Somex->letty,rv=cc_term_offsetmap(of_cvarmapx)x.vtypeloffsetinSome(ty,rv)|None->cc_term_offset_readmaploffset;Noneend|TMemp->beginleta=cc_term_addrmappinpoints_toa;letty,ra=cc_term_offsetmapa.addrofa.typeOfPointedloffsetinSome(ty,ra)endandcc_term_offsetmaprty=function|TNoOffset->ty,r|TField(fd,ofs)->letdf=Offset.fieldfdincc_term_offsetmap(add_offsetmaprdf)fd.ftypeofs|TIndex(t,ofs)->cc_termmapt;letde=Offset.indextyinlette=Offset.typeofdeincc_term_offsetmap(add_offsetmaprde)teofs|TModel_->failwith"Wp.Region: model field"andcc_term_offset_readmap=function|TNoOffset->()|TField(_,ofs)->cc_term_offset_readmapofs|TModel(_,ofs)->cc_term_offset_readmapofs|TIndex(t,ofs)->cc_termmapt;cc_term_offset_readmapofsandcc_term_addrmapt=addrofmap@@cc_term_valuemaptandcc_term_optionmap=functionNone->()|Somet->cc_termmapt(* -------------------------------------------------------------------------- *)(* --- ACSL Predicates --- *)(* -------------------------------------------------------------------------- *)andcc_pred(map:map)(p:predicate)=matchp.pred_contentwith|Pfalse|Ptrue->()|Prel(_,a,b)->cc_termmapa;cc_termmapb|Pnota->cc_predmapa|Pif(t,a,b)->cc_termmapt;cc_predmapa;cc_predmapb|Pand(a,b)|Por(a,b)|Pxor(a,b)|Pimplies(a,b)|Piff(a,b)->cc_predmapa;cc_predmapb|Pforall(_,p)|Pexists(_,p)->cc_predmapp|Pseparatedts->List.iter(cc_termmap)ts|Pvalid(_,t)|Pvalid_read(_,t)|Pobject_pointer(_,t)|Pvalid_functiont|Pinitialized(_,t)|Pdangling(_,t)|Pallocable(_,t)|Pfreeable(_,t)->cc_termmapt|Pfresh(_,_,ptr,n)->cc_termmapptr;cc_termmapn|Pat(p,_at)->cc_predmapp|Plet_|Papp_->failwith"Wp.Region: unsupported logic predicates and bindings"(* -------------------------------------------------------------------------- *)(* --- ACSL Spec & Defs --- *)(* -------------------------------------------------------------------------- *)classvisitormap=objectinheritVisitor.frama_c_inplaceassupermethod!vpredicatep=cc_predmapp;Cil.SkipChildrenmethod!vtermt=cc_termmapt;Cil.SkipChildrenmethod!vstmts=cc_skindmaps;super#vstmts(* vpredicate and vterm are called from vcode_annot *)(* speed up: skip non interesting subtrees *)method!vloop_pragma_=Cil.SkipChildren(* no need *)method!vvdec_=Cil.SkipChildren(* done via stmt *)method!vexpr_=Cil.SkipChildren(* done via stmt *)method!vlval_=Cil.SkipChildren(* done via stmt *)method!vattr_=Cil.SkipChildren(* done via stmt *)method!vinst_=Cil.SkipChildren(* done via stmt *)endletcc_fundecmapdef=letvisitor=newvisitormapinignore(Cil.visitCilFunction(visitor:>Cil.cilVisitor)def)letcc_specmapspec=letvisitor=newvisitormapinignore(Cil.visitCilFunspec(visitor:>Cil.cilVisitor)spec)(* -------------------------------------------------------------------------- *)(* --- L-path Iterator --- *)(* -------------------------------------------------------------------------- *)openRegionAnnotletiter_starmapftr=letpointed=add_pointedmaprinacs_derefpointed(Deref,t);fpointedletiter_shiftmapftr=letpointed=add_pointedmaprinacs_derefpointed(Array,t);frletiter_indexmapftarrr=f(add_offsetmapr(Offset.indextarr))letiter_fieldsmapffdsr=List.iter(funfd->f(add_offsetmapr(Offset.fieldfd)))fdsletreciter_lpathmapflv=matchlv.lnodewith|L_varx->f(of_cvarmapx)|L_regiona->f(of_namemapa)|L_cast(_,a)->iter_lpathmapfa|L_addra->iter_lpathmap(funr->f(get_addrofmapr))a|L_star(te,a)->iter_lpathmap(iter_starmapfte)a|L_shift(a,te,_)->iter_lpathmap(iter_shiftmapfte)a|L_index(a,_,_)->iter_lpathmap(iter_indexmapflv.ltype)a|L_field(a,fs)->iter_lpathmap(iter_fieldsmapffs)a(* -------------------------------------------------------------------------- *)(* --- Region Specs --- *)(* -------------------------------------------------------------------------- *)letcc_lpathmaprclass_rpatternlv=iter_lpathmap(Region.add_aliasmap~into:rclass)lvletcc_regionmapspec=letrclass=Region.of_classmapspec.region_nameinletrpattern=spec.region_patterninList.iter(cc_lpathmaprclassrpattern)spec.region_lpath(* -------------------------------------------------------------------------- *)