~ubuntu-branches/debian/sid/frama-c/sid

« back to all changes in this revision

Viewing changes to src/memory_state/widen.ml

  • Committer: Bazaar Package Importer
  • Author(s): Mehdi Dogguy
  • Date: 2009-06-03 08:19:25 UTC
  • Revision ID: james.westby@ubuntu.com-20090603081925-kihvxvt0wy3zc4ar
Tags: upstream-20081201.dfsg
ImportĀ upstreamĀ versionĀ 20081201.dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
(**************************************************************************)
 
2
(*                                                                        *)
 
3
(*  This file is part of Frama-C.                                         *)
 
4
(*                                                                        *)
 
5
(*  Copyright (C) 2007-2008                                               *)
 
6
(*    CEA (Commissariat ļæ½ l'ļæ½nergie Atomique)                             *)
 
7
(*                                                                        *)
 
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.                                              *)
 
11
(*                                                                        *)
 
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.                   *)
 
16
(*                                                                        *)
 
17
(*  See the GNU Lesser General Public License version 2.1                 *)
 
18
(*  for more details (enclosed in the file licenses/LGPLv2.1).            *)
 
19
(*                                                                        *)
 
20
(**************************************************************************)
 
21
 
 
22
(* $Id: widen.ml,v 1.39 2008/10/03 13:09:17 uid568 Exp $ *)
 
23
 
 
24
open Cil
 
25
open Cil_types
 
26
open Db
 
27
open Db_types
 
28
open Abstract_value
 
29
open BaseUtils
 
30
open Cilutil
 
31
open Visitor
 
32
 
 
33
class widen_visitor kf init_widen_hints (init_enclosing_loop_info:(Cil_types.stmt list * StmtSet.t) option) =
 
34
object (* visit all sub-expressions from [kf] definition *)
 
35
  inherit Visitor.generic_frama_c_visitor
 
36
    (Project.current ()) (Cil.inplace_visit())
 
37
  val widen_hints = init_widen_hints
 
38
  val enclosing_loop_info = init_enclosing_loop_info
 
39
  method vstmt (s:stmt) =
 
40
    begin
 
41
      let infer_widen_variables bl enclosing_loop_info =
 
42
        (* Look at the if-goto and if-break statements.
 
43
           The variables of the condition are added to the
 
44
           widening variable set for this loop.
 
45
           These variables may control the loop. That may be not the case ! *)
 
46
        (* Format.printf "Look at widening variables.\n" ; *)
 
47
        let visitor = new widen_visitor kf widen_hints enclosing_loop_info
 
48
        in
 
49
        ignore (visitFramacBlock visitor bl);
 
50
        SkipChildren
 
51
      in
 
52
      begin match s.skind with
 
53
      | Loop (_, bl,_,_,_) ->
 
54
          let annot = Annotations.get s in
 
55
          let l_pragma =
 
56
            Ast_info.lift_annot_list_func
 
57
              Logic_const.extract_loop_pragma annot
 
58
          in
 
59
          let widening_stmts = match bl.bstmts with
 
60
          | [] -> [s]
 
61
          | x::_ -> [s;x]
 
62
          in
 
63
          (* Look at the loop pragmas *)
 
64
          let is_pragma_widen_variables = ref false
 
65
          in let f p =
 
66
            match p with
 
67
            | Widen_variables l ->
 
68
                let f (lv, lt) t =
 
69
                  match t with
 
70
                  | { term_node= TLval (TVar {lv_origin = Some vi}, _)} ->
 
71
                      let vid = Base.create_varinfo vi in
 
72
                      (* Format.printf "Reading user pragma for widening variable: %a.\n"
 
73
                         Base.pretty (Base.Var vi); *)
 
74
                      (vid::lv, lt)
 
75
                  | _ -> (lv, t::lt)
 
76
                in begin match List.fold_left f ([], []) l with
 
77
                | (lv, []) ->
 
78
                    (* the annotation is empty or else, there are only variables *)
 
79
                    let var_hints = List.fold_right BaseSet.add lv BaseSet.empty
 
80
                    in
 
