diff --git a/src/plugins/region/access.ml b/src/plugins/region/access.ml index 10768c98f64c02467d77296df4b9ed64d684030b..5baa3096b5d7d24b5bcb9d4dd089fef236646816 100644 --- a/src/plugins/region/access.ml +++ b/src/plugins/region/access.ml @@ -24,19 +24,34 @@ open Cil_types open Cil_datatype type acs = + | Exp of Stmt.t * exp | Lval of Stmt.t * lval + | Init of Stmt.t * varinfo | Term of Property.t * term_lval let compare (a : acs) (b : acs) : int = match a, b with + | Init(sa,xa), Init(sb,xb) -> + let cmp = Stmt.compare sa sb in + if cmp <> 0 then cmp else Varinfo.compare xa xb + | Init _ , _ -> (-1) + | _ , Init _ -> (+1) + | Lval(sa,la), Lval(sb,lb) -> let cmp = Stmt.compare sa sb in if cmp <> 0 then cmp else Lval.compare la lb + | Lval _ , _ -> (-1) + | _ , Lval _ -> (+1) + + | Exp(sa,ea), Exp(sb,eb) -> + let cmp = Stmt.compare sa sb in + if cmp <> 0 then cmp else Exp.compare ea eb + | Exp _ , _ -> (-1) + | _ , Exp _ -> (+1) + | Term(sa,ta), Term(sb,tb) -> let cmp = Property.compare sa sb in if cmp <> 0 then cmp else Term_lval.compare ta tb - | Lval _ , Term _ -> (-1) - | Term _ , Lval _ -> (+1) let pstmt fmt (s : stmt) = match s.labels with @@ -46,10 +61,23 @@ let pstmt fmt (s : stmt) = Format.fprintf fmt "L%d" loc.pos_lnum let pretty fmt = function + | Init(s,x) -> + Format.fprintf fmt "%a@%a" Varinfo.pretty x pstmt s + | Exp(s,e) -> + Format.fprintf fmt "%a@%a" Exp.pretty e pstmt s | Lval(s,l) -> Format.fprintf fmt "%a@%a" Lval.pretty l pstmt s | Term(s,l) -> Format.fprintf fmt "%a@%s" Term_lval.pretty l (Property.Names.get_prop_name_id s) +let typeof = function + | Init(_,x) -> x.vtype + | Lval(_,lv) -> Cil.typeOfLval lv + | Exp(_,e) -> Cil.typeOf e + | Term(_,lt) -> + match Cil.typeOfTermLval lt with + | Ctype ty -> ty + | _ -> Cil.voidType + module Set = Set.Make(struct type t = acs let compare = compare end) diff --git a/src/plugins/region/access.mli b/src/plugins/region/access.mli index b36604e1bdf99383cdd5931d01870e6985621a7b..cadb24bc098a9b3908f67308bf3cd0bc39f1b7be 100644 --- a/src/plugins/region/access.mli +++ b/src/plugins/region/access.mli @@ -20,11 +20,17 @@ (* *) (**************************************************************************) +open Cil_types + type acs = - | Lval of Cil_types.stmt * Cil_types.lval - | Term of Property.t * Cil_types.term_lval + | Exp of stmt * exp + | Lval of stmt * lval + | Init of stmt * varinfo + | Term of Property.t * term_lval val compare : acs -> acs -> int val pretty : Format.formatter -> acs -> unit +val typeof : acs -> typ + module Set : Set.S with type elt = acs diff --git a/src/plugins/region/insert.ml b/src/plugins/region/insert.ml index 0da88f88ec9e16fcb671183659a387c84937a827..721feee97b2ee97b133c0bc018f24967281a0a88 100644 --- a/src/plugins/region/insert.ml +++ b/src/plugins/region/insert.ml @@ -23,20 +23,128 @@ open Cil_types open Memory -[@@@ warning "-a"] +let typeof_array_elt ty = + match Cil.unrollType ty with + | TArray(te,_,_) -> te + | _ -> Cil.voidType -let rec lval (m: map) (lv : lval) : node = +(* -------------------------------------------------------------------------- *) +(* --- L-Values & Expressions --- *) +(* -------------------------------------------------------------------------- *) + +let rec lval (m:map) (s:stmt) (lv:lval) : node = let h = fst lv in - offset m (host m h) (Cil.typeOfLhost h) (snd lv) + loffset m s (lhost m s h) (Cil.typeOfLhost h) (snd lv) -and host (m: map) = function +and lhost (m:map) (s:stmt) = function | Var x -> Memory.root m x - | Mem e -> assert false + | Mem e -> ptr m s e -and offset (m: map) (r: node) (ty: typ)= function +and loffset (m:map) (s:stmt) (r:node) (ty:typ)= function | NoOffset -> r | Field(fd,ofs) -> let size = Cil.bitsSizeOf ty in let offset, length = Cil.fieldBitsOffset fd in + let data = Memory.cell m () in + let rc = Memory.range m ~size ~offset ~length ~data in + ignore @@ Memory.merge m r rc ; loffset m s data fd.ftype ofs + | Index(_,ofs) -> + let size = Cil.bitsSizeOf ty in + let te = typeof_array_elt ty in + let data = Memory.cell m () in + let rc = Memory.range m ~size ~offset:0 ~length:size ~data in + ignore @@ Memory.merge m r rc ; loffset m s data te ofs + +and ptr m s e = + match exp m s e with None -> cell m () | Some r -> r + +and exp (m: map) (s:stmt) (e:exp) : node option = + match e.enode with + + | AddrOf lv | StartOf lv -> + let rv = lval m s lv in + Some rv + + | Lval lv -> + let rv = lval m s lv in + Memory.read m rv (Lval(s,lv)) ; + if Cil.isPointerType @@ Cil.typeOfLval lv then + let rp = cell m () in + Memory.points_to m rv rp ; + Some rp + else + None + + | UnOp(_,e,_) -> + ignore (exp m s e) ; None + + | BinOp((PlusPI|MinusPI),p,k,_) -> + ignore (exp m s k) ; + let r = ptr m s p in + Memory.shift m r (Exp(s,e)) ; + Some r + + | BinOp(_,a,b,_) -> + ignore (exp m s a) ; + ignore (exp m s b) ; + None + + | CastE(ty,p) -> + if Cil.isPointerType ty then + Some (ptr m s p) + else + (ignore (exp m s e) ; None) + + | Const _ + | SizeOf _ | SizeOfE _ | SizeOfStr _ + | AlignOf _ | AlignOfE _ + -> None + +(* -------------------------------------------------------------------------- *) +(* --- Initializers --- *) +(* -------------------------------------------------------------------------- *) + +let rec init (m:map) (s:stmt) (acs:Access.acs) (lv:lval) (iv:init) = + match iv with + + | SingleInit e -> + let r = lval m s lv in + Memory.write m r acs ; + Option.iter (Memory.points_to m r) (exp m s e) + + | CompoundInit(_,fvs) -> + List.iter + (fun (ofs,iv) -> + let lv = Cil.addOffsetLval ofs lv in + init m s acs lv iv + ) fvs + +(* -------------------------------------------------------------------------- *) +(* --- Instructions --- *) +(* -------------------------------------------------------------------------- *) + +let instr (m:map) (s:stmt) (instr:instr) = + match instr with + | Skip _ | Code_annot _ -> () + + | Set(lv,e,_) -> + let r = lval m s lv in + let v = exp m s e in + Memory.write m r (Lval(s,lv)) ; + Option.iter (Memory.points_to m r) v + + | Local_init(x,AssignInit iv,_) -> + let acs = Access.Init(s,x) in + init m s acs (Var x,NoOffset) iv + + | Call _ -> assert false - | Index(exp,ofs) -> assert false + + | Local_init(_,ConsInit _,_) -> + Options.warning ~source:(fst @@ Cil_datatype.Stmt.loc s) + "Constructor init not yet implemented" + | Asm _ -> + Options.warning ~source:(fst @@ Cil_datatype.Stmt.loc s) + "Inline assembly not supported (ignored)" + +(* -------------------------------------------------------------------------- *) diff --git a/src/plugins/region/insert.mli b/src/plugins/region/insert.mli index 664d5d2b3c7b0ff004284bfdec103bd6183e7425..9016f2094c945dcafa87b2cab066910e8b41dea2 100644 --- a/src/plugins/region/insert.mli +++ b/src/plugins/region/insert.mli @@ -19,3 +19,11 @@ (* for more details (enclosed in the file licenses/LGPLv2.1). *) (* *) (**************************************************************************) + +open Cil_types +open Memory + +val lval : map -> stmt -> lval -> node +val ptr : map -> stmt -> exp -> node +val exp : map -> stmt -> exp -> node option +val instr : map -> stmt -> instr -> unit diff --git a/src/plugins/region/memory.ml b/src/plugins/region/memory.ml index 5287fb031c73e397a6922de3213d30a614744350..98b06b38d6a1d1845152e5575ccf81c641f0c1fb 100644 --- a/src/plugins/region/memory.ml +++ b/src/plugins/region/memory.ml @@ -220,19 +220,27 @@ let merge (m: map) (a: node) (b: node) : node = (* --- Access --- *) (* -------------------------------------------------------------------------- *) +let access (m:map) (a:node) (ty: typ) = + let sr = sizeof (region m a).layout in + let size = Ranges.gcd sr (Cil.bitsSizeOf ty) in + if sr <> size then ignore (merge m a (cell m ~size ())) + let points_to (m: map) (a: node) (b: node) = ignore @@ merge m a @@ cell m ~ptr:b () let read (m: map) (a: node) from = let r = region m a in - Ufind.set m.store a { r with reads = Access.Set.add from r.reads } + Ufind.set m.store a { r with reads = Access.Set.add from r.reads } ; + access m a (Access.typeof from) let write (m: map) (a: node) from = let r = region m a in - Ufind.set m.store a { r with writes = Access.Set.add from r.writes } + Ufind.set m.store a { r with writes = Access.Set.add from r.writes } ; + access m a (Access.typeof from) let shift (m: map) (a: node) from = let r = region m a in Ufind.set m.store a { r with shifts = Access.Set.add from r.shifts } +(* no access *) (* -------------------------------------------------------------------------- *)