1
(**************************************************************************)
3
(* This file is part of Frama-C. *)
5
(* Copyright (C) 2007-2008 *)
6
(* CEA (Commissariat � l'�nergie Atomique) *)
8
(* you can redistribute it and/or modify it under the terms of the GNU *)
9
(* Lesser General Public License as published by the Free Software *)
10
(* Foundation, version 2.1. *)
12
(* It is distributed in the hope that it will be useful, *)
13
(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)
14
(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)
15
(* GNU Lesser General Public License for more details. *)
17
(* See the GNU Lesser General Public License version 2.1 *)
18
(* for more details (enclosed in the file licenses/LGPLv2.1). *)
20
(**************************************************************************)
22
(* $Id: loop.ml,v 1.12 2008/10/03 13:09:16 uid568 Exp $ *)
29
let name = "natural_loops"
31
module Natural_Loops =
32
Kernel_function.Make_Table
34
(Datatype.Couple(Cil_datatype.Stmt)(Datatype.List(Cil_datatype.Stmt))))
38
let dependencies = [ Cil_state.self ]
41
let pretty_natural_loops fmt kf loops =
42
Format.fprintf fmt "Natural_loops for %s:@." (Kernel_function.get_name kf);
44
(fun (start,members) ->
45
Format.fprintf fmt "Loop start: %d ( " start.sid;
46
List.iter (fun d -> Format.fprintf fmt "%d " d.sid) members;
47
Format.fprintf fmt ")@\n";)
57
| Definition (cilfundec,_) ->
59
Cmdline.Debug.get () > 0 || Cmdline.Pdg.Verbosity.get() > 0
62
Format.printf "COMPUTE NATURAL LOOPS FOR %S@." (Kernel_function.get_name kf);
63
let dominators = Dominators.computeIDom cilfundec in
65
Format.printf "DONE COMPUTE NATURAL LOOPS IDOM FOR %S@."
66
(Kernel_function.get_name kf);*)
67
let naturals = Dominators.findNaturalLoops cilfundec dominators in
69
Format.printf "DONE COMPUTE NATURAL LOOPS FOR %S@."
70
(Kernel_function.get_name kf);
71
pretty_natural_loops Format.std_formatter kf naturals;
81
(fun acc (n,_) -> StmtSet.add n acc)
85
(* non natural loop over-approximation try:
86
let can_reach = !stmt_can_reach kf in *)
87
fun stmt -> let nat_loop = StmtSet.mem stmt natural_loops in
89
(* if nat_loop then nat_loop
91
if can_reach stmt stmt
92
then true (* this is non natural loop or an imbricated loop... *)
95
let back_edges kf stmt =
96
if is_natural kf stmt then
97
let rec lookup = function
99
| (s, pred_s) :: sl -> if s.sid = stmt.sid then pred_s else lookup sl
101
lookup (get_naturals kf)
105
let while_for_natural_loop kf stmt =
106
match stmt.skind with
108
| _ -> (* the while stmt is probably the non looping predecessor *)
109
let be = back_edges kf stmt in
110
Format.printf "Stmt:%d " stmt.sid;
111
List.iter (fun x -> Format.printf "B_edge:%d " x.sid) be;
112
List.iter (fun x -> Format.printf "Preds:%d " x.sid) stmt.preds;
113
let non_looping_pred =
114
List.filter (fun pred -> not (List.mem pred be)) stmt.preds
116
match non_looping_pred with
119
Format.eprintf "@.Lexical non natural loop detected !@.";
122
let compute_allstmt_block block =
124
val mutable allstmts = StmtSet.empty
125
method allstmts = allstmts
126
inherit nopCilVisitor as super
128
allstmts <- StmtSet.add s allstmts;
132
ignore (visitCilBlock (visitor:>cilVisitor) block);
135
let compute_loops_stmts kf =
136
let tbl = InstrHashtbl.create 17 in
138
inherit nopCilVisitor as super
141
| Loop (_,block,_,_,_) ->
142
InstrHashtbl.add tbl (Kstmt s) (compute_allstmt_block block)
150
(visitor :> cilVisitor) (Kernel_function.get_definition kf));
151
with Kernel_function.No_Definition ->
155
exception No_such_while
157
(** @raise No_such_while if [stmt.skind] is not a [While]. *)
160
Kernel_function.Make_Table
161
(Cil_datatype.InstrHashtbl(Cil_datatype.StmtSet))
163
let name = "LoopStmts"
165
let dependencies = [ Cil_state.self ]
169
(match loop_stmt.skind with
171
| _ -> raise No_such_while);
172
let tbl = S.memo compute_loops_stmts kf in
173
try InstrHashtbl.find tbl (Kstmt loop_stmt) with Not_found -> assert false
177
compile-command: "LC_ALL=C make -C ../.."