Project

General

Profile

Download (37.6 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
open Utils
12
open Format
13
open Lustre_types
14
open Machine_code_types
15
open C_backend_common
16
open Corelang
17
open Spec_types
18
open Machine_code_common
19
module Mpfr = Lustrec_mpfr
20

    
21
(**************************************************************************)
22
(*     Printing spec for c *)
23

    
24
(**************************************************************************)
25

    
26
let pp_acsl_basic_type_desc t_desc =
27
  if Types.is_bool_type t_desc then
28
    (* if !Options.cpp then "bool" else "_Bool" *)
29
    "_Bool"
30
  else if Types.is_int_type t_desc then
31
    (* !Options.int_type *)
32
    if t_desc.tid = -1 then "int" else "integer"
33
  else if Types.is_real_type t_desc then
34
    if !Options.mpfr then Mpfr.mpfr_t else !Options.real_type
35
  else assert false
36
(* Not a basic C type. Do not handle arrays or pointers *)
37

    
38
let pp_acsl ?(ghost=false) pp fmt x =
39
  let op = if ghost then "" else "*" in
40
  let cl = if ghost then "@" else "*" in
41
  fprintf fmt "@[<v>/%s%@ @[<v>%a@]@,%s/@]" op pp x cl
42

    
43
let pp_acsl_cut ?ghost pp fmt = fprintf fmt "%a@," (pp_acsl ?ghost pp)
44

    
45
let pp_acsl_line pp fmt = fprintf fmt "//%@ @[<h>%a@]" pp
46

    
47
let pp_acsl_line' ?(ghost=false) pp fmt x =
48
  let op = if ghost then "" else "*" in
49
  let cl = if ghost then "@" else "*" in
50
  fprintf fmt "/%s%@ @[<h>%a@] %s/" op pp x cl
51

    
52
let pp_acsl_line'_cut pp fmt = fprintf fmt "%a@," (pp_acsl_line' pp)
53

    
54
let pp_requires pp fmt = fprintf fmt "requires %a;" pp
55

    
56
let pp_ensures pp fmt = fprintf fmt "ensures %a;" pp
57

    
58
let pp_assumes pp fmt = fprintf fmt "assumes %a;" pp
59

    
60
let pp_terminates pp fmt = fprintf fmt "terminates %a;" pp
61

    
62
let pp_assigns pp =
63
  pp_comma_list
64
    ~pp_prologue:(fun fmt () -> pp_print_string fmt "assigns ")
65
    ~pp_epilogue:pp_print_semicolon'
66
    pp
67

    
68
let pp_ghost pp fmt = fprintf fmt "ghost %a" pp
69

    
70
let pp_assert pp fmt = fprintf fmt "assert %a;" pp
71

    
72
let pp_loop_invariant pp fmt = fprintf fmt "loop invariant %a;" pp
73

    
74
let pp_mem_valid pp_var fmt (name, var) =
75
  fprintf fmt "%s_valid(%a)" name pp_var var
76

    
77
let pp_mem_valid' = pp_mem_valid pp_print_string
78

    
79
let pp_ref pp fmt = fprintf fmt "&%a" pp
80

    
81
let pp_ref' = pp_ref pp_print_string
82

    
83
let pp_indirect pp_ptr pp_field fmt (ptr, field) =
84
  fprintf fmt "%a->%a" pp_ptr ptr pp_field field
85

    
86
let pp_indirect' = pp_indirect pp_print_string pp_print_string
87

    
88
let pp_access pp_stru pp_field fmt (stru, field) =
89
  fprintf fmt "%a.%a" pp_stru stru pp_field field
90

    
91
let pp_access' = pp_access pp_print_string pp_print_string
92

    
93
let pp_var_decl fmt v = pp_print_string fmt v.var_id
94

    
95
let pp_reg self fmt field =
96
  pp_access pp_indirect' pp_var_decl fmt ((self, "_reg"), field)
97

    
98
let pp_true fmt () = pp_print_string fmt "\\true"
99

    
100
let pp_false fmt () = pp_print_string fmt "\\false"
101

    
102
let pp_nothing fmt () = pp_print_string fmt "\\nothing"
103

    
104
let pp_null fmt () = pp_print_string fmt "\\null"
105

    
106
let pp_stdout fmt () = pp_print_string fmt "stdout"
107

    
108
let pp_at pp_v fmt (v, l) = fprintf fmt "\\at(%a, %s)" pp_v v l
109

    
110
let find_machine f =
111
  List.find (fun m -> m.mname.node_id = f)
112

    
113
let instances machines m =
114
  let open List in
115
  let grow paths i td mems =
116
    match paths with
117
    | [] ->
118
      [ [ i, (td, mems) ] ]
119
    | _ ->
120
      map (cons (i, (td, mems))) paths
121
  in
122
  let rec aux paths m =
123
    map
124
      (fun (i, (td, _)) ->
125
        try
126
          let m = find_machine (node_name td) machines in
127
          aux (grow paths i td m.mmemory) m
128
        with Not_found -> grow paths i td [])
129
      m.minstances
130
    |> flatten
131
  in
132
  aux [] m |> map rev
133

    
134
let memories insts =
135
  List.(
136
    map
137
      (fun path ->
138
        let _, (_, mems) = hd (rev path) in
139
        map (fun mem -> path, mem) mems)
140
      insts
141
    |> flatten)
142

    
143
let pp_instance ?(indirect = true) pp ptr =
144
  pp_print_list
145
    ~pp_prologue:(fun fmt () -> fprintf fmt "%a->" pp ptr)
146
    ~pp_sep:(fun fmt () -> pp_print_string fmt (if indirect then "->" else "."))
147
    (fun fmt (i, _) -> pp_print_string fmt i)
148

    
149
let pp_memory ?(indirect = true) ptr fmt (path, mem) =
150
  pp_access
151
    ((if indirect then pp_indirect else pp_access)
152
       (pp_instance ~indirect pp_print_string ptr)
153
       pp_print_string)
154
    pp_var_decl
155
    fmt
156
    ((path, "_reg"), mem)
157

    
158
let prefixes l =
159
  let rec pref acc = function
160
    | x :: l ->
161
      pref ([ x ] :: List.map (List.cons x) acc) l
162
    | [] ->
163
      acc
164
  in
165
  pref [] (List.rev l)
166

    
167
let powerset_instances paths =
168
  List.map prefixes paths |> List.flatten |> remove_duplicates
169

    
170
let pp_separated pp_self pp_mem pp_ptr fmt (self, mem, paths, ptrs) =
171
  fprintf
172
    fmt
173
    "\\separated(@[<v>%a, %a%a%a@])"
