diff --git a/src/plugins/region/Region.ml b/src/plugins/region/Region.ml index f236171a3028096c948ed6c465f9bab4a979becd..f7b0628225193fc8fb2837dfe0d1925ce94a7423 100644 --- a/src/plugins/region/Region.ml +++ b/src/plugins/region/Region.ml @@ -36,12 +36,14 @@ let nodes = Memory.nodes let equal = Memory.equal let included = Memory.included let separated = Memory.separated +let singleton = Memory.singleton let size = Memory.size let roots = Memory.roots let labels = Memory.labels let reads = Memory.reads let writes = Memory.writes let shifts = Memory.shifts +let typed = Memory.typed let parents m n = Memory.nodes m @@ Memory.parents m n let points_to m n = Option.map (Memory.node m) @@ Memory.points_to m n let pointed_by m n = Memory.nodes m @@ Memory.pointed_by m n diff --git a/src/plugins/region/Region.mli b/src/plugins/region/Region.mli index c17d49d53195ff92cb7185c9d0118f1d2a898759..46e3997e0d8e2c8d3e72a5c19dcfbfafa1c6fb85 100644 --- a/src/plugins/region/Region.mli +++ b/src/plugins/region/Region.mli @@ -82,6 +82,10 @@ val labels: map -> node -> string list val reads : map -> node -> typ list val writes : map -> node -> typ list val shifts : map -> node -> typ list + +val typed : map -> node -> typ option +(** Full-sized cells with unique type access *) + val iter : map -> (node -> unit) -> unit (** {2 Alias Analysis} *) @@ -101,6 +105,11 @@ val included : map -> node -> node -> bool *) val separated : map -> node -> node -> bool + +(** [singleton m a] returns [true] when node [a] is guaranteed to have only + one single address in its equivalence class. *) +val singleton : map -> node -> bool + (** [lval m lv] is region where the address of [l] lives in. The returned region is normalized. @raises Not_found if the l-value is not localized in the map *) diff --git a/src/plugins/region/memory.ml b/src/plugins/region/memory.ml index 1a51e063d1a6ac70f11c147d11d4294039137c95..c9c75368a2f3d5f72a2cca07cc06b09aa7b230b5 100644 --- a/src/plugins/region/memory.ml +++ b/src/plugins/region/memory.ml @@ -630,16 +630,55 @@ let included map source target : bool = let separated map r1 r2 = not (included map r1 r2) && not (included map r2 r1) +let single_path m r0 r s = + match (Ufind.get m.store r0).clayout with + | Blob -> true + | Cell(s0,_) -> s = s0 + | Compound(_,_,R rgs) -> + List.for_all + (fun (rg : node Ranges.range) -> + not (Ufind.eq m.store r rg.data) || rg.length = s + ) rgs + +let rec singleton m r = + let node = Ufind.get m.store r in + (* normalized parents *) + match nodes m node.cparents with + | [] -> Vset.cardinal node.croots = 1 + | [r0] -> + Vset.is_empty node.croots && + single_path m r0 r (sizeof node.clayout) && + singleton m r0 + | _ -> false + (* -------------------------------------------------------------------------- *) -let reads (m : map) (r:node) = +let reads (m:map) (r:node) = let node = Ufind.get m.store r in List.map Access.typeof @@ Access.Set.elements node.creads -let writes (m : map) (r:node) = +let writes (m:map) (r:node) = let node = Ufind.get m.store r in List.map Access.typeof @@ Access.Set.elements node.cwrites -let shifts (m : map) (r:node) = +let shifts (m:map) (r:node) = let node = Ufind.get m.store r in List.map Access.typeof @@ Access.Set.elements node.cshifts + +let typed (m:map) (r:node) = + let types = ref None in + let node = Ufind.get m.store r in + let size = sizeof node.clayout in + try + let check acs = + let t = Access.typeof acs in + if Cil.bitsSizeOf t > size then raise Exit ; + match !types with + | None -> types := Some t + | Some t0 -> if not @@ Cil_datatype.Typ.equal t0 t then raise Exit + in + Access.Set.iter check node.creads ; + Access.Set.iter check node.cwrites ; + Access.Set.iter check node.cshifts ; + !types + with Exit -> None diff --git a/src/plugins/region/memory.mli b/src/plugins/region/memory.mli index 5485a5c974f8b2fae7c525d2077d0ab0a246c5d3..ea7949d6ed68e8dec78a71b7799140cf93534367 100644 --- a/src/plugins/region/memory.mli +++ b/src/plugins/region/memory.mli @@ -105,7 +105,9 @@ val pointed_by : map -> node -> node list val included : map -> node -> node -> bool val separated : map -> node -> node -> bool +val singleton : map -> node -> bool val reads : map -> node -> typ list val writes : map -> node -> typ list val shifts : map -> node -> typ list +val typed : map -> node -> typ option diff --git a/src/plugins/wp/RegionAnalysis.ml b/src/plugins/wp/RegionAnalysis.ml index aa173e616e704583942284c957949188fdc2e7ee..008824f22d3745c7d4ae35baaa1d7967ffbd2892 100644 --- a/src/plugins/wp/RegionAnalysis.ml +++ b/src/plugins/wp/RegionAnalysis.ml @@ -46,50 +46,33 @@ struct let pretty fmt r = Format.fprintf fmt "R%03d" @@ Region.id r end -let types map r = - let module Tset = Cil_datatype.Typ.Set in - let pool = ref Tset.empty in - let add ty = pool := Tset.add ty !pool in - List.iter add @@ Region.reads map r ; - List.iter add @@ Region.writes map r ; - List.iter add @@ Region.shifts map r ; - Tset.elements !pool - -let rec singleton map r = - match Region.parents map r with - | [] -> List.length @@ Region.roots map r = 1 - | [r] -> Region.roots map r = [] && singleton map r - | _ -> false - (* Keeping track of the decision to apply which memory model to each region *) module Kind = WpContext.Generator(Type) (struct - (* Data : WpContext.Data with type key = Key.t *) - type key = region - type data = MemRegion.kind + open MemRegion let name = "Wp.RegionAnalysis.Kind" + type key = region + type data = kind + let kind map r p = if Region.singleton map r then Single p else Many p let compile r = - let open MemRegion in let map = get_map () in - match types map r with - | [ty] when Cil.bitsSizeOf ty >= Region.size map r -> + match Region.typed map r with + | Some ty -> begin - let pkind p = if singleton map r then Single p else Many p in match Ctypes.object_of ty with - | C_int i -> pkind (Int i) - | C_float f -> pkind (Float f) - | C_pointer _ -> pkind Ptr + | C_int i -> kind map r (Int i) + | C_float f -> kind map r (Float f) + | C_pointer _ -> kind map r Ptr | _ -> Garbled end - | _ -> Garbled + | None -> Garbled end) module Name = WpContext.Generator(Type) (struct - (* Data : WpContext.Data with type key = Key.t *) + let name = "Wp.RegionAnalysis.Name" type key = region type data = string option - let name = "Wp.RegionAnalysis.Name" let compile r = let map = get_map () in match Region.labels map r with