Project

General

Profile

« Previous | Next » 

Revision 4b596770

Added by Lélio Brun about 4 years ago

first draft: to be tested with frama-c

View differences:

src/backends/C/c_backend_spec.ml
139 139
  Format.fprintf fmt "";
140 140
  ()
141 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

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

  
......
197 205
    pp_l l
198 206
    pp_r r
199 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

  
200 213
let pp_valid =
201 214
  pp_print_parenthesized
202 215
    ~pp_nil:pp_true
......
208 221
    pp_r r
209 222

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

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

  
......
230 243
    pp_t t
231 244
    pp_f f
232 245

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

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

  
......
250 266
let pp_var_decl fmt v =
251 267
  pp_print_string fmt v.var_id
252 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

  
253 275
let pp_ptr_decl fmt v =
254 276
  fprintf fmt "*%s" v.var_id
255 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

  
256 337
let pp_mem_trans_aux ?i pp_mem_in pp_mem_out pp_input pp_output fmt
257
    (name, inputs, outputs, mem_in, mem_out) =
258
  fprintf fmt "%s_trans%a(@[<hov>%a,@ %a%a%a@])"
338
    (name, inputs, locals, outputs, mem_in, mem_out) =
339
  fprintf fmt "%s_trans%a(@[<hov>%a,@ %a%a%a%a@])"
259 340
    name
260 341
    (pp_print_option pp_print_int) i
261 342
    pp_mem_in mem_in
......
263 344
       ~pp_epilogue:pp_print_comma
264 345
       ~pp_sep:pp_print_comma
265 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
266 354
    pp_mem_out mem_out
267 355
    (pp_print_list
268 356
       ~pp_prologue:pp_print_comma
269 357
       ~pp_sep:pp_print_comma
270 358
       pp_output) outputs
271 359

  
272
let pp_mem_trans ?i pp_mem_in pp_mem_out fmt (m, mem_in, mem_out) =
273
  pp_mem_trans_aux ?i pp_mem_in pp_mem_out pp_var_decl pp_ptr_decl fmt
274
    (m.mname.node_id, m.mstep.step_inputs, m.mstep.step_outputs, mem_in, mem_out)
275

  
276
let pp_mem_trans' ?i fmt = pp_mem_trans ?i pp_print_string pp_print_string fmt
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
277 384

  
278 385
let pp_nothing fmt () =
279 386
  pp_print_string fmt "\\nothing"
......
310 417
    ((name, (name, "mem_ghost", mem), (name, "mem", "*" ^ self)),
311 418
     v)
312 419

  
313
let print_machine_ghost_simulation dependencies m fmt i instr =
420
let print_ghost_simulation dependencies m fmt (i, instr) =
314 421
  let name = m.mname.node_id in
315 422
  let self = mk_self m in
316 423
  let mem = mk_mem m in
317 424
  let prev_ghost fmt () = pp_mem_ghost' ~i fmt (name, mem, self) in
318 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 =
319 458
  print_machine_ghost_simulation_aux m
320
    (fun fmt -> function
321
       | MStateAssign (m, _) ->
322
         pred
323
           (pp_equal
324
              (pp_access (pp_access pp_var_decl))
325
              (pp_indirect (pp_access pp_var_decl)))
326
           ((mem, ("_reg", m)),
327
            (self, ("_reg", m)))
328
       | MStep ([i0], i, vl)
329
         when Basic_library.is_value_internal_fun
330
             (mk_val (Fun (i, vl)) i0.var_type)  ->
331
         prev_ghost fmt ()
332
       | MStep (_, i, _) when !Options.mpfr && Mpfr.is_homomorphic_fun i ->
333
         prev_ghost fmt ()
334
       | MStep ([_], i, _) when has_c_prototype i dependencies ->
335
         prev_ghost fmt ()
336
       | MStep (_, i, _)
337
       | MReset i ->
338
         begin try
339
             let n, _ = List.assoc i m.minstances in
340
             pred
341
               (pp_mem_ghost pp_access' pp_indirect')
342
               (node_name n, (mem, i), (self, i))
343
           with Not_found -> prev_ghost fmt ()
344
         end
345
       | _ -> prev_ghost fmt ())