81
                    List.iter
 
82
                      (fun widening_stmt ->
 
83
                         widen_hints :=
 
84
                           Widen_type.add_var_hints widening_stmt var_hints !widen_hints)
 
85
                      widening_stmts;
 
86
                    is_pragma_widen_variables := true
 
87
 
 
88
                | (_lv, _lt) ->
 
89
                    ignore
 
90
                      (CilE.warn_once
 
91
                         "could not interpret loop pragma relative to widening variables")
 
92
                end
 
93
            | Widen_hints l ->
 
94
                let f (lv, lnum, lt) t =
 
95
                  match t with
 
96
                  | { term_node=
 
97
                        TLval (TVar { lv_origin = Some vi}, _)} ->
 
98
                      let vid = Base.create_varinfo vi in
 
99
                      (vid::lv, lnum, lt)
 
100
                  | { term_node= TConst (CInt64(v,_,_))} ->
 
101
                      let v = Ival.Widen_Hints.V.of_int64 v
 
102
                      in (lv, v::lnum, lt)
 
103
                  | _ -> (lv, lnum, t::lt)
 
104
                in begin match List.fold_left f ([], [], []) l with
 
105
                | (lv, lnum, []) ->
 
106
                    (* the annotation is emty or else, there are only variables *)
 
107
                    let hints =
 
108
                      List.fold_right Ival.Widen_Hints.add lnum Ival.Widen_Hints.empty
 
109
                    in
 
110
                    List.iter
 
111
                      (fun key ->
 
112
                         List.iter
 
113
                           (fun widening_stmt -> widen_hints :=
 
114
                              Widen_type.add_num_hints (Some(widening_stmt))
 
115
                                (Widen_type.VarKey(key)) hints !widen_hints)
 
116
                           widening_stmts)
 
117
                      lv
 
118
                | _ ->
 
119
                    ignore (CilE.warn_once "could not interpret loop pragma relative to widening hint")
 
120
                end
 
121
            | _ -> ()
 
122
          in List.iter f l_pragma ;
 
123
          if not !is_pragma_widen_variables then
 
124
            let loop =
 
125
              try Loop.get_loop_stmts kf s
 
126
              with Loop.No_such_while -> assert false
 
127
            in
 
128
            (* There is no Widen_variables pragma for this loop. *)
 
129
            infer_widen_variables bl (Some (widening_stmts, loop))
 
130
          else
 
131
            DoChildren
 
132
      | If (exp, bl_then, bl_else, _) ->
 
133
          begin
 
134
            match enclosing_loop_info with
 
135
            | None -> ()
 
136
            | Some (widening_stmts, loop_stmts) ->
 
137
                List.iter
 
138
                  (fun bl ->
 
139
                     match bl with
 
140
                     | {bstmts = []} -> ()
 
141
                     | {bstmts =
 
142
                           ({skind = Break _; succs = [stmt]}|
 
143
                                 {skind = Goto ({contents=stmt},_)})::_}
 
144
                         when not (StmtSet.mem stmt loop_stmts) ->
 
145
                         let varinfos = extract_varinfos_from_exp exp
 
146
                         in let var_hints =
 
147
                           VarinfoSet.fold
 
148
                             (fun vi lv ->
 
149
                                (*Format.printf "Inferring pragma for widening variable: %a.\n" Base.pretty (Base.Var vi);*)
 
150
                                BaseSet.add
 
151
                                  (Base.create_varinfo vi) lv)
 
152
                             varinfos
 
153
                             BaseSet.empty
 
154
                         in
 
155
                         List.iter
 
156
                           (fun widening_stmt ->
 
157
                              widen_hints :=
 
158
                                Widen_type.add_var_hints
 
159
                                  widening_stmt
 
160
                                  var_hints
 
161
                                  !widen_hints)
 
162
                           widening_stmts
 
163
                     | _ -> ())
 
164
                  [bl_then ; bl_else]
 
165
          end;
 
166
          DoChildren ;
 
167
      | _ -> DoChildren
 
168
      end ;
 
169
    end
 
170
  method vexpr (e:exp) = begin
 
