Goto loop termination support
This commit is contained in:
parent
5a3177825f
commit
2fc13a3ec4
2 changed files with 27 additions and 6 deletions
8
examples/interval_loop/interval_goto_loop.c
Normal file
8
examples/interval_loop/interval_goto_loop.c
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
void main(){
|
||||||
|
int i = 0;
|
||||||
|
L0:
|
||||||
|
if(i >= 10) goto LF;
|
||||||
|
i++; goto L0;
|
||||||
|
LF:
|
||||||
|
assert(i >= 10);
|
||||||
|
}
|
|
@ -550,17 +550,29 @@ and stat_list (env:env) (entry:node) (exit:node) (l:stat ext list) : env =
|
||||||
stat_list env1 next exit rest
|
stat_list env1 next exit rest
|
||||||
|
|
||||||
|
|
||||||
(*
|
|
||||||
(* Decorate a function graph with widen targets until all loops have at least one *)
|
(* Decorate a function graph with widen targets until all loops have at least one *)
|
||||||
let make_widen_target (e:node) =
|
let make_widen_target (e:node) =
|
||||||
List.iter (fun x -> if(x.node_id = e.node_id) then x.widen_target <- true) !nodes
|
List.iter (fun x -> if(x.node_id = e.node_id) then x.widen_target <- true) !nodes
|
||||||
|
|
||||||
let rec ensure_widens (entry:node) =
|
module Widenator = struct
|
||||||
type color = Unseen | Opened | Visited
|
type color = Unseen | Opened | Visited
|
||||||
let type colnode = color * node in
|
type state = color NodeMap.t
|
||||||
()
|
let get_color n st = try( NodeMap.find n !st )with Not_found -> Unseen
|
||||||
*)
|
|
||||||
|
|
||||||
|
let rec ensure_widens n st =
|
||||||
|
st := NodeMap.add n Opened !st;
|
||||||
|
(List.iter (fun a -> match get_color a.arc_dst st with
|
||||||
|
| Opened -> if a.arc_dst.widen_target then () else (Format.printf "Warning : raw goto loop detected!@ "; make_widen_target a.arc_dst)
|
||||||
|
| _ -> ()) n.node_out);
|
||||||
|
(List.iter (fun a -> match get_color a.arc_dst st with
|
||||||
|
| Opened | Visited -> () (* already handled *)
|
||||||
|
| Unseen -> if a.arc_dst.widen_target then () else ensure_widens a.arc_dst st) n.node_out);
|
||||||
|
st := NodeMap.add n Visited !st
|
||||||
|
|
||||||
|
let widen_function f =
|
||||||
|
let r = ref NodeMap.empty in
|
||||||
|
ensure_widens f.func_entry r
|
||||||
|
end
|
||||||
(* Translate a function *)
|
(* Translate a function *)
|
||||||
|
|
||||||
let func (env:env) (f:fun_decl) : env =
|
let func (env:env) (f:fun_decl) : env =
|
||||||
|
@ -640,7 +652,8 @@ let prog ((t, x): prog) : cfg =
|
||||||
(* extract program info *)
|
(* extract program info *)
|
||||||
let vars = List.rev (VarSet.fold (fun a acc -> a::acc) env.env_allvars []) in
|
let vars = List.rev (VarSet.fold (fun a acc -> a::acc) env.env_allvars []) in
|
||||||
let funcs = List.rev (StringMap.fold (fun _ f acc -> f::acc) env.env_funcs []) in
|
let funcs = List.rev (StringMap.fold (fun _ f acc -> f::acc) env.env_funcs []) in
|
||||||
{ cfg_vars = vars;
|
List.iter Widenator.widen_function funcs;
|
||||||
|
{ cfg_vars = vars;
|
||||||
cfg_funcs = funcs;
|
cfg_funcs = funcs;
|
||||||
cfg_init_entry = entry;
|
cfg_init_entry = entry;
|
||||||
cfg_init_exit = exit;
|
cfg_init_exit = exit;
|
||||||
|
|
Loading…
Reference in a new issue