346
    ~i:(i+1) fmt instr.instr_desc
459
    (print_ghost_simulation dependencies m)
460
    ~i:(i+1)
461
    fmt (i, instr)
347 462

  
348 463
let print_machine_ghost_struct fmt m =
349 464
  pp_spec (pp_ghost (print_machine_struct ~ghost:true)) fmt m
......
364 479
      (print_machine_ghost_simulation_aux m
365 480
         (pp_mem_ghost' ~i:(List.length m.mstep.step_instrs))) (name, mem, self)
366 481

  
367
let print_machine_core_annotations dependencies fmt m =
368
  if not (fst (Machine_code_common.get_stateless_status m)) then
369
    let name = m.mname.node_id in
370
    let self = mk_self m in
371
    let mem = mk_mem m in
372
    fprintf fmt "%a@,%a@,%a%a"
373
      print_machine_ghost_struct m
374
      (print_machine_ghost_simulation_aux m pp_true ~i:0) ()
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) ()
375 617
      (pp_print_list_i
376 618
        ~pp_epilogue:pp_print_cut
377 619
        ~pp_open_box:pp_open_vbox0
378
        (print_machine_ghost_simulation dependencies m))
620
        (print_machine_trans_simulation machines dependencies m))
379 621
      m.mstep.step_instrs
380
      (print_machine_ghost_simulation_aux m
381
         (pp_mem_ghost' ~i:(List.length m.mstep.step_instrs))) (name, mem, self)
622
      (print_machine_trans_simulation_aux m last_trans) ()
623
  end
382 624

  
383 625
let pp_at pp_p fmt (p, l) =
384 626
  fprintf fmt "\\at(%a, %s)" pp_p p l
......
388 630
let pp_at_pre pp_p fmt p =
389 631
  pp_at pp_p fmt (p, label_pre)
390 632

  
391
module VarDecl = struct
392
  type t = var_decl
393
  let compare v1 v2 = compare v1.var_id v2.var_id
394
end
395
module VDSet = Set.Make(VarDecl)
396

  
397 633
let pp_arrow_spec fmt () =
398 634
  let name = "_arrow" in
399 635
  let mem_in = "mem_in" in
......
418 654
       (pp_predicate
419 655
          (pp_mem_trans_aux
420 656
             pp_machine_decl pp_machine_decl pp_print_string pp_print_string)
421
          (pp_and
422
             (pp_equal
423
                pp_print_string
424
                (pp_access pp_access'))
425
             (pp_ite
426
                (pp_access pp_access')
427
                (pp_equal
428
                   (pp_access pp_access')
429
                   pp_print_string)
430
                (pp_equal
431
                   (pp_access pp_access')
432
                   (pp_access pp_access'))))))
433
    ((name, [], ["_Bool out"], (name, "mem_ghost", mem_in), (name, "mem_ghost", mem_out)),
434
     (("out", mem_in_first),
435
      (mem_in_first, (mem_out_first, "false"), (mem_out_first, mem_in_first))))
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"))))
436 676
    (pp_spec_cut
437 677
       (pp_predicate
438 678
          (pp_mem_ghost pp_machine_decl pp_machine_decl)
......
463 703
         ~pp_open_box:pp_open_vbox0
464 704
         ~pp_sep:pp_print_cutcut
465 705
         ~pp_prologue:(pp_print_endcut "/* ACSL core annotations */")
466
         (print_machine_core_annotations dependencies)
706
         (print_machine_core_annotations machines dependencies)
467 707
         ~pp_epilogue:pp_print_cutcut) machines
468 708

  
469 709
  let pp_reset_spec fmt self m =
......
544 784
               (pp_implies
545 785
                  (pp_at_pre pp_mem_ghost')
546 786
                  (pp_implies
547
                     (pp_mem_ghost' ~i:(i+1))
548
                     (pp_mem_trans' ~i:(i+1)))))))
787
                     (pp_mem_ghost' ~i)
788
                     (pp_mem_trans' ~i))))))
549 789
      ((),
550 790
       ((name, mem_in, self),
551 791
        ((name, mem_out, self),

Also available in: Unified diff