Project

General

Profile

Download (28.2 KB) Statistics
| Branch: | Tag: | Revision:
1
(********************************************************************)
2
(*                                                                  *)
3
(*  The LustreC compiler toolset   /  The LustreC Development Team  *)
4
(*  Copyright 2012 -    --   ONERA - CNRS - INPT                    *)
5
(*                                                                  *)
6
(*  LustreC is free software, distributed WITHOUT ANY WARRANTY      *)
7
(*  under the terms of the GNU Lesser General Public License        *)
8
(*  version 2.1.                                                    *)
9
(*                                                                  *)
10
(********************************************************************)
11

    
12
open Utils.Format
13
open Lustre_types
14
open Machine_code_types
15
open C_backend_common
16
open Machine_code_common
17
open Corelang
18

    
19
(**************************************************************************)
20
(*     Printing spec for c *)
21

    
22
(**************************************************************************)
23
(* OLD STUFF ???
24

    
25

    
26
let pp_acsl_type var fmt t =
27
  let rec aux t pp_suffix =
28
  match (Types.repr t).Types.tdesc with
29
  | Types.Tclock t'       -> aux t' pp_suffix
30
  | Types.Tbool           -> fprintf fmt "int %s%a" var pp_suffix ()
31
  | Types.Treal           -> fprintf fmt "real %s%a" var pp_suffix ()
32
  | Types.Tint            -> fprintf fmt "int %s%a" var pp_suffix ()
33
  | Types.Tarray (d, t')  ->
34
    let pp_suffix' fmt () = fprintf fmt "%a[%a]" pp_suffix () pp_c_dimension d in
35
    aux t' pp_suffix'
36
  (* | Types.Tstatic (_, t') -> fprintf fmt "const "; aux t' pp_suffix *)
37
  (* | Types.Tconst ty       -> fprintf fmt "%s %s" ty var *)
38
  (* | Types.Tarrow (_, _)   -> fprintf fmt "void (\*%s)()" var *)
39
  | _                     -> eprintf "internal error: pp_acsl_type %a@." Types.print_ty t; assert false
40
  in aux t (fun fmt () -> ())
41

    
42
let pp_acsl_var_decl fmt id =
43
  pp_acsl_type id.var_id fmt id.var_type
44

    
45

    
46
let rec pp_eexpr is_output fmt eexpr = 
47
  let pp_eexpr = pp_eexpr is_output in
48
  match eexpr.eexpr_desc with
49
    | EExpr_const c -> Printers.pp_econst fmt c
50
    | EExpr_ident id -> 
51
      if is_output id then pp_print_string fmt ("*" ^ id) else pp_print_string fmt id
52
    | EExpr_tuple el -> Utils.fprintf_list ~sep:"," pp_eexpr fmt el
53
    | EExpr_arrow (e1, e2) -> fprintf fmt "%a -> %a" pp_eexpr e1 pp_eexpr e2
54
    | EExpr_fby (e1, e2) -> fprintf fmt "%a fby %a" pp_eexpr e1 pp_eexpr e2
55
    (* | EExpr_concat (e1, e2) -> fprintf fmt "%a::%a" pp_eexpr e1 pp_eexpr e2 *)
56
    (* | EExpr_tail e -> fprintf fmt "tail %a" pp_eexpr e *)
57
    | EExpr_pre e -> fprintf fmt "pre %a" pp_eexpr e
58
    | EExpr_when (e, id) -> fprintf fmt "%a when %s" pp_eexpr e id
59
    | EExpr_merge (id, e1, e2) -> 
60
      fprintf fmt "merge (%s, %a, %a)" id pp_eexpr e1 pp_eexpr e2
61
    | EExpr_appl (id, e, r) -> pp_eapp is_output fmt id e r
62
    | EExpr_forall (vars, e) -> fprintf fmt "forall %a; %a" Printers.pp_node_args vars pp_eexpr e 
63
    | EExpr_exists (vars, e) -> fprintf fmt "exists %a; %a" Printers.pp_node_args vars pp_eexpr e 
64

    
65

    
66
    (* | EExpr_whennot _ *)
67
    (* | EExpr_uclock _ *)
68
    (* | EExpr_dclock _ *)
69
    (* | EExpr_phclock _ -> assert false *)
70
and pp_eapp is_output fmt id e r =
71
  let pp_eexpr = pp_eexpr is_output in
72
  match r with
73
  | None ->
74
    (match id, e.eexpr_desc with
75
    | "+", EExpr_tuple([e1;e2]) -> fprintf fmt "(%a + %a)" pp_eexpr e1 pp_eexpr e2
76
    | "uminus", _ -> fprintf fmt "(- %a)" pp_eexpr e
77
    | "-", EExpr_tuple([e1;e2]) -> fprintf fmt "(%a - %a)" pp_eexpr e1 pp_eexpr e2
78
    | "*", EExpr_tuple([e1;e2]) -> fprintf fmt "(%a * %a)" pp_eexpr e1 pp_eexpr e2
79
    | "/", EExpr_tuple([e1;e2]) -> fprintf fmt "(%a / %a)" pp_eexpr e1 pp_eexpr e2
80
    | "mod", EExpr_tuple([e1;e2]) -> fprintf fmt "(%a mod %a)" pp_eexpr e1 pp_eexpr e2
81
    | "&&", EExpr_tuple([e1;e2]) -> fprintf fmt "(%a && %a)" pp_eexpr e1 pp_eexpr e2
82
    | "||", EExpr_tuple([e1;e2]) -> fprintf fmt "(%a || %a)" pp_eexpr e1 pp_eexpr e2
83
    | "xor", EExpr_tuple([e1;e2]) -> fprintf fmt "(%a ^^ %a)" pp_eexpr e1 pp_eexpr e2
84
    | "impl", EExpr_tuple([e1;e2]) -> fprintf fmt "(%a ==> %a)" pp_eexpr e1 pp_eexpr e2
85
    | "<", EExpr_tuple([e1;e2]) -> fprintf fmt "(%a < %a)" pp_eexpr e1 pp_eexpr e2
86
    | "<=", EExpr_tuple([e1;e2]) -> fprintf fmt "(%a <= %a)" pp_eexpr e1 pp_eexpr e2
87
    | ">", EExpr_tuple([e1;e2]) -> fprintf fmt "(%a > %a)" pp_eexpr e1 pp_eexpr e2
88
    | ">=", EExpr_tuple([e1;e2]) -> fprintf fmt "(%a >= %a)" pp_eexpr e1 pp_eexpr e2
89
    | "!=", EExpr_tuple([e1;e2]) -> fprintf fmt "(%a != %a)" pp_eexpr e1 pp_eexpr e2
90
    | "=", EExpr_tuple([e1;e2]) -> fprintf fmt "(%a == %a)" pp_eexpr e1 pp_eexpr e2
91
    | "not", _ -> fprintf fmt "(! %a)" pp_eexpr e
92
    | "ite", EExpr_tuple([e1;e2;e3]) -> fprintf fmt "(if %a then %a else %a)" pp_eexpr e1 pp_eexpr e2 pp_eexpr e3
93
    | _ -> fprintf fmt "%s (%a)" id pp_eexpr e)
94
  | Some x -> fprintf fmt "%s (%a) every %s" id pp_eexpr e x 
95

    
96
let pp_ensures is_output fmt e =
97
  match e with
98
    | EnsuresExpr e -> fprintf fmt "ensures %a;@ " (pp_eexpr is_output) e
99
    | SpecObserverNode (name, args) -> fprintf fmt "observer %s (%a);@ " name (Utils.fprintf_list ~sep:", " (pp_eexpr is_output)) args
100

    
101
let pp_acsl_spec outputs fmt spec =
102
  let is_output = fun oid -> List.exists (fun v -> v.var_id = oid) outputs in
103
  let pp_eexpr = pp_eexpr is_output in
104
  fprintf fmt "@[<v 2>/*@@ ";
105
  Utils.fprintf_list ~sep:"" (fun fmt r -> fprintf fmt "requires %a;@ " pp_eexpr r) fmt spec.requires;
106
  Utils.fprintf_list ~sep:"" (pp_ensures is_output) fmt spec.ensures;
107
  fprintf fmt "@ ";
108
  (* fprintf fmt "assigns *self%t%a;@ "  *)
109
  (*   (fun fmt -> if List.length outputs > 0 then fprintf fmt ", ") *)
110
  (*   (fprintf_list ~sep:"," (fun fmt v -> fprintf fmt "*%s" v.var_id)) outputs; *)
111
  Utils.fprintf_list ~sep:"@ " (fun fmt (name, assumes, requires) -> 
112
    fprintf fmt "behavior %s:@[@ %a@ %a@]" 
113
      name
114
      (Utils.fprintf_list ~sep:"@ " (fun fmt r -> fprintf fmt "assumes %a;" pp_eexpr r)) assumes
115
      (Utils.fprintf_list ~sep:"@ " (pp_ensures is_output)) requires
116
  ) fmt spec.behaviors;
117
  fprintf fmt "@]@ */@.";
118
  ()
119

    
120

    
121

    
122

    
123
let print_machine_decl_prefix fmt m =
124
   (* Print specification if any *)
125
   (match m.mspec with
126
  | None -> ()
127
  | Some spec -> 
128
    pp_acsl_spec m.mstep.step_outputs fmt spec
129
  )
130

    
131
  *)
132

    
133
   (* TODO ACSL
134
   Return updates machines (eg with local annotations) and acsl preamble *)
135
let preprocess_acsl machines = machines, []
136
                          
137
(* TODO: This preamble shall be a list of types, axiomatics, predicates, theorems *)
138
let pp_acsl_preamble fmt _preamble =
139
  Format.fprintf fmt "";
140
  ()
141

    
142
module VarDecl = struct
143
  type t = var_decl
144
  let compare v1 v2 = compare v1.var_id v2.var_id
145
end
146
module VDSet = Set.Make(VarDecl)
147

    
148
module Live = Map.Make(Int)
149

    
150
let pp_spec pp fmt =
151
  fprintf fmt "@[<v>/*%@@[<v>@,%a@]@,*/@]" pp
152

    
153
let pp_spec_cut pp fmt =
154
  fprintf fmt "%a@," (pp_spec pp)
155

    
156
let pp_spec_line pp fmt =
157
  fprintf fmt "//%@ %a@," pp
158

    
159
let pp_requires pp_req fmt =
160
  fprintf fmt "requires %a;" pp_req
161

    
162
let pp_ensures pp_ens fmt =
163
  fprintf fmt "ensures %a;" pp_ens
164

    
165
let pp_assigns pp_asg fmt =
166
  fprintf fmt "assigns %a;" pp_asg
167

    
168
let pp_ghost pp_gho fmt =
169
  fprintf fmt "ghost %a" pp_gho
170

    
171
let pp_assert pp_ast fmt =
172
  fprintf fmt "assert %a;" pp_ast
173

    
174
let pp_mem_valid pp_var fmt (name, var) =
175
  fprintf fmt "%s_valid(%a)" name pp_var var
176

    
177
let pp_mem_valid' = pp_mem_valid pp_print_string
178

    
179
let pp_indirect pp_field fmt (ptr, field) =
180
  fprintf fmt "%s->%a" ptr pp_field field
181

    
182
let pp_indirect' = pp_indirect pp_print_string
183

    
184
let pp_access pp_field fmt (stru, field) =
185
  fprintf fmt "%s.%a" stru pp_field field
186

    
187
let pp_access' = pp_access pp_print_string
188

    
189
let pp_inst self fmt (name, _) =
190
  pp_indirect' fmt (self, name)
191

    
192
let pp_true fmt () =
193
  pp_print_string fmt "\\true"
194

    
195
let pp_separated self fmt =
196
  fprintf fmt "\\separated(@[<h>%s%a@])"
197
    self
198
    (pp_print_list
199
       ~pp_prologue:pp_print_comma
200
       ~pp_sep:pp_print_comma
201
       (pp_inst self))
202

    
203
let pp_forall pp_l pp_r fmt (l, r) =
204
  fprintf fmt "@[<v 2>\\forall %a;@,%a@]"
205
    pp_l l
206
    pp_r r
207

    
208
let pp_exists pp_l pp_r fmt (l, r) =
209
  fprintf fmt "@[<v 2>\\exists %a;@,%a@]"
210
    pp_l l
211
    pp_r r
212

    
213
let pp_valid =
214
  pp_print_parenthesized
215
    ~pp_nil:pp_true
216
    ~pp_prologue:(fun fmt () -> pp_print_string fmt "\\valid")
217

    
218
let pp_equal pp_l pp_r fmt (l, r) =
219
  fprintf fmt "%a == %a"
220
    pp_l l
221
    pp_r r
222

    
223
let pp_implies pp_l pp_r fmt (l, r) =
224
  fprintf fmt "@[<v>%a ==>@ %a@]"
225
    pp_l l
226
    pp_r r
227

    
228
let pp_and pp_l pp_r fmt (l, r) =
229
  fprintf fmt "@[<v>%a @ && %a@]"
230
    pp_l l
231
    pp_r r
232

    
233
let pp_and_l pp_v fmt =
234
  pp_print_list
235
    ~pp_open_box:pp_open_vbox0
236
    ~pp_sep:(fun fmt () -> fprintf fmt "@,&& ")
237
    pp_v
238
    fmt
239

    
240
let pp_ite pp_c pp_t pp_f fmt (c, t, f) =
241
  fprintf fmt "%a @[<hov>? %a@ : %a@]"
242
    pp_c c
243
    pp_t t
244
    pp_f f
245

    
246
let pp_paren pp fmt v =
247
  fprintf fmt "(%a)" pp v
248

    
249
let pp_machine_decl fmt (id, mem_type, var) =
250
  fprintf fmt "struct %s_%s %s" id mem_type var
251

    
252
let pp_mem_ghost pp_mem pp_self ?i fmt (name, mem, self) =
253
  fprintf fmt "%s_ghost%a(@[<hov>%a,@ %a@])"
254
    name
255
    (pp_print_option pp_print_int) i
256
    pp_mem mem
257
    pp_self self
258

    
259
let pp_mem_ghost' = pp_mem_ghost pp_print_string pp_print_string
260

    
261
let pp_mem_init pp_mem fmt (name, mem) =
262
  fprintf fmt "%s_init(%a)" name pp_mem mem
263

    
264
let pp_mem_init' = pp_mem_init pp_print_string
265

    
266
let pp_var_decl fmt v =
267
  pp_print_string fmt v.var_id
268

    
269
let pp_locals m fmt vs =
270
  pp_print_list
271
    ~pp_open_box:pp_open_hbox
272
    ~pp_sep:pp_print_comma
273
    (pp_c_decl_local_var m) fmt vs
274

    
275
let pp_ptr_decl fmt v =
276
  fprintf fmt "*%s" v.var_id
277

    
278
let rec assigned s instr =
279
  let open VDSet in
280
  match instr.instr_desc with
281
  | MLocalAssign (x, _) ->
282
    add x s
283
  | MStep (xs, _, _) ->
284
    union s (of_list xs)
285
  | MBranch (_, brs) ->
286
    List.(fold_left (fun s (_, instrs) -> fold_left assigned s instrs) s brs)
287
  | _ -> s
288

    
289
let rec occur_val s v =
290
  let open VDSet in
291
  match v.value_desc with
292
  | Var x ->
293
    add x s
294
  | Fun (_, vs)
295
  | Array vs ->
296
    List.fold_left occur_val s vs
297
  | Access (v1, v2)
298
  | Power (v1, v2) ->
299
    occur_val (occur_val s v1) v2
300
  | _ -> s
301

    
302
let rec occur s instr =
303
  let open VDSet in
304
  match instr.instr_desc with
305
  | MLocalAssign (_, v)
306
  | MStateAssign (_, v) ->
307
    occur_val s v
308
  | MStep (_, _, vs) ->
309
    List.fold_left occur_val s vs
310
  | MBranch (v, brs) ->
311
    List.(fold_left (fun s (_, instrs) -> fold_left occur s instrs)
312
            (occur_val s v) brs)
313
  | _ -> s
314

    
315
let live = Hashtbl.create 32
316

    
317
let set_live_of m =
318
  let open VDSet in
319
  let locals = of_list m.mstep.step_locals in
320
  let outputs = of_list m.mstep.step_outputs in
321
  let vars = union locals outputs in
322
  let no_occur_after i =
323
    let occ, _ = List.fold_left (fun (s, j) instr ->
324
        if j <= i then (s, j+1) else (occur s instr, j+1))
325
        (empty, 0) m.mstep.step_instrs in
326
    diff locals occ
327
  in
328
  let l, _, _ = List.fold_left (fun (l, asg, i) instr ->
329
      let asg = inter (assigned asg instr) vars in
330
      Live.add (i + 1) (diff asg (no_occur_after i)) l, asg, i + 1)
331
      (Live.empty, empty, 0) m.mstep.step_instrs in
332
  Hashtbl.add live m.mname.node_id (Live.add 0 empty l)
333

    
334
let live_i m i =
335
  Live.find i (Hashtbl.find live m.mname.node_id)
336

    
337
let pp_mem_trans_aux ?i pp_mem_in pp_mem_out pp_input pp_output fmt
338
    (name, inputs, locals, outputs, mem_in, mem_out) =
339
  fprintf fmt "%s_trans%a(@[<hov>%a,@ %a%a%a%a@])"
340
    name
341
    (pp_print_option pp_print_int) i
342
    pp_mem_in mem_in
343
    (pp_print_list
344
       ~pp_epilogue:pp_print_comma
345
       ~pp_sep:pp_print_comma
346
       pp_input) inputs
347
    (pp_print_option
348
       (fun fmt _ ->
349
          pp_print_list
350
            ~pp_epilogue:pp_print_comma
351
            ~pp_sep:pp_print_comma
352
            pp_input fmt locals))
353
    i
354
    pp_mem_out mem_out
355
    (pp_print_list
356
       ~pp_prologue:pp_print_comma
357
       ~pp_sep:pp_print_comma
358
       pp_output) outputs
359

    
360
let pp_mem_trans ?i pp_mem_in pp_mem_out pp_input pp_output fmt
361
    (m, mem_in, mem_out) =
362
  let locals, outputs = match i with
363
    | Some 0 ->
364
      [], []
365
    | Some i when i < List.length m.mstep.step_instrs ->
366
      let li = live_i m i in
367
      VDSet.(inter (of_list m.mstep.step_locals) li |> elements,
368
             inter (of_list m.mstep.step_outputs) li |> elements)
369
    | Some _ ->
370
      [], m.mstep.step_outputs
371
    | _ ->
372
      m.mstep.step_locals, m.mstep.step_outputs
373
  in
374
  pp_mem_trans_aux ?i pp_mem_in pp_mem_out pp_input pp_output fmt
375
    (m.mname.node_id,
376
     m.mstep.step_inputs,
377
     locals,
378
     outputs,
379
     mem_in,
380
     mem_out)
381

    
382
let pp_mem_trans' ?i fmt =
383
  pp_mem_trans ?i pp_print_string pp_print_string pp_var_decl pp_ptr_decl fmt
384

    
385
let pp_nothing fmt () =
386
  pp_print_string fmt "\\nothing"
387

    
388
let pp_predicate pp_l pp_r fmt (l, r) =
389
  fprintf fmt "@[<v 2>predicate %a =@,%a;@]"
390
    pp_l l
391
    pp_r r
392

    
393
let print_machine_valid_predicate fmt m =
394
  if not (fst (Machine_code_common.get_stateless_status m)) then
395
    let name = m.mname.node_id in
396
    let self = mk_self m in
397
    pp_spec
398
      (pp_predicate
399
         (pp_mem_valid pp_machine_decl)
400
         (pp_and
401
            (pp_and_l (fun fmt (_, (td, _) as inst) ->
402
                 pp_mem_valid (pp_inst self) fmt (node_name td, inst)))
403
            (pp_valid pp_print_string)))
404
      fmt
405
      ((name, (name, "mem", "*" ^ self)),
406
       (m.minstances, [self]))
407

    
408
let print_machine_ghost_simulation_aux ?i m pp fmt v =
409
  let name = m.mname.node_id in
410
  let self = mk_self m in
411
  let mem = mk_mem m in
412
  pp_spec
413
    (pp_predicate
414
       (pp_mem_ghost pp_machine_decl pp_machine_decl ?i)
415
       pp)
416
    fmt
417
    ((name, (name, "mem_ghost", mem), (name, "mem", "*" ^ self)),
418
     v)
419

    
420
let print_ghost_simulation dependencies m fmt (i, instr) =
421
  let name = m.mname.node_id in
422
  let self = mk_self m in
423
  let mem = mk_mem m in
424
  let prev_ghost fmt () = pp_mem_ghost' ~i fmt (name, mem, self) in
425
  let pred pp v = pp_and prev_ghost pp fmt ((), v) in
426
  let rec aux fmt instr =
427
    match instr.instr_desc with
428
    | MStateAssign (m, _) ->
429
      pp_equal
430
        (pp_access (pp_access pp_var_decl))
431
        (pp_indirect (pp_access pp_var_decl))
432
        fmt
433
        ((mem, ("_reg", m)), (self, ("_reg", m)))
434
    | MStep ([i0], i, vl)
435
      when Basic_library.is_value_internal_fun
436
          (mk_val (Fun (i, vl)) i0.var_type)  ->
437
      pp_true fmt ()
438
    | MStep (_, i, _) when !Options.mpfr && Mpfr.is_homomorphic_fun i ->
439
      pp_true fmt ()
440
    | MStep ([_], i, _) when has_c_prototype i dependencies ->
441
      pp_true fmt ()
442
    | MStep (_, i, _)
443
    | MReset i ->
444
      begin try
445
          let n, _ = List.assoc i m.minstances in
446
          pp_mem_ghost pp_access' pp_indirect' fmt
447
            (node_name n, (mem, i), (self, i))
448
        with Not_found -> pp_true fmt ()
449
      end
450
    | MBranch (_, brs) ->
451
      (* TODO: handle branches *)
452
      pp_and_l aux fmt List.(flatten (map snd brs))
453
    | _ -> pp_true fmt ()
454
  in
455
  pred aux instr
456

    
457
let print_machine_ghost_simulation dependencies m fmt i instr =
458
  print_machine_ghost_simulation_aux m
459
    (print_ghost_simulation dependencies m)
460
    ~i:(i+1)
461
    fmt (i, instr)
462

    
463
let print_machine_ghost_struct fmt m =
464
  pp_spec (pp_ghost (print_machine_struct ~ghost:true)) fmt m
465

    
466
let print_machine_ghost_simulations dependencies fmt m =
467
  if not (fst (Machine_code_common.get_stateless_status m)) then
468
    let name = m.mname.node_id in
469
    let self = mk_self m in
470
    let mem = mk_mem m in
471
    fprintf fmt "%a@,%a@,%a%a"
472
      print_machine_ghost_struct m
473
      (print_machine_ghost_simulation_aux m pp_true ~i:0) ()
474
      (pp_print_list_i
475
        ~pp_epilogue:pp_print_cut
476
        ~pp_open_box:pp_open_vbox0
477
        (print_machine_ghost_simulation dependencies m))
478
      m.mstep.step_instrs
479
      (print_machine_ghost_simulation_aux m
480
         (pp_mem_ghost' ~i:(List.length m.mstep.step_instrs))) (name, mem, self)
481

    
482
let pp_basic_assign_spec pp_var fmt typ var_name value =
483
  if Types.is_real_type typ && !Options.mpfr
484
  then
485
    assert false
486
    (* Mpfr.pp_inject_assign pp_var fmt (var_name, value) *)
487
  else
488
    pp_equal pp_var pp_var fmt (var_name, value)
489

    
490
let pp_assign_spec m self pp_var fmt (var_type, var_name, value) =
491
  let depth = expansion_depth value in
492
  let loop_vars = mk_loop_variables m var_type depth in
493
  let reordered_loop_vars = reorder_loop_variables loop_vars in
494
  let rec aux typ fmt vars =
495
    match vars with
496
    | [] ->
497
      pp_basic_assign_spec
498
        (pp_value_suffix ~indirect:false m self var_type loop_vars pp_var)
499
        fmt typ var_name value
500
    | (d, LVar i) :: q ->
501
      assert false
502
      (* let typ' = Types.array_element_type typ in
503
       * fprintf fmt "@[<v 2>{@,int %s;@,for(%s=0;%s<%a;%s++)@,%a @]@,}"
504
       *   i i i pp_c_dimension d i
505
       *   (aux typ') q *)
506
    | (d, LInt r) :: q ->
507
      assert false
508
      (* let typ' = Types.array_element_type typ in
509
       * let szl = Utils.enumerate (Dimension.size_const_dimension d) in
510
       * fprintf fmt "@[<v 2>{@,%a@]@,}"
511
       *   (pp_print_list (fun fmt i -> r := i; aux typ' fmt q)) szl *)
512
    | _ -> assert false
513
  in
514
  begin
515
    reset_loop_counter ();
516
    aux var_type fmt reordered_loop_vars;
517
  end
518

    
519
let print_machine_trans_simulation_aux ?i m pp fmt v =
520
  let name = m.mname.node_id in
521
  let mem_in = mk_mem_in m in
522
  let mem_out = mk_mem_out m in
523
  pp_spec
524
    (pp_predicate
525
       (pp_mem_trans pp_machine_decl pp_machine_decl
526
          (pp_c_decl_local_var m) pp_c_decl_output_var ?i)
527
       pp)
528
    fmt
529
    ((m, (name, "mem_ghost", mem_in), (name, "mem_ghost", mem_out)),
530
     v)
531

    
532
let print_trans_simulation machines dependencies m fmt (i, instr) =
533
  let mem_in = mk_mem_in m in
534
  let mem_out = mk_mem_out m in
535
  let d = VDSet.(diff (live_i m i) (live_i m (i+1))) in
536
  printf "%d : %a\n%d : %a\n\n"
537
    i
538
    (pp_print_parenthesized pp_var_decl) (VDSet.elements (live_i m i))
539
    (i+1)
540
    (pp_print_parenthesized pp_var_decl) (VDSet.elements (live_i m (i+1)));
541
  let prev_trans fmt () = pp_mem_trans' ~i fmt (m, mem_in, mem_out) in
542
  let pred pp v =
543
    let locals = VDSet.(inter (of_list m.mstep.step_locals) d |> elements) in
544
    if locals = []
545
    then pp_and prev_trans pp fmt ((), v)
546
    else pp_exists (pp_locals m) (pp_and prev_trans pp) fmt (locals, ((), v))
547
  in
548
  let rec aux fmt instr = match instr.instr_desc with
549
    | MLocalAssign (x, v)
550
    | MStateAssign (x, v) ->
551
      pp_assign_spec m mem_in (pp_c_var_read m) fmt
552
        (x.var_type, mk_val (Var x) x.var_type, v)
553
    | MStep ([i0], i, vl)
554
      when Basic_library.is_value_internal_fun
555
          (mk_val (Fun (i, vl)) i0.var_type)  ->
556
      pp_true fmt ()
557
    | MStep (_, i, _) when !Options.mpfr && Mpfr.is_homomorphic_fun i ->
558
      pp_true fmt ()
559
    | MStep ([_], i, _) when has_c_prototype i dependencies ->
560
      pp_true fmt ()
561
    | MStep (xs, f, ys) ->
562
      begin try
563
          let n, _ = List.assoc f m.minstances in
564
            pp_mem_trans_aux
565
              pp_access' pp_access'
566
              (pp_c_val m mem_in (pp_c_var_read m))
567
              pp_var_decl
568
              fmt
569
              (node_name n, ys, [], xs, (mem_in, f), (mem_out, f))
570
        with Not_found -> pp_true fmt ()
571
      end
572
    | MReset f ->
573
      begin try
574
          let n, _ = List.assoc f m.minstances in
575
          pp_mem_init' fmt (node_name n, mem_out)
576
        with Not_found -> pp_true fmt ()
577
      end
578
    | MBranch (v, brs) ->
579
      (* TODO: handle branches *)
580
      pp_and_l (fun fmt (l, instrs) ->
581
          pp_paren (pp_implies
582
                      (pp_equal
583
                         (pp_c_val m mem_in (pp_c_var_read m))
584
                         pp_print_string)
585
                      (pp_and_l aux))
586
            fmt
587
            ((v, l), instrs))
588
        fmt brs
589
    | _ -> pp_true fmt ()
590
  in
591
  pred aux instr
592

    
593
let print_machine_trans_simulation machines dependencies m fmt i instr =
594
  print_machine_trans_simulation_aux m
595
    (print_trans_simulation machines dependencies m)
596
    ~i:(i+1)
597
    fmt (i, instr)
598

    
599
let print_machine_core_annotations machines dependencies fmt m =
600
  if not (fst (Machine_code_common.get_stateless_status m)) then begin
601
    set_live_of m;
602
    let i = List.length m.mstep.step_instrs in
603
    let mem_in = mk_mem_in m in
604
    let mem_out = mk_mem_out m in
605
    let last_trans fmt () =
606
      let locals = VDSet.(inter
607
                            (of_list m.mstep.step_locals)
608
                            (live_i m i)
609
                          |> elements) in
610
      if locals = []
611
      then pp_mem_trans' ~i fmt (m, mem_in, mem_out)
612
      else pp_exists (pp_locals m) (pp_mem_trans' ~i) fmt
613
          (locals, (m, mem_in, mem_out))
614
    in
615
    fprintf fmt "%a@,%a%a"
616
      (print_machine_trans_simulation_aux m pp_true ~i:0) ()
617
      (pp_print_list_i
618
        ~pp_epilogue:pp_print_cut
619
        ~pp_open_box:pp_open_vbox0
620
        (print_machine_trans_simulation machines dependencies m))
621
      m.mstep.step_instrs
622
      (print_machine_trans_simulation_aux m last_trans) ()
623
  end
624

    
625
let pp_at pp_p fmt (p, l) =
626
  fprintf fmt "\\at(%a, %s)" pp_p p l
627

    
628
let label_pre = "Pre"
629

    
630
let pp_at_pre pp_p fmt p =
631
  pp_at pp_p fmt (p, label_pre)
632

    
633
let pp_arrow_spec fmt () =
634
  let name = "_arrow" in
635
  let mem_in = "mem_in" in
636
  let mem_out = "mem_out" in
637
  let reg_first = "_reg", "_first" in
638
  let mem_in_first = mem_in, reg_first in
639
  let mem_out_first = mem_out, reg_first in
640
  let mem = "mem" in
641
  let self = "self" in
642
  fprintf fmt "/* ACSL arrow spec */@,%a%a%a%a"
643
    (pp_spec_line (pp_ghost pp_print_string))
644
    "struct _arrow_mem_ghost {struct _arrow_reg _reg;};"
645
    (pp_spec_cut
646
       (pp_predicate
647
          (pp_mem_init pp_machine_decl)
648
          (pp_equal
649
             (pp_access pp_access')
650
             pp_print_string)))
651
    ((name, (name, "mem_ghost", mem_in)),
652
     (mem_in_first, "true"))
653
    (pp_spec_cut
654
       (pp_predicate
655
          (pp_mem_trans_aux
656
             pp_machine_decl pp_machine_decl pp_print_string pp_print_string)
657
          (pp_ite
658
             (pp_access pp_access')
659
             (pp_paren
660
                (pp_and
661
                   (pp_equal
662
                      (pp_access pp_access')
663
                      pp_print_string)
664
                   (pp_equal pp_print_string pp_print_string)))
665
                (pp_paren
666
                   (pp_and
667
                      (pp_equal
668
                         (pp_access pp_access')
669
                         (pp_access pp_access'))
670
                      (pp_equal pp_print_string pp_print_string))))))
671
    ((name, ["int x"; "int y"], [], ["_Bool out"],
672
      (name, "mem_ghost", mem_in), (name, "mem_ghost", mem_out)),
673
     (* (("out", mem_in_first), *)
674
     (mem_in_first, ((mem_out_first, "false"), ("out", "x")),
675
      ((mem_out_first, mem_in_first), ("out", "y"))))
676
    (pp_spec_cut
677
       (pp_predicate
678
          (pp_mem_ghost pp_machine_decl pp_machine_decl)
679
          (pp_equal
680
             (pp_access pp_access')
681
             (pp_indirect pp_access'))))
682
    ((name, (name, "mem_ghost", mem), (name, "mem", "*" ^ self)),
683
    ((mem, reg_first), (self, reg_first)))
684

    
685
module SrcMod = struct
686

    
687
  let pp_predicates dependencies fmt machines =
688
    fprintf fmt
689
      "%a@,%a%a%a"
690
      pp_arrow_spec ()
691
      (pp_print_list
692
         ~pp_open_box:pp_open_vbox0
693
         ~pp_prologue:(pp_print_endcut "/* ACSL `valid` predicates */")
694
         print_machine_valid_predicate
695
         ~pp_epilogue:pp_print_cutcut) machines
696
      (pp_print_list
697
         ~pp_open_box:pp_open_vbox0
698
         ~pp_sep:pp_print_cutcut
699
         ~pp_prologue:(pp_print_endcut "/* ACSL ghost simulations */")
700
         (print_machine_ghost_simulations dependencies)
701
         ~pp_epilogue:pp_print_cutcut) machines
702
      (pp_print_list
703
         ~pp_open_box:pp_open_vbox0
704
         ~pp_sep:pp_print_cutcut
705
         ~pp_prologue:(pp_print_endcut "/* ACSL core annotations */")
706
         (print_machine_core_annotations machines dependencies)
707
         ~pp_epilogue:pp_print_cutcut) machines
708

    
709
  let pp_reset_spec fmt self m =
710
    let name = m.mname.node_id in
711
    let mem = mk_mem m in
712
    pp_spec_cut (fun fmt () ->
713
        fprintf fmt
714
          "%a@,%a@,%a@,%a"
715
          (pp_requires pp_mem_valid') (name, self)
716
          (pp_requires (pp_separated self)) m.minstances
717
          (pp_assigns
718
             (pp_print_list
719
                ~pp_sep:pp_print_comma
720
                ~pp_nil:pp_nothing
721
                (pp_inst self))) m.minstances
722
          (pp_ensures
723
             (pp_forall
724
                pp_machine_decl
725
                (pp_implies
726
                   pp_mem_ghost'
727
                   pp_mem_init')))
728
          ((name, "mem_ghost", mem),
729
           ((name, mem, self), (name, mem))))
730
      fmt ()
731

    
732
  let pp_step_spec fmt self m =
733
    let name = m.mname.node_id in
734
    let mem_in = mk_mem_in m in
735
    let mem_out = mk_mem_out m in
736
    pp_spec_cut (fun fmt () ->
737
        fprintf fmt
738
          "%a@,%a@,%a@,%a@,%a"
739
          (pp_requires (pp_valid pp_var_decl)) m.mstep.step_outputs
740
          (pp_requires pp_mem_valid') (name, self)
741
          (pp_requires (pp_separated self)) m.minstances
742
          (pp_assigns
743
             (if m.mstep.step_outputs = [] && m.minstances = [] then
744
                pp_nothing
745
              else
746
                fun fmt () ->
747
                  fprintf fmt "@[<h>%a%a@]"
748
                    (pp_print_list
749
                       ~pp_sep:pp_print_comma
750
                       ~pp_epilogue:pp_print_comma
751
                       pp_ptr_decl) m.mstep.step_outputs
752
                    (pp_print_list
753
                       ~pp_sep:pp_print_comma
754
                       (pp_inst self)) m.minstances)) ()
755
          (pp_ensures
756
             (pp_forall
757
                (fun fmt () ->
758
                   fprintf fmt "%a, %s"
759
                     pp_machine_decl (name, "mem_ghost", mem_in)
760
                     mem_out)
761
                (pp_implies
762
                   (pp_at_pre pp_mem_ghost')
763
                   (pp_implies
764
                      pp_mem_ghost'
765
                      pp_mem_trans'))))
766
          ((),
767
           ((name, mem_in, self),
768
            ((name, mem_out, self),
769
             (m, mem_in, mem_out)))))
770
      fmt ()
771

    
772
  let pp_step_instr_spec m self fmt (i, _instr) =
773
    let name = m.mname.node_id in
774
    let mem_in = mk_mem_in m in
775
    let mem_out = mk_mem_out m in
776
    fprintf fmt "@,%a"
777
      (pp_spec
778
         (pp_assert
779
            (pp_forall
780
               (fun fmt () ->
781
                  fprintf fmt "%a, %s"
782
                    pp_machine_decl (name, "mem_ghost", mem_in)
783
                    mem_out)
784
               (pp_implies
785
                  (pp_at_pre pp_mem_ghost')
786
                  (pp_implies
787
                     (pp_mem_ghost' ~i)
788
                     (pp_mem_trans' ~i))))))
789
      ((),
790
       ((name, mem_in, self),
791
        ((name, mem_out, self),
792
         (m, mem_in, mem_out))))
793

    
794
end
795

    
796
(**************************************************************************)
797
(*                              MAKEFILE                                  *)
798
(**************************************************************************)
799

    
800
module MakefileMod = struct
801

    
802
  let other_targets fmt basename _nodename dependencies =
803
    fprintf fmt "FRAMACEACSL=`frama-c -print-share-path`/e-acsl@.";
804
    (* EACSL version of library file . c *)
805
    fprintf fmt "%s_eacsl.c: %s.c %s.h@." basename basename basename;
806
    fprintf fmt
807
      "\tframa-c -e-acsl-full-mmodel -machdep x86_64 -e-acsl %s.c -then-on e-acsl -print -ocode %s_eacsl.c@."
808
      basename basename;
809
    fprintf fmt "@.";
810
    fprintf fmt "@.";
811

    
812
    (* EACSL version of library file . c + main .c  *)
813
    fprintf fmt "%s_main_eacsl.c: %s.c %s.h %s_main.c@." basename basename basename basename;
814
    fprintf fmt "\tframa-c -e-acsl-full-mmodel -machdep x86_64 -e-acsl %s.c %s_main.c -then-on e-acsl -print -ocode %s_main_eacsl.i@."
815
      basename basename basename;
816
    (* Ugly hack to deal with eacsl bugs *)
817
    fprintf fmt "\tgrep -v _fc_stdout %s_main_eacsl.i > %s_main_eacsl.c" basename basename;
818
    fprintf fmt "@.";
819
    fprintf fmt "@.";
820

    
821
    (* EACSL version of binary *)
822
    fprintf fmt "%s_main_eacsl: %s_main_eacsl.c@." basename basename;
823
    fprintf fmt "\t${GCC} -Wno-attributes -I${INC} -I. -c %s_main_eacsl.c@." basename; (* compiling instrumented lib + main *)
824
    C_backend_makefile.fprintf_dependencies fmt dependencies;
825
    fprintf fmt "\t${GCC} -Wno-attributes -o %s_main_eacsl io_frontend.o %a %s %s_main_eacsl.o %a@."
826
      basename
827
      (Utils.fprintf_list ~sep:" " (fun fmt dep -> Format.fprintf fmt "%s.o" dep.name))
828
      (C_backend_makefile.compiled_dependencies dependencies)
829
      ("${FRAMACEACSL}/e_acsl.c "
830
       ^ "${FRAMACEACSL}/memory_model/e_acsl_bittree.c "
831
       ^ "${FRAMACEACSL}/memory_model/e_acsl_mmodel.c")
832
      basename
833
      (Utils.fprintf_list ~sep:" " (fun fmt lib -> fprintf fmt "-l%s" lib))
834
      (C_backend_makefile.lib_dependencies dependencies)
835
    ;
836
    fprintf fmt "@."
837

    
838
end
839

    
840
(* Local Variables: *)
841
(* compile-command:"make -C ../../.." *)
842
(* End: *)
(9-9/10)