let writes_between f dsid sid =
if Hashtbl.mem wbHtbl (dsid,sid) then Hashtbl.find wbHtbl (dsid,sid) else
let dstmo = find_statement f dsid in
let stmo = find_statement f sid in
let find_write s = match s.skind with
Instr il -> List.exists (fun i ->
match i with
Set((Mem _,_),_,_) -> true
| Set((_,Index (_,_)),_,_) -> true
| Call(_,_,_,_) -> true
| _ -> false) [il]
| _ -> false
in
let visited_sid_isr = ref IS.empty in
let rec dfs goal b start =
if !debug then Cilmsg.debug "writes_between: dfs visiting %a\n" d_stmt start;
if start.sid = goal.sid then
let wh = find_write start in
(if !debug && b then (Cilmsg.debug "writes_between: start=goal and found a write\n");
if !debug && (not b) then (Cilmsg.debug "writes_between: start=goal and no write\n");
if !debug && wh then (Cilmsg.debug "writes_between: start=goal and write here\n");
if !debug && (not wh) then (Cilmsg.debug "writes_between: start=goal and no write here\n");
b || (find_write start))
else
if IS.mem start.sid (!visited_sid_isr) then false else
let w = find_write start in
if !debug && w then Cilmsg.debug "writes_between: found write %a" d_stmt start;
visited_sid_isr := IS.add start.sid (!visited_sid_isr);
let rec proc_succs sl = match sl with [] -> false
| s::rest -> if dfs goal (w || b) s then true else proc_succs rest
in
proc_succs start.succs
in
match stmo, dstmo with
None, _ | _, None -> Cilmsg.fatal "writes_between: defining stmt not an instr"
| Some stm, Some dstm ->
let _ = visited_sid_isr := IS.singleton stm.sid in
let from_stm = List.fold_left (dfs stm) false stm.succs in
let _ = visited_sid_isr := IS.empty in
let from_dstm = dfs stm false dstm in
(Hashtbl.add wbHtbl (dsid,sid) (from_stm || from_dstm);
from_stm || from_dstm)