174
    pp_self
175
    self
176
    pp_mem
177
    mem
178
    (pp_comma_list ~pp_prologue:pp_print_comma (pp_instance pp_self self))
179
    paths
180
    (pp_comma_list ~pp_prologue:pp_print_comma pp_ptr)
181
    ptrs
182

    
183
let pp_separated' self mem fmt (paths, ptrs) =
184
  pp_separated
185
    pp_print_string
186
    pp_print_string
187
    pp_var_decl
188
    fmt
189
    (self, mem, paths, ptrs)
190

    
191
let pp_separated'' =
192
  pp_comma_list
193
    ~pp_prologue:(fun fmt () -> pp_print_string fmt "\\separated(")
194
    ~pp_epilogue:pp_print_cpar
195
    pp_var_decl
196

    
197
let pp_forall pp_l pp_r fmt (l, r) =
198
  fprintf fmt "@[<v 2>\\forall %a;@,%a@]" pp_l l pp_r r
199

    
200
let pp_exists pp_l pp_r fmt (l, r) =
201
  fprintf fmt "@[<v 2>\\exists %a;@,%a@]" pp_l l pp_r r
202

    
203
let pp_equal pp_l pp_r fmt (l, r) = fprintf fmt "%a == %a" pp_l l pp_r r
204

    
205
let pp_implies pp_l pp_r fmt (l, r) =
206
  fprintf fmt "@[<v>%a ==>@ %a@]" pp_l l pp_r r
207

    
208
let pp_and pp_l pp_r fmt (l, r) = fprintf fmt "@[<v>%a @ && %a@]" pp_l l pp_r r
209

    
210
let pp_and_l pp_v fmt =
211
  pp_print_list
212
    ~pp_open_box:pp_open_vbox0
213
    ~pp_sep:(fun fmt () -> fprintf fmt "@,&& ")
214
    ~pp_nil:pp_true
215
    pp_v
216
    fmt
217

    
218
let pp_or pp_l pp_r fmt (l, r) = fprintf fmt "@[<v>%a @ || %a@]" pp_l l pp_r r
219

    
220
let pp_or_l pp_v fmt =
221
  pp_print_list
222
    ~pp_open_box:pp_open_vbox0
223
    ~pp_sep:(fun fmt () -> fprintf fmt "@,|| ")
224
    pp_v
225
    fmt
226

    
227
let pp_not pp fmt = fprintf fmt "!%a" pp
228

    
229
let pp_valid pp = pp_and_l (fun fmt x -> fprintf fmt "\\valid(%a)" pp x)
230

    
231
let pp_valid_read pp fmt = fprintf fmt "\\valid_read(%a)" pp
232

    
233
let pp_old pp fmt = fprintf fmt "\\old(%a)" pp
234

    
235
let pp_ite pp_c pp_t pp_f fmt (c, t, f) =
236
  fprintf fmt "(%a @[<hov>? %a@ : %a)@]" pp_c c pp_t t pp_f f
237

    
238
let pp_paren pp fmt v = fprintf fmt "(%a)" pp v
239

    
240
let pp_initialization pp_mem fmt (name, mem) =
241
  fprintf fmt "%s_initialization(%a)" name pp_mem mem
242

    
243
let pp_initialization' = pp_initialization pp_print_string
244

    
245
let pp_local m =
246
  pp_c_decl_local_var ~pp_c_basic_type_desc:pp_acsl_basic_type_desc m
247

    
248
let pp_locals m =
249
  pp_comma_list ~pp_open_box:(fun fmt () -> pp_open_hovbox fmt 0) (pp_local m)
250

    
251
let pp_ptr_decl fmt v = pp_ptr fmt v.var_id
252

    
253
let pp_basic_assign_spec pp_l pp_r fmt typ var_name value =
254
  if Types.is_real_type typ && !Options.mpfr then assert false
255
    (* Mpfr.pp_inject_assign pp_var fmt (var_name, value) *)
256
  else pp_equal pp_l pp_r fmt (var_name, value)
257

    
258
let pp_assign_spec m self_l pp_var_l indirect_l self_r pp_var_r indirect_r fmt
259
    (var_type, var_name, value) =
260
  let depth = expansion_depth value in
261
  let loop_vars = mk_loop_variables m var_type depth in
262
  let reordered_loop_vars = reorder_loop_variables loop_vars in
263
  let aux typ fmt vars =
264
    match vars with
265
    | [] ->
266
      pp_basic_assign_spec
267
        (pp_value_suffix
268
           ~indirect:indirect_l
269
           m
270
           self_l
271
           var_type
272
           loop_vars
273
           pp_var_l)
274
        (pp_value_suffix
275
           ~indirect:indirect_r
276
           m
277
           self_r
278
           var_type
279
           loop_vars
280
           pp_var_r)
281
        fmt
282
        typ
283
        var_name
284
        value
285
    | (_d, LVar _i) :: _q ->
286
      assert false