171
    let with_succ v = [v ; Ival.Widen_Hints.V.succ v]
 
172
    and with_pred v = [Ival.Widen_Hints.V.pred v ; v ]
 
173
    and with_s_p_ v = [(Ival.Widen_Hints.V.pred v) ; v ; (Ival.Widen_Hints.V.succ v)]
 
174
    and default_visit e =
 
175
      match Cil.isInteger e with
 
176
      | Some _int64 -> (*
 
177
                        let v = Ival.Widen_Hints.V.of_int64 int64
 
178
                        in widen_hints := Db.Widen_Hints.add_to_all v !widen_hints ;
 
179
                      *)
 
180
          SkipChildren
 
181
      | _ -> DoChildren
 
182
    and comparison_visit add1 add2 e1 e2 =
 
183
      let add key set =
 
184
        let hints =
 
185
          List.fold_right
 
186
            Ival.Widen_Hints.add
 
187
            set
 
188
            Ival.Widen_Hints.empty
 
189
        in
 
190
        (*Format.printf "Adding widen hint %a for base %a@\n" Ival.Widen_Hints.pretty hints
 
191
          Base.pretty key;*)
 
192
        widen_hints := Widen_type.add_num_hints None (Widen_type.VarKey key) hints !widen_hints
 
193
      in
 
194
      begin
 
195
        let e1,e2 = constFold true e1, constFold true e2 in
 
196
        match (Cil.isInteger e1, Cil.isInteger e2, e1, e2) with
 
197
        | Some int64, _, _, Lval (Var varinfo, _) ->
 
198
            add
 
199
              (Base.create_varinfo varinfo)
 
200
              (add1 (Ival.Widen_Hints.V.of_int64 int64));
 
201
            SkipChildren
 
202
        | _, Some int64, Lval (Var varinfo, _), _ ->
 
203
            add
 
204
              (Base.create_varinfo varinfo)
 
205
              (add2 (Ival.Widen_Hints.V.of_int64 int64));
 
206
            SkipChildren
 
207
        | _ -> DoChildren
 
208
      end
 
209
    in
 
210
    match e with
 
211
    | BinOp (Lt, e1, e2, _)
 
212
    | BinOp (Gt, e2, e1, _)
 
213
    | BinOp (Le, e2, e1, _)
 
214
    | BinOp (Ge, e1, e2, _) ->
 
215
        comparison_visit with_succ with_pred e1 e2
 
216
    | BinOp (Eq, e1, e2, _)
 
217
    | BinOp (Ne, e1, e2, _) ->
 
218
        comparison_visit with_s_p_ with_s_p_ e1 e2
 
219
    | _ -> default_visit e
 
220
  end
 
221
end
 
222
 
 
223
let compute_widen_hints kf _s default_widen_hints = (* [s] isn't used yet *)
 
224
  let widen_hints =
 
225
    begin
 
226
      match kf.fundec with
 
227
        | Declaration _ -> default_widen_hints
 
228
        | Definition (fd,_) ->
 
229
            begin
 
230
              let widen_hints = ref default_widen_hints
 
231
              in let visitor = new widen_visitor kf widen_hints None
 
232
              in ignore (visitFramacFunction visitor fd) ;
 
233
                !widen_hints
 
234
            end
 
235
    end
 
236
  in widen_hints
 
237
 
 
238
module Hints =
 
239
  Kernel_function.Make_Table
 
240
    (Widen_type.Datatype)
 
241
    (struct
 
242
       let name = "Widen.Hints"
 
243
       let size = 97
 
244
       let dependencies = [ Cil_state.self ]
 
245
     end)
 
246
 
 
247
let getWidenHints (kf:kernel_function) (s:stmt) =
 
248
  let widen_hints_map =
 
249
    Hints.memo (fun kf -> compute_widen_hints kf s Widen_type.default) kf
 
250
  in
 
251
  Widen_type.hints_from_keys s widen_hints_map
 
252
 
 
253
(*
 
254
Local Variables:
 
255
compile-command: "make -C ../.."
 
256
End:
 
257
*)