287
    (* let typ' = Types.array_element_type typ in
288
     * fprintf fmt "@[<v 2>{@,int %s;@,for(%s=0;%s<%a;%s++)@,%a @]@,}"
289
     *   i i i pp_c_dimension d i
290
     *   (aux typ') q *)
291
    | (_d, LInt _r) :: _q ->
292
      assert false
293
    (* let typ' = Types.array_element_type typ in
294
     * let szl = Utils.enumerate (Dimension.size_const_dimension d) in
295
     * fprintf fmt "@[<v 2>{@,%a@]@,}"
296
     *   (pp_print_list (fun fmt i -> r := i; aux typ' fmt q)) szl *)
297
    | _ ->
298
      assert false
299
  in
300
  reset_loop_counter ();
301
  aux var_type fmt reordered_loop_vars
302

    
303
let pp_memory_pack_aux ?i pp_mem pp_self fmt (name, mem, self) =
304
  fprintf
305
    fmt
306
    "%s_pack%a(@[<hov>%a,@ %a@])"
307
    name
308
    (pp_print_option pp_print_int)
309
    i
310
    pp_mem
311
    mem
312
    pp_self
313
    self
314

    
315
let pp_memory_pack pp_mem pp_self fmt (mp, mem, self) =
316
  pp_memory_pack_aux
317
    ?i:mp.mpindex
318
    pp_mem
319
    pp_self
320
    fmt
321
    (mp.mpname.node_id, mem, self)
322

    
323
let pp_transition_aux ?i m pp_mem_in pp_mem_out pp_var fmt
324
    (name, vars, mem_in, mem_out) =
325
  let stateless = fst (get_stateless_status m) in
326
  fprintf
327
    fmt
328
    "%s_transition%a(@[<hov>%t%a%t@])"
329
    name
330
    (pp_print_option pp_print_int)
331
    i
332
    (fun fmt -> if not stateless then pp_mem_in fmt mem_in)
333
    (pp_comma_list
334
       ~pp_prologue:(fun fmt () -> if not stateless then pp_print_comma fmt ())
335
       pp_var)
336
    vars
337
    (fun fmt -> if not stateless then fprintf fmt ",@ %a" pp_mem_out mem_out)
338

    
339
let pp_transition m pp_mem_in pp_mem_out pp_var fmt (t, mem_in, mem_out) =
340
  pp_transition_aux
341
    ?i:t.tindex
342
    m
343
    pp_mem_in
344
    pp_mem_out
345
    pp_var
346
    fmt
347
    (t.tname.node_id, t.tvars, mem_in, mem_out)
348

    
349
let pp_transition_aux' ?i m =
350
  pp_transition_aux ?i m pp_print_string pp_print_string (fun fmt v ->
351
      (if is_output m v then pp_ptr_decl else pp_var_decl) fmt v)
352

    
353
let pp_reset_cleared pp_mem_in pp_mem_out fmt (name, mem_in, mem_out) =
354
  fprintf
355
    fmt
356
    "%s_reset_cleared(@[<hov>%a,@ %a@])"
357
    name
358
    pp_mem_in
359
    mem_in
360
    pp_mem_out
361
    mem_out
362

    
363
let pp_reset_cleared' = pp_reset_cleared pp_print_string pp_print_string
364

    
365
let pp_functional_update mems insts fmt mem =
366
  let rec aux fmt = function
367
    | [] ->
368
      pp_print_string fmt mem
369
    | (x, is_mem) :: fields ->
370
      fprintf
371
        fmt
372
        "{ @[<hov>%a@ \\with .%s%s = %s@] }"
373
        aux
374
        fields
375
        (if is_mem then "_reg." else "")
376
        x
377
        x
378
  in
379
  aux
380
    fmt
381
    (List.map (fun (x, _) -> x, false) (Utils.IMap.bindings insts)
382
    @ List.map (fun x -> x, true) (Utils.ISet.elements mems))
383

    
384
module PrintSpec = struct
385
  type mode =
386
    | MemoryPackMode
387
    | TransitionMode
388
    | TransitionFootprintMode
389
    | ResetIn
390
    | ResetOut
391
    | InstrMode of ident
392

    
393
  let pp_reg mem fmt = function
394
    | ResetFlag ->
395
      fprintf fmt "%s.%s" mem reset_flag_name
396
    | StateVar x ->
397
      fprintf fmt "%s.%a" mem pp_var_decl x
398

    
399
  let pp_expr :
400
      type a.
401
      ?test_output:bool ->
402
      machine_t ->
403
      ident ->
404
      formatter ->
405
      (value_t, a) expression_t ->
406
      unit =
407
   fun ?(test_output = false) m mem fmt -> function
408
    | Val v ->
409
      pp_c_val m mem (pp_c_var_read ~test_output m) fmt v
410
    | Tag t ->
411
      pp_print_string fmt t
412
    | Var v ->
413
      pp_var_decl fmt v
414
    | Memory r ->
415
      pp_reg mem fmt r
416

    
417
  let pp_predicate mode m mem_in mem_in' mem_out mem_out' fmt p =
418
    let test_output, mem_update =
419
      match mode with
420
      | InstrMode _ ->
421
        true, false
422
      | TransitionFootprintMode ->
423
        false, true
424
      | _ ->
425
        false, false
426
    in
427
    let pp_expr : type a. bool -> formatter -> (value_t, a) expression_t -> unit
428
        =
429
     fun test_output fmt e -> pp_expr ~test_output m mem_out fmt e
430
    in
431
    match p with
432
    | Transition (f, inst, i, vars, r, mems, insts) ->
433
      let pp_mem_in, pp_mem_out =
434
        match inst with
435
        | None ->
436
          ( pp_print_string,
437
            if mem_update then pp_functional_update mems insts
438
            else pp_print_string )
439
        | Some inst ->
440
          ( (fun fmt mem_in ->
441
              if r then pp_print_string fmt mem_in
442
              else pp_access' fmt (mem_in, inst)),
443
            fun fmt mem_out -> pp_access' fmt (mem_out, inst) )
444
      in
445
      pp_transition_aux
446
        ?i
447
        m
448
        pp_mem_in
449
        pp_mem_out
450
        (pp_expr test_output)
451
        fmt
452
        (f, vars, mem_in', mem_out')
453
    | Reset (_f, inst, r) ->
454
      pp_ite
455
        (pp_c_val m mem_in (pp_c_var_read m))
456
        (pp_equal (pp_reset_flag' ~indirect:false) pp_print_int)
457
        (pp_equal pp_print_string pp_access')
458
        fmt
459
        (r, (mem_out, 1), (mem_out, (mem_in, inst)))
460
    | MemoryPack (f, inst, i) ->
461
      let pp_mem, pp_self =
462
        match inst with
463
        | None ->
464
          pp_print_string, pp_print_string
465
        | Some inst ->
466
          ( (fun fmt mem -> pp_access' fmt (mem, inst)),
467
            fun fmt self -> pp_indirect' fmt (self, inst) )
468
      in
469
      pp_memory_pack_aux ?i pp_mem pp_self fmt (f, mem_out, mem_in)
470
    | ResetCleared f ->
471
      pp_reset_cleared' fmt (f, mem_in, mem_out)
472
    (* fprintf fmt "ResetCleared_%a" pp_print_string f *)
473
    | Initialization ->
474
      ()
475

    
476
  let reset_flag = dummy_var_decl "_reset" Type_predef.type_bool
477

    
478
  let val_of_expr : type a. (value_t, a) expression_t -> value_t = function
479
    | Val v ->
480
      v
481
    | Tag t ->
482
      id_to_tag t
483
    | Var v ->
484
      vdecl_to_val v
485
    | Memory (StateVar v) ->
486
      vdecl_to_val v
487
    | Memory ResetFlag ->
488
      vdecl_to_val reset_flag
489

    
490
  let find_arrow m =
491
    try List.find (fun (_, (td, _)) -> Arrow.td_is_arrow td) m.minstances |> fst
492
    with Not_found ->
493
      eprintf "Internal error: arrow not found";
494
      raise Not_found
495

    
496
  let rec has_memory_val m v =
497
    let has_mem = has_memory_val m in
498
    match v.value_desc with
499
    | Var v ->
500
      is_memory m v
501
    | Array vl
502
    | Fun (_, vl) ->
503
      List.exists has_mem vl
504
    | Access (t, i)
505
    | Power (t, i) ->
506
      has_mem t || has_mem i
507
    | _ ->
508
      false
509

    
510
  let has_memory : type a. machine_t -> (value_t, a) expression_t -> bool = fun m -> function
511
    | Val v -> has_memory_val m v
512
    | _ -> false
513

    
514
  let pp_spec mode m =
515
    let rec pp_spec mode fmt f =
516
      let mem_in, mem_in', indirect_r, mem_out, mem_out', indirect_l =
517
        let self = mk_self m in
518
        let mem = mk_mem m in
519
        let mem_in = mk_mem_in m in
520
        let mem_out = mk_mem_out m in
521
        let mem_reset = mk_mem_reset m in
522
        match mode with
523
        | MemoryPackMode ->
524
          self, self, true, mem, mem, false
525
        | TransitionMode ->
526
          mem_in, mem_in, false, mem_out, mem_out, false
527
        | TransitionFootprintMode ->
528
          mem_in, mem_in, false, mem_out, mem_out, false
529
        | ResetIn ->
530
          mem_reset, mem_reset, false, mem_out, mem_out, false
531
        | ResetOut ->
532
          mem_in, mem_in, false, mem_reset, mem_reset, false
533
        | InstrMode self ->
534
          let mem = "*" ^ mem in
535
          fprintf str_formatter "%a" (pp_at pp_print_string) (mem, reset_label);
536
          self, flush_str_formatter (), false, mem, mem, false
537
      in
538
      let pp_expr : type a. formatter -> (value_t, a) expression_t -> unit =
539
       fun fmt e -> pp_expr m mem_out fmt e
540
      in
541
      let pp_spec' = pp_spec mode in
542
      match f with
543
      | True ->
544
        pp_true fmt ()
545
      | False ->
546
        pp_false fmt ()
547
      | Equal (a, b) ->
548
        let pp_eq fmt () =
549
          pp_assign_spec
550
            m
551
            mem_out
552
            (pp_c_var_read ~test_output:false m)
553
            indirect_l
554
            mem_in
555
            (pp_c_var_read ~test_output:false m)
556
            indirect_r
557
            fmt
558
            (type_of_l_value a, val_of_expr a, val_of_expr b)
559
        in
560
        if has_memory m b then
561
          let inst = find_arrow m in
562
          pp_paren
563
            (pp_implies
564
               (pp_not (pp_initialization pp_access'))
565
               pp_eq)
566
            fmt
567
            ((Arrow.arrow_id, (mem_in, inst)), ())
568
        else
569
          pp_eq fmt ()
570
      | And fs ->
571
        pp_and_l pp_spec' fmt fs
572
      | Or fs ->
573
        pp_or_l pp_spec' fmt fs
574
      | Imply (a, b) ->
575
        pp_paren (pp_implies pp_spec' pp_spec') fmt (a, b)
576
      | Exists (xs, a) ->
577
        pp_exists (pp_locals m) pp_spec' fmt (xs, a)
578
      | Forall (xs, a) ->
579
        pp_forall (pp_locals m) pp_spec' fmt (xs, a)
580
      | Ternary (e, a, b) ->
581
        pp_ite pp_expr pp_spec' pp_spec' fmt (e, a, b)
582
      | Predicate p ->
583
        pp_predicate mode m mem_in mem_in' mem_out mem_out' fmt p
584
      | StateVarPack ResetFlag ->
585
        let r = vdecl_to_val reset_flag in
586
        pp_assign_spec
587
          m
588
          mem_out
589
          (pp_c_var_read ~test_output:false m)
590
          indirect_l
591
          mem_in
592
          (pp_c_var_read ~test_output:false m)
593
          indirect_r
594
          fmt
595
          (Type_predef.type_bool, r, r)
596
      | StateVarPack (StateVar v) ->
597
        let v' = vdecl_to_val v in
598
        let inst = find_arrow m in
599
        pp_paren
600
          (pp_implies
601
             (pp_not (pp_initialization pp_access'))
602
             (pp_assign_spec
603
                m
604
                mem_out
605
                (pp_c_var_read ~test_output:false m)
606
                indirect_l
607
                mem_in
608
                (pp_c_var_read ~test_output:false m)
609
                indirect_r))
610
          fmt
611
          ((Arrow.arrow_id, (mem_out, inst)), (v.var_type, v', v'))
612
      | ExistsMem (f, rc, tr) ->
613
        pp_exists
614
          (pp_machine_decl' ~ghost:true)
615
          (pp_and (pp_spec ResetOut) (pp_spec ResetIn))
616
          fmt
617
          ((f, mk_mem_reset m), (rc, tr))
618
      | Value v ->
619
        pp_c_val m mem_in (pp_c_var_read ~test_output:true m) fmt v
620

    
621
    in
622
    pp_spec mode
623
end
624

    
625
let pp_predicate pp_l pp_r fmt (l, r) =
626
  fprintf fmt "@[<v 2>predicate %a =@,%a;@]" pp_l l pp_r r
627

    
628
let pp_lemma pp_l pp_r fmt (l, r) =
629
  fprintf fmt "@[<v 2>lemma %a:@,%a;@]" pp_l l pp_r r
630

    
631
let pp_mem_valid_def fmt m =
632
  if not (fst (get_stateless_status m)) then
633
    let name = m.mname.node_id in
634
    let self = mk_self m in
635
    pp_acsl
636
      (pp_predicate
637
         (pp_mem_valid (pp_machine_decl pp_ptr))
638
         (pp_and
639
            (pp_and_l (fun fmt (inst, (td, _)) ->
640
                 if Arrow.td_is_arrow td then
641
                   pp_valid pp_indirect' fmt [ self, inst ]
642
                 else pp_mem_valid pp_indirect' fmt (node_name td, (self, inst))))
643
            (pp_valid pp_print_string)))
644
      fmt
645
      ((name, (name, self)), (m.minstances, [ self ]))
646

    
647
let pp_memory_pack_def m fmt mp =
648
  let name = mp.mpname.node_id in
649
  let self = mk_self m in
650
  let mem = mk_mem m in
651
  pp_acsl
652
    (pp_predicate
653
       (pp_memory_pack (pp_machine_decl' ~ghost:true) (pp_machine_decl pp_ptr))
654
       (PrintSpec.pp_spec MemoryPackMode m))
655
    fmt
656
    ((mp, (name, mem), (name, self)), mp.mpformula)
657

    
658
let pp_machine_ghost_struct fmt m =
659
  pp_acsl (pp_ghost (pp_machine_struct ~ghost:true)) fmt m
660

    
661
let pp_memory_pack_defs fmt m =
662
  if not (fst (get_stateless_status m)) then
663
    fprintf
664
      fmt
665
      "%a@,%a"
666
      pp_machine_ghost_struct
667
      m
668
      (pp_print_list
669
         ~pp_epilogue:pp_print_cut
670
         ~pp_open_box:pp_open_vbox0
671
         (pp_memory_pack_def m))
672
      m.mspec.mmemory_packs
673

    
674
let pp_transition_def m fmt t =
675
  let name = t.tname.node_id in
676
  let mem_in = mk_mem_in m in
677
  let mem_out = mk_mem_out m in
678
  pp_acsl
679
    (pp_predicate
680
       (pp_transition
681
          m
682
          (pp_machine_decl' ~ghost:true)
683
          (pp_machine_decl' ~ghost:true)
684
          (pp_local m))
685
       (PrintSpec.pp_spec TransitionMode m))
686
    fmt
687
    ((t, (name, mem_in), (name, mem_out)), t.tformula)
688

    
689
let pp_transition_defs fmt m =
690
  pp_print_list
691
    ~pp_epilogue:pp_print_cut
692
    ~pp_open_box:pp_open_vbox0
693
    (pp_transition_def m)
694
    fmt
695
    m.mspec.mtransitions
696

    
697
let pp_transition_footprint fmt t =
698
  fprintf
699
    fmt
700
    "%s_transition%a_footprint"
701
    t.tname.node_id
702
    (pp_print_option pp_print_int)
703
    t.tindex
704

    
705
let pp_transition_footprint_lemma m fmt t =
706
  let name = t.tname.node_id in
707
  let mem_in = mk_mem_in m in
708
  let mem_out = mk_mem_out m in
709
  let mems =
710
    ISet.(
711
      diff (of_list (List.map (fun v -> v.var_id) m.mmemory)) t.tmem_footprint)
712
  in
713
  let insts =
714
    IMap.(
715
      diff
716
        (of_list (List.map (fun (x, (td, _)) -> x, node_name td) m.minstances))
717
        t.tinst_footprint)
718
  in
719
  let memories =
720
    List.map
721
      (fun v -> { v with var_type = { v.var_type with tid = -1 } })
722
      (List.filter (fun v -> ISet.mem v.var_id mems) m.mmemory)
723
  in
724
  let mems_empty = ISet.is_empty mems in
725
  let insts_empty = IMap.is_empty insts in
726
  let instances = List.map (fun (i, f) -> f, i) (IMap.bindings insts) in
727
  let tr ?mems ?insts () =
728
    Spec_common.mk_transition
729
      ?mems
730
      ?insts
731
      ?i:t.tindex
732
      name
733
      (vdecls_to_vals t.tvars)
734
  in
735
  if not (mems_empty && insts_empty) then
736
    pp_acsl
737
      (pp_lemma
738
         pp_transition_footprint
739
         (pp_forall
740
            (pp_machine_decl ~ghost:true (pp_comma_list pp_print_string))
741
            ((if insts_empty then fun pp fmt (_, x) -> pp fmt x
742
             else pp_forall (pp_comma_list (pp_machine_decl' ~ghost:true)))
743
               ((if mems_empty then fun pp fmt (_, x) -> pp fmt x
744
                else pp_forall (pp_locals m))
745
                  (PrintSpec.pp_spec TransitionFootprintMode m)))))
746
      fmt
747
      ( t,
748
        ( (m.mname.node_id, [ mem_in; mem_out ]),
749
          ( instances,
750
            (memories, Forall (t.tvars, Imply (tr (), tr ~mems ~insts ()))) ) )
751
      )
752

    
753
let pp_transition_footprint_lemmas fmt m =
754
  pp_print_list
755
    ~pp_epilogue:pp_print_cut
756
    ~pp_open_box:pp_open_vbox0
757
    (pp_transition_footprint_lemma m)
758
    fmt
759
    (List.filter
760
       (fun t -> match t.tindex with Some i when i > 0 -> true | _ -> false)
761
       m.mspec.mtransitions)
762

    
763
let pp_initialization_def fmt m =
764
  if not (fst (get_stateless_status m)) then
765
    let name = m.mname.node_id in
766
    let mem_in = mk_mem_in m in
767
    pp_acsl
768
      (pp_predicate
769
         (pp_initialization (pp_machine_decl' ~ghost:true))
770
         (pp_and_l (fun fmt (i, (td, _)) ->
771
              if Arrow.td_is_arrow td then
772
                pp_initialization pp_access' fmt (node_name td, (mem_in, i))
773
              else
774
                pp_equal
775
                  (pp_reset_flag ~indirect:false pp_access')
776
                  pp_print_int
777
                  fmt
778
                  ((mem_in, i), 1))))
779
      fmt
780
      ((name, (name, mem_in)), m.minstances)
781

    
782
let pp_reset_cleared_def fmt m =
783
  if not (fst (get_stateless_status m)) then
784
    let name = m.mname.node_id in
785
    let mem_in = mk_mem_in m in
786
    let mem_out = mk_mem_out m in
787
    pp_acsl
788
      (pp_predicate
789
         (pp_reset_cleared
790
            (pp_machine_decl' ~ghost:true)
791
            (pp_machine_decl' ~ghost:true))
792
         (pp_ite
793
            (pp_reset_flag' ~indirect:false)
794
            (pp_and
795
               (pp_equal (pp_reset_flag' ~indirect:false) pp_print_int)
796
               pp_initialization')
797
            (pp_equal pp_print_string pp_print_string)))
798
      fmt
799
      ( (name, (name, mem_in), (name, mem_out)),
800
        (mem_in, ((mem_out, 0), (name, mem_out)), (mem_out, mem_in)) )
801

    
802
let pp_register_chain ?(indirect = true) ptr =
803
  pp_print_list
804
    ~pp_prologue:(fun fmt () -> fprintf fmt "%s->" ptr)
805
    ~pp_epilogue:(fun fmt () ->
806
      fprintf fmt "%s_reg._first" (if indirect then "->" else "."))
807
    ~pp_sep:(fun fmt () -> pp_print_string fmt (if indirect then "->" else "."))
808
    (fun fmt (i, _) -> pp_print_string fmt i)
809

    
810
let pp_reset_flag_chain ?(indirect = true) ptr fmt mems =
811
  pp_print_list
812
    ~pp_prologue:(fun fmt () -> fprintf fmt "%s->" ptr)
813
    ~pp_epilogue:(fun fmt () -> pp_reset_flag' ~indirect fmt "")
814
    ~pp_sep:(fun fmt () -> pp_print_string fmt (if indirect then "->" else "."))
815
    (fun fmt (i, _) -> pp_print_string fmt i)
816
    fmt
817
    mems
818

    
819
let pp_arrow_reset_ghost mem fmt inst =
820
  fprintf fmt "%s_reset_ghost(%a)" Arrow.arrow_id pp_indirect' (mem, inst)
821

    
822
module GhostProto : MODIFIERS_GHOST_PROTO = struct
823
  let pp_ghost_parameters ?(cut = true) fmt vs =
824
    fprintf
825
      fmt
826
      "%a%a"
827
      (if cut then pp_print_cut else pp_print_nothing)
828
      ()
829
      (pp_acsl_line'
830
         (pp_ghost (pp_print_parenthesized (fun fmt (x, pp) -> pp fmt x))))
831
      vs
832
end
833

    
834
module HdrMod = struct
835
  module GhostProto = GhostProto
836

    
837
  let pp_machine_decl_prefix _ _ = ()
838

    
839
  let pp_import_arrow fmt () =
840
    fprintf
841
      fmt
842
      "#include \"%s/arrow_spec.h%s\""
843
      (Arrow.arrow_top_decl ()).top_decl_owner
844
      (if !Options.cpp then "pp" else "")
845

    
846
  let pp_predicates fmt machines =
847
    let pp_preds comment pp =
848
      pp_print_list
849
        ~pp_open_box:pp_open_vbox0
850
        ~pp_prologue:(pp_print_endcut comment)
851
        pp
852
        ~pp_epilogue:pp_print_cutcut
853
    in
854
    fprintf
855
      fmt
856
      "%a%a"
857
      (pp_preds "/* ACSL `valid` predicates */" pp_mem_valid_def)
858
      machines
859
      (pp_preds "/* ACSL `memory pack` simulations */" pp_memory_pack_defs)
860
      machines
861

    
862
  let pp_machine_alloc_decl fmt m =
863
    pp_machine_decl_prefix fmt m;
864
    if not (fst (get_stateless_status m)) then
865
      if !Options.static_mem then
866
        (* Static allocation *)
867
        let macro = m, mk_attribute m, mk_instance m in
868
        fprintf
869
          fmt
870
          "%a@,%a@,%a"
871
          (pp_static_declare_macro ~ghost:true)
872
          macro
873
          (pp_static_link_macro ~ghost:true)
874
          macro
875
          (pp_static_alloc_macro ~ghost:true)
876
          macro
877
      else
878
        (* Dynamic allocation *)
879
        (* TODO: handle dynamic alloc *)
880
        assert false
881
  (* fprintf fmt "extern %a;@,extern %a" pp_alloc_prototype
882
   *   (m.mname.node_id, m.mstatic)
883
   *   pp_dealloc_prototype m.mname.node_id *)
884
end
885

    
886
module SrcMod = struct
887
  module GhostProto = GhostProto
888

    
889
  let pp_predicates fmt machines =
890
    let pp_preds comment pp =
891
      pp_print_list
892
        ~pp_open_box:pp_open_vbox0
893
        ~pp_prologue:(pp_print_endcut comment)
894
        pp
895
        ~pp_epilogue:pp_print_cutcut
896
    in
897
    fprintf
898
      fmt
899
      "%a%a%a%a%a%a"
900
      (pp_preds "/* ACSL `valid` predicates */" pp_mem_valid_def)
901
      machines
902
      (pp_preds "/* ACSL `memory pack` simulations */" pp_memory_pack_defs)
903
      machines
904
      (pp_preds "/* ACSL initialization annotations */" pp_initialization_def)
905
      machines
906
      (pp_preds "/* ACSL reset cleared annotations */" pp_reset_cleared_def)
907
      machines
908
      (pp_preds "/* ACSL transition annotations */" pp_transition_defs)
909
      machines
910
      (pp_preds
911
         "/* ACSL transition memory footprints lemmas */"
912
         pp_transition_footprint_lemmas)
913
      machines
914

    
915
  let pp_clear_reset_spec fmt self mem m =
916
    let name = m.mname.node_id in
917
    let arws, narws =
918
      List.partition (fun (_, (td, _)) -> Arrow.td_is_arrow td) m.minstances
919
    in
920
    let mk_insts = List.map (fun x -> [ x ]) in
921
    pp_acsl_cut
922
      (fun fmt () ->
923
        fprintf
924
          fmt
925
          "%a@,\
926
           %a@,\
927
           %a@,\
928
           %a@,\
929
           %a@,\
930
           %a@,\
931
           %a@,\
932
           %a@,\
933
           %a@,\
934
           %a@,\
935
           @[<v 2>behavior reset:@;\
936
           %a@,\
937
           %a@]@,\
938
           @[<v 2>behavior no_reset:@;\
939
           %a@,\
940
           %a@]@,\
941
           complete behaviors;@,\
942
           disjoint behaviors;"
943
          (pp_requires pp_mem_valid')
944
          (name, self)
945
          (pp_requires (pp_separated' self mem))
946
          (mk_insts m.minstances, [])
947
          (pp_requires (pp_memory_pack_aux pp_ptr pp_print_string))
948
          (name, mem, self)
949
          (pp_ensures
950
             (pp_memory_pack_aux
951
                ~i:(List.length m.mspec.mmemory_packs - 2)
952
                pp_ptr
953
                pp_print_string))
954
          (name, mem, self)
955
          (pp_assigns pp_reset_flag')
956
          [ self ]
957
          (pp_assigns (pp_register_chain self))
958
          (mk_insts arws)
959
          (pp_assigns (pp_reset_flag_chain self))
960
          (mk_insts narws)
961
          (pp_assigns pp_reset_flag')
962
          [ mem ]
963
          (pp_assigns (pp_register_chain ~indirect:false mem))
964
          (mk_insts arws)
965
          (pp_assigns (pp_reset_flag_chain ~indirect:false mem))
966
          (mk_insts narws)
967
          (pp_assumes (pp_equal pp_reset_flag' pp_print_int))
968
          (mem, 1)
969
          (pp_ensures (pp_initialization pp_ptr))
970
          (name, mem)
971
          (pp_assumes (pp_equal pp_reset_flag' pp_print_int))
972
          (mem, 0)
973
          (pp_ensures (pp_equal pp_ptr (pp_old pp_ptr)))
974
          (mem, mem))
975
      fmt
976
      ()
977

    
978
  let pp_set_reset_spec fmt self mem m =
979
    let name = m.mname.node_id in
980
    pp_acsl_cut
981
      (fun fmt () ->
982
        fprintf
983
          fmt
984
          "%a@,%a@,%a"
985
          (pp_ensures (pp_memory_pack_aux pp_ptr pp_print_string))
986
          (name, mem, self)
987
          (pp_ensures (pp_equal pp_reset_flag' pp_print_int))
988
          (mem, 1)
989
          (pp_assigns pp_reset_flag')
990
          [ self; mem ])
991
      fmt
992
      ()
993

    
994
  let pp_node_spec m fmt = function
995
    | Contract c
996
    | NodeSpec (_, Some c) ->
997
      PrintSpec.pp_spec PrintSpec.TransitionMode m fmt
998
        (Spec_common.red (Imply (c.mc_pre, c.mc_post)))
999
    | NodeSpec (f, None) ->
1000
      pp_print_string fmt f
1001

    
1002
  let pp_step_spec fmt machines self mem m =
1003
    let name = m.mname.node_id in
1004
    let insts = instances machines m in
1005
    let insts' = powerset_instances insts in
1006
    let insts'' =
1007
      List.(
1008
        filter
1009
          (fun l -> l <> [])
1010
          (map (filter (fun (_, (td, _)) -> not (Arrow.td_is_arrow td))) insts))
1011
    in
1012
    let inputs = m.mstep.step_inputs in
1013
    let outputs = m.mstep.step_outputs in
1014
    let pp_if_outputs pp =
1015
      if outputs = [] then pp_print_nothing else pp
1016
    in
1017
    let spec = m.mspec.mnode_spec in
1018
    (* (\* prevent printing an ensures clause with contract name *\)
1019
     * let spec =
1020
     *   match m.mspec.mnode_spec with
1021
     *   | Some (NodeSpec _) -> None
1022
     *   | s -> s
1023
     * in *)
1024
    let pp_spec = pp_print_option
1025
        (if m.mis_contract then pp_print_nothing else pp_ensures (pp_node_spec m)) in
1026
    pp_acsl_cut
1027
      ~ghost:m.mis_contract
1028
      (fun fmt () ->
1029
        if fst (get_stateless_status m) then
1030
          fprintf
1031
            fmt
1032
            "%a@,%a@,%a@,%a@,%a"
1033
            (pp_if_outputs (pp_requires (pp_valid pp_var_decl)))
1034
            outputs
1035
            (pp_if_outputs (pp_requires pp_separated''))
1036
            outputs
1037
            (pp_assigns pp_ptr_decl)
1038
            outputs
1039
            (pp_ensures (pp_transition_aux' m))
1040
            (name, inputs @ outputs, "", "")
1041
            pp_spec
1042
            spec
1043
        else
1044
          fprintf
1045
            fmt
1046
            "%a@,%a@,%a@,%a@,%a@,%a@,%a@,%a@,%a@,%a@,%a@,%a@,%a@,%a@,%a@,%a@,%a@,%a"
1047
            (pp_if_outputs (pp_requires (pp_valid pp_var_decl)))
1048
            outputs
1049
            (pp_requires pp_mem_valid')
1050
            (name, self)
1051
            (pp_requires (pp_separated' self mem))
1052
            (insts', outputs)
1053
            (pp_requires (pp_memory_pack_aux pp_ptr pp_print_string))
1054
            (name, mem, self)
1055
            (pp_ensures (pp_memory_pack_aux pp_ptr pp_print_string))
1056
            (name, mem, self)
1057
            (pp_ensures
1058
               (pp_transition_aux m (pp_old pp_ptr) pp_ptr (fun fmt v ->
1059
                    (if is_output m v then pp_ptr_decl else pp_var_decl) fmt v)))
1060
            (name, inputs @ outputs, mem, mem)
1061
            pp_spec
1062
            spec
1063
            (pp_assigns pp_ptr_decl)
1064
            outputs
1065
            (pp_assigns (pp_reg self))
1066
            m.mmemory
1067
            (pp_assigns pp_reset_flag')
1068
            [ self ]
1069
            (pp_assigns (pp_memory self))
1070
            (memories insts')
1071
            (pp_assigns (pp_register_chain self))
1072
            insts
1073
            (pp_assigns (pp_reset_flag_chain self))
1074
            insts''
1075
            (pp_assigns (pp_reg mem))
1076
            m.mmemory
1077
            (pp_assigns pp_reset_flag')
1078
            [ mem ]
1079
            (pp_assigns (pp_memory ~indirect:false mem))
1080
            (memories insts')
1081
            (pp_assigns (pp_register_chain ~indirect:false mem))
1082
            insts
1083
            (pp_assigns (pp_reset_flag_chain ~indirect:false mem))
1084
            insts'')
1085
      fmt
1086
      ()
1087

    
1088
  let pp_ghost_instr_code m self fmt instr =
1089
    match instr.instr_desc with
1090
    | MStateAssign (x, v) ->
1091
      fprintf
1092
        fmt
1093
        "@,%a"
1094
        (pp_acsl_line (pp_ghost (pp_assign m self (pp_c_var_read m))))
1095
        (x, v)
1096
    | MResetAssign b ->
1097
      fprintf fmt "@,%a" (pp_acsl_line (pp_ghost (pp_reset_assign self))) b
1098
    | MSetReset inst ->
1099
      let td, _ = List.assoc inst m.minstances in
1100
      if Arrow.td_is_arrow td then
1101
        fprintf
1102
          fmt
1103
          "@,%a;"
1104
          (pp_acsl_line (pp_ghost (pp_arrow_reset_ghost self)))
1105
          inst
1106
    | _ ->
1107
      ()
1108

    
1109
  let pp_step_instr_spec m self mem fmt instr =
1110
    let ghost = m.mis_contract in
1111
    fprintf
1112
      fmt
1113
      "%a%a"
1114
      (pp_ghost_instr_code m mem)
1115
      instr
1116
      (pp_print_list
1117
         ~pp_open_box:pp_open_vbox0
1118
         ~pp_prologue:pp_print_cut
1119
         (pp_acsl_line' ~ghost (pp_assert (PrintSpec.pp_spec (InstrMode self) m))))
1120
      instr.instr_spec
1121

    
1122
  let pp_ghost_parameter mem fmt inst =
1123
    GhostProto.pp_ghost_parameters
1124
      ~cut:false
1125
      fmt
1126
      (match inst with
1127
      | Some inst ->
1128
        [ (inst, fun fmt inst -> pp_ref pp_indirect' fmt (mem, inst)) ]
1129
      | None ->
1130
        [ mem, pp_print_string ])
1131

    
1132
  let pp_contract fmt machines _self m =
1133
    match m.mspec.mnode_spec with
1134
    | Some (NodeSpec (f, _)) ->
1135
      let m_f = find_machine f machines in
1136
      pp_acsl_cut
1137
        (pp_ghost
1138
           (fun fmt () ->
1139
              fprintf
1140
                fmt
1141
                "@;<0 2>@[<v>%a%a(%a%a);@]"
1142
                (pp_print_list ~pp_open_box:pp_open_vbox0 ~pp_sep:pp_print_semicolon ~pp_eol:pp_print_semicolon (pp_c_decl_local_var m))
1143
                m_f.mstep.step_outputs
1144
                pp_machine_step_name
1145
                m_f.mname.node_id
1146
                (pp_comma_list ~pp_eol:pp_print_comma (pp_c_var_read m))
1147
                m_f.mstep.step_inputs
1148
                (pp_comma_list (pp_c_var_write m))
1149
                m_f.mstep.step_outputs))
1150
        fmt ()
1151
    | _ -> ()
1152

    
1153
end
1154

    
1155
module MainMod = struct
1156
  let main_mem_ghost = "main_mem_ghost"
1157

    
1158
  let pp_declare_ghost_state fmt name =
1159
    pp_acsl_line'_cut
1160
      (pp_ghost (fun fmt () ->
1161
           fprintf
1162
             fmt
1163
             "%a(,%s);"
1164
             (pp_machine_static_alloc_name ~ghost:true)
1165
             name
1166
             main_mem_ghost))
1167
      fmt
1168
      ()
1169

    
1170
  let pp_ghost_state_parameter fmt () =
1171
    GhostProto.pp_ghost_parameters
1172
      ~cut:false
1173
      fmt
1174
      [ main_mem_ghost, pp_ref pp_print_string ]
1175

    
1176
  let pp_main_loop_invariants main_mem machines fmt m =
1177
    let name = m.mname.node_id in
1178
    let insts = powerset_instances (instances machines m) in
1179
    pp_acsl_cut
1180
      (fun fmt () ->
1181
        fprintf
1182
          fmt
1183
          "%a@,%a@,%a@,%a"
1184
          (pp_loop_invariant pp_mem_valid')
1185
          (name, main_mem)
1186
          (pp_loop_invariant
1187
             (pp_memory_pack_aux pp_print_string pp_print_string))
1188
          (name, main_mem_ghost, main_mem)
1189
          (pp_loop_invariant
1190
             (pp_separated
1191
                (pp_paren pp_print_string)
1192
                pp_ref'
1193
                (pp_ref pp_var_decl)))
1194
          (main_mem, main_mem_ghost, insts, m.mstep.step_outputs)
1195
          (pp_loop_invariant
1196
             (pp_or
1197
                (pp_valid_read pp_stdout)
1198
                (pp_equal pp_stdout pp_null)))
1199
          ((), ((), ())))
1200
      fmt
1201
      ()
1202

    
1203
  let pp_main_spec fmt =
1204
    pp_acsl_cut
1205
      (fun fmt () ->
1206
        fprintf
1207
          fmt
1208
          "%a@,%a@,%a@,%a"
1209
          (pp_requires
1210
             (pp_or
1211
                (pp_valid_read pp_stdout)
1212
                (pp_equal pp_stdout pp_null)))
1213
          ((), ((), ()))
1214
          (pp_terminates pp_false)
1215
          ()
1216
          (pp_ensures pp_false)
1217
          ()
1218
          (pp_assigns pp_nothing)
1219
          [ () ])
1220
      fmt
1221
      ()
1222
end
1223

    
1224
(**************************************************************************)
1225
(*                              MAKEFILE                                  *)
1226
(**************************************************************************)
1227

    
1228
module MakefileMod = struct
1229
  let other_targets fmt basename _nodename dependencies =
1230
    fprintf fmt "FRAMACEACSL=`frama-c -print-share-path`/e-acsl@.";
1231
    (* EACSL version of library file . c *)
1232
    fprintf fmt "%s_eacsl.c: %s.c %s.h@." basename basename basename;
1233
    fprintf
1234
      fmt
1235
      "\tframa-c -e-acsl-full-mmodel -machdep x86_64 -e-acsl %s.c -then-on \
1236
       e-acsl -print -ocode %s_eacsl.c@."
1237
      basename
1238
      basename;
1239
    fprintf fmt "@.";
1240
    fprintf fmt "@.";
1241

    
1242
    (* EACSL version of library file . c + main .c *)
1243
    fprintf
1244
      fmt
1245
      "%s_main_eacsl.c: %s.c %s.h %s_main.c@."
1246
      basename
1247
      basename
1248
      basename
1249
      basename;
1250
    fprintf
1251
      fmt
1252
      "\tframa-c -e-acsl-full-mmodel -machdep x86_64 -e-acsl %s.c %s_main.c \
1253
       -then-on e-acsl -print -ocode %s_main_eacsl.i@."
1254
      basename
1255
      basename
1256
      basename;
1257
    (* Ugly hack to deal with eacsl bugs *)
1258
    fprintf
1259
      fmt
1260
      "\tgrep -v _fc_stdout %s_main_eacsl.i > %s_main_eacsl.c"
1261
      basename
1262
      basename;
1263
    fprintf fmt "@.";
1264
    fprintf fmt "@.";
1265

    
1266
    (* EACSL version of binary *)
1267
    fprintf fmt "%s_main_eacsl: %s_main_eacsl.c@." basename basename;
1268
    fprintf
1269
      fmt
1270
      "\t${GCC} -Wno-attributes -I${INC} -I. -c %s_main_eacsl.c@."
1271
      basename;
1272
    (* compiling instrumented lib + main *)
1273
    C_backend_makefile.fprintf_dependencies fmt dependencies;
1274
    fprintf
1275
      fmt
1276
      "\t${GCC} -Wno-attributes -o %s_main_eacsl io_frontend.o %a %s \
1277
       %s_main_eacsl.o %a@."
1278
      basename
1279
      (pp_print_list (fun fmt dep -> fprintf fmt "%s.o" dep.name))
1280
      (C_backend_makefile.compiled_dependencies dependencies)
1281
      ("${FRAMACEACSL}/e_acsl.c "
1282
     ^ "${FRAMACEACSL}/memory_model/e_acsl_bittree.c "
1283
     ^ "${FRAMACEACSL}/memory_model/e_acsl_mmodel.c")
1284
      basename
1285
      (pp_print_list (fun fmt lib -> fprintf fmt "-l%s" lib))
1286
      (C_backend_makefile.lib_dependencies dependencies);
1287
    fprintf fmt "@."
1288
end
1289

    
1290
(* Local Variables: *)
1291
(* compile-command:"make -C ../../.." *)
1292
(* End: *)
(15-15/18)