Project

General

Profile

« Previous | Next » 

Revision c226a3ba

Added by LĂ©lio Brun over 3 years ago

start generating ACSL spec

View differences:

src/backends/C/c_backend_spec.ml
9 9
(*                                                                  *)
10 10
(********************************************************************)
11 11

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

  
15 19
(**************************************************************************)
16 20
(*     Printing spec for c *)
......
126 130

  
127 131
  *)
128 132

  
129
(* TODO ACSL
130
   mspec are function body annotations, sush as loop invariants, acsl asserts ... *) 
131
let pp_mspec _ _ = ()
132

  
133
   (* TODO ACSL 
133
   (* TODO ACSL
134 134
   Return updates machines (eg with local annotations) and acsl preamble *)
135 135
let preprocess_acsl machines = machines, []
136 136
                          
......
138 138
let pp_acsl_preamble fmt preamble =
139 139
  Format.fprintf fmt "";
140 140
  ()
141

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

  
145
let pp_spec_cut pp fmt =
146
  fprintf fmt "%a@," (pp_spec pp)
147

  
148
let pp_spec_line pp fmt =
149
  fprintf fmt "//%@ %a@," pp
150

  
151
let pp_requires pp_req fmt =
152
  fprintf fmt "requires %a;" pp_req
153

  
154
let pp_ensures pp_ens fmt =
155
  fprintf fmt "ensures %a;" pp_ens
156

  
157
let pp_assigns pp_asg fmt =
158
  fprintf fmt "assigns %a;" pp_asg
159

  
160
let pp_ghost pp_gho fmt =
161
  fprintf fmt "ghost %a" pp_gho
162

  
163
let pp_assert pp_ast fmt =
164
  fprintf fmt "assert %a;" pp_ast
165

  
166
let pp_mem_valid pp_var fmt (name, var) =
167
  fprintf fmt "%s_valid(%a)" name pp_var var
168

  
169
let pp_mem_valid' = pp_mem_valid pp_print_string
170

  
171
let pp_indirect pp_field fmt (ptr, field) =
172
  fprintf fmt "%s->%a" ptr pp_field field
173

  
174
let pp_indirect' = pp_indirect pp_print_string
175

  
176
let pp_access pp_field fmt (stru, field) =
177
  fprintf fmt "%s.%a" stru pp_field field
178

  
179
let pp_access' = pp_access pp_print_string
180

  
181
let pp_inst self fmt (name, _) =
182
  pp_indirect' fmt (self, name)
183

  
184
let pp_true fmt () =
185
  pp_print_string fmt "\\true"
186

  
187
let pp_separated self fmt =
188
  fprintf fmt "\\separated(@[<h>%s%a@])"
189
    self
190
    (pp_print_list
191
       ~pp_prologue:pp_print_comma
192
       ~pp_sep:pp_print_comma
193
       (pp_inst self))
194

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

  
200
let pp_valid =
201
  pp_print_parenthesized
202
    ~pp_nil:pp_true
203
    ~pp_prologue:(fun fmt () -> pp_print_string fmt "\\valid")
204

  
205
let pp_equal pp_l pp_r fmt (l, r) =
206
  fprintf fmt "%a == %a"
207
    pp_l l
208
    pp_r r
209

  
210
let pp_implies pp_l pp_r fmt (l, r) =
211
  fprintf fmt "%a ==>@ %a"
212
    pp_l l
213
    pp_r r
214

  
215
let pp_and pp_l pp_r fmt (l, r) =
216
  fprintf fmt "%a @ && %a"
217
    pp_l l
218
    pp_r r
219

  
220
let pp_and_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_machine_decl fmt (id, mem_type, var) =
228
  fprintf fmt "struct %s_%s %s" id mem_type var
229

  
230
let pp_mem_ghost pp_mem pp_self ?i fmt (name, mem, self) =
231
  fprintf fmt "%s_ghost%a(%a, %a)"
232
    name
233
    (pp_print_option pp_print_int) i
234
    pp_mem mem
235
    pp_self self
236

  
237
let pp_mem_ghost' = pp_mem_ghost pp_print_string pp_print_string
238

  
239
let pp_mem_init fmt (name, mem) =
240
  fprintf fmt "%s_init(%s)" name mem
241

  
242
let pp_var_decl fmt v =
243
  pp_print_string fmt v.var_id
244

  
245
let pp_ptr_decl fmt v =
246
  fprintf fmt "*%s" v.var_id
247

  
248
let pp_mem_trans ?i fmt (m, mem_in, mem_out) =
249
  fprintf fmt "%s_trans%a(@[<h>%s, %a%s%a@])"
250
    m.mname.node_id
251
    (pp_print_option pp_print_int) i
252
    mem_in
253
    (pp_print_list
254
       ~pp_epilogue:pp_print_comma
255
       ~pp_sep:pp_print_comma
256
       pp_var_decl) m.mstep.step_inputs
257
    mem_out
258
    (pp_print_list
259
       ~pp_prologue:pp_print_comma
260
       ~pp_sep:pp_print_comma
261
       pp_ptr_decl) m.mstep.step_outputs
262

  
263
let pp_nothing fmt () =
264
  pp_print_string fmt "\\nothing"
265

  
266
let pp_predicate pp_l pp_r fmt (l, r) =
267
  fprintf fmt "@[<v 2>predicate %a =@,%a;@]"
268
    pp_l l
269
    pp_r r
270

  
271
let print_machine_valid_predicate fmt m =
272
  if not (fst (Machine_code_common.get_stateless_status m)) then
273
    let name = m.mname.node_id in
274
    let self = mk_self m in
275
    pp_spec
276
      (pp_predicate
277
         (pp_mem_valid pp_machine_decl)
278
         (pp_and
279
            (pp_and_l (fun fmt (_, (td, _) as inst) ->
280
                 pp_mem_valid (pp_inst self) fmt (node_name td, inst)))
281
            (pp_valid pp_print_string)))
282
      fmt
283
      ((name, (name, "mem", "*" ^ self)),
284
       (m.minstances, [self]))
285

  
286
let print_machine_ghost_simulation_aux ?i m pp fmt v =
287
  let name = m.mname.node_id in
288
  let self = mk_self m in
289
  let mem = mk_mem m in
290
  pp_spec
291
    (pp_predicate
292
       (pp_mem_ghost pp_machine_decl pp_machine_decl ?i)
293
       pp)
294
    fmt
295
    ((name, (name, "mem_ghost", mem), (name, "mem", "*" ^ self)),
296
     v)
297

  
298
let print_machine_ghost_simulation dependencies m fmt i instr =
299
  let name = m.mname.node_id in
300
  let self = mk_self m in
301
  let mem = mk_mem m in
302
  let prev_ghost fmt () = pp_mem_ghost' ~i fmt (name, mem, self) in
303
  let pred pp v = pp_and prev_ghost pp fmt ((), v) in
304
  print_machine_ghost_simulation_aux m
305
    (fun fmt -> function
306
       | MStateAssign (m, _) ->
307
         pred
308
           (pp_equal
309
              (pp_access (pp_access pp_var_decl))
310
              (pp_indirect (pp_access pp_var_decl)))
311
           ((mem, ("_reg", m)),
312
            (self, ("_reg", m)))
313
       | MStep ([i0], i, vl)
314
         when Basic_library.is_value_internal_fun
315
             (mk_val (Fun (i, vl)) i0.var_type)  ->
316
         prev_ghost fmt ()
317
       | MStep (_, i, _) when !Options.mpfr && Mpfr.is_homomorphic_fun i ->
318
         prev_ghost fmt ()
319
       | MStep ([_], i, _) when has_c_prototype i dependencies ->
320
         prev_ghost fmt ()
321
       | MStep (_, i, _)
322
       | MReset i ->
323
         begin try
324
             let n, _ = List.assoc i m.minstances in
325
             pred
326
               (pp_mem_ghost pp_access' pp_indirect')
327
               (node_name n, (mem, i), (self, i))
328
           with Not_found -> prev_ghost fmt ()
329
         end
330
       | _ -> prev_ghost fmt ())
331
    ~i:(i+1) fmt instr.instr_desc
332

  
333
let print_machine_ghost_struct fmt m =
334
  pp_spec (pp_ghost (print_machine_struct ~ghost:true)) fmt m
335

  
336
let print_machine_ghost_simulations dependencies fmt m =
337
  if not (fst (Machine_code_common.get_stateless_status m)) then
338
    let name = m.mname.node_id in
339
    let self = mk_self m in
340
    let mem = mk_mem m in
341
    fprintf fmt "%a@,%a@,%a%a"
342
      print_machine_ghost_struct m
343
      (print_machine_ghost_simulation_aux m pp_true ~i:0) ()
344
      (pp_print_list_i
345
        ~pp_epilogue:pp_print_cut
346
        ~pp_open_box:pp_open_vbox0
347
        (print_machine_ghost_simulation dependencies m))
348
      m.mstep.step_instrs
349
      (print_machine_ghost_simulation_aux m
350
         (pp_mem_ghost' ~i:(List.length m.mstep.step_instrs))) (name, mem, self)
351

  
352
let pp_at pp_p fmt (p, l) =
353
  fprintf fmt "\\at(%a, %s)" pp_p p l
354

  
355
let label_pre = "Pre"
356

  
357
let pp_at_pre pp_p fmt p =
358
  pp_at pp_p fmt (p, label_pre)
359

  
360
module SrcMod = struct
361

  
362
  let pp_predicates dependencies fmt machines =
363
    fprintf fmt
364
      "%a%a"
365
      (pp_print_list
366
         ~pp_open_box:pp_open_vbox0
367
         ~pp_prologue:(pp_print_endcut "/* ACSL `valid` predicates */")
368
         print_machine_valid_predicate
369
         ~pp_epilogue:pp_print_cutcut) machines
370
      (pp_print_list
371
         ~pp_open_box:pp_open_vbox0
372
         ~pp_sep:pp_print_cutcut
373
         ~pp_prologue:(fun fmt () -> fprintf fmt
374
                          "/* ACSL ghost simulations */@,%a"
375
                          (pp_spec_line (pp_ghost pp_print_string))
376
                          "struct _arrow_mem_ghost {struct _arrow_reg _reg;};")
377
         (print_machine_ghost_simulations dependencies)
378
         ~pp_epilogue:pp_print_cutcut) machines
379

  
380
  let pp_reset_spec fmt self m =
381
    let name = m.mname.node_id in
382
    let mem = mk_mem m in
383
    pp_spec_cut (fun fmt () ->
384
        fprintf fmt
385
          "%a@,%a@,%a@,%a"
386
          (pp_requires pp_mem_valid') (name, self)
387
          (pp_requires (pp_separated self)) m.minstances
388
          (pp_assigns
389
             (pp_print_list
390
                ~pp_sep:pp_print_comma
391
                ~pp_nil:pp_nothing
392
                (pp_inst self))) m.minstances
393
          (pp_ensures
394
             (pp_forall
395
                pp_machine_decl
396
                (pp_implies
397
                   pp_mem_ghost'
398
                   pp_mem_init)))
399
          ((name, "mem_ghost", mem),
400
           ((name, mem, self), (name, mem))))
401
      fmt ()
402

  
403
  let pp_step_spec fmt self m =
404
    let name = m.mname.node_id in
405
    let mem_in = mk_mem_in m in
406
    let mem_out = mk_mem_out m in
407
    pp_spec_cut (fun fmt () ->
408
        fprintf fmt
409
          "%a@,%a@,%a@,%a@,%a"
410
          (pp_requires (pp_valid pp_var_decl)) m.mstep.step_outputs
411
          (pp_requires pp_mem_valid') (name, self)
412
          (pp_requires (pp_separated self)) m.minstances
413
          (pp_assigns
414
             (if m.mstep.step_outputs = [] && m.minstances = [] then
415
                pp_nothing
416
              else
417
                fun fmt () ->
418
                  fprintf fmt "@[<h>%a%a@]"
419
                    (pp_print_list
420
                       ~pp_sep:pp_print_comma
421
                       ~pp_epilogue:pp_print_comma
422
                       pp_ptr_decl) m.mstep.step_outputs
423
                    (pp_print_list
424
                       ~pp_sep:pp_print_comma
425
                       (pp_inst self)) m.minstances)) ()
426
          (pp_ensures
427
             (pp_forall
428
                (fun fmt () ->
429
                   fprintf fmt "%a, %s"
430
                     pp_machine_decl (name, "mem_ghost", mem_in)
431
                     mem_out)
432
                (pp_implies
433
                   (pp_at_pre pp_mem_ghost')
434
                   (pp_implies
435
                      pp_mem_ghost'
436
                      pp_mem_trans))))
437
          ((),
438
           ((name, mem_in, self),
439
            ((name, mem_out, self),
440
             (m, mem_in, mem_out)))))
441
      fmt ()
442

  
443
  let pp_step_instr_spec m self fmt (i, instr) =
444
    let name = m.mname.node_id in
445
    let mem_in = mk_mem_in m in
446
    let mem_out = mk_mem_out m in
447
    fprintf fmt "@,%a"
448
      (pp_spec
449
         (pp_assert
450
            (pp_forall
451
               (fun fmt () ->
452
                  fprintf fmt "%a, %s"
453
                    pp_machine_decl (name, "mem_ghost", mem_in)
454
                    mem_out)
455
               (pp_implies
456
                  (pp_at_pre pp_mem_ghost')
457
                  (pp_implies
458
                     (pp_mem_ghost' ~i:(i+1))
459
                     (pp_mem_trans ~i:(i+1)))))))
460
      ((),
461
       ((name, mem_in, self),
462
        ((name, mem_out, self),
463
         (m, mem_in, mem_out))))
464

  
465
end
466

  
141 467
(**************************************************************************)
142 468
(*                              MAKEFILE                                  *)
143 469
(**************************************************************************)
144 470

  
145
let makefile_targets fmt basename _nodename dependencies =
146
  fprintf fmt "FRAMACEACSL=`frama-c -print-share-path`/e-acsl@.";
147
  (* EACSL version of library file . c *)
148
  fprintf fmt "%s_eacsl.c: %s.c %s.h@." basename basename basename;
149
  fprintf fmt 
150
    "\tframa-c -e-acsl-full-mmodel -machdep x86_64 -e-acsl %s.c -then-on e-acsl -print -ocode %s_eacsl.c@." 
151
    basename basename; 
152
  fprintf fmt "@.";
153
  fprintf fmt "@.";
154

  
155
  (* EACSL version of library file . c + main .c  *)
156
  fprintf fmt "%s_main_eacsl.c: %s.c %s.h %s_main.c@." basename basename basename basename;
157
  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@." 
158
    basename basename basename; 
159
  (* Ugly hack to deal with eacsl bugs *)
160
  fprintf fmt "\tgrep -v _fc_stdout %s_main_eacsl.i > %s_main_eacsl.c" basename basename;
161
  fprintf fmt "@.";
162
  fprintf fmt "@.";
163

  
164
  (* EACSL version of binary *)
165
  fprintf fmt "%s_main_eacsl: %s_main_eacsl.c@." basename basename;
166
  fprintf fmt "\t${GCC} -Wno-attributes -I${INC} -I. -c %s_main_eacsl.c@." basename; (* compiling instrumented lib + main *)
167
  C_backend_makefile.fprintf_dependencies fmt dependencies; 
168
  fprintf fmt "\t${GCC} -Wno-attributes -o %s_main_eacsl io_frontend.o %a %s %s_main_eacsl.o %a@." 
169
    basename 
170
    (Utils.fprintf_list ~sep:" " (fun fmt dep -> Format.fprintf fmt "%s.o" dep.name)) 
171
    (C_backend_makefile.compiled_dependencies dependencies)
172
    ("${FRAMACEACSL}/e_acsl.c " 
173
     ^ "${FRAMACEACSL}/memory_model/e_acsl_bittree.c " 
174
     ^ "${FRAMACEACSL}/memory_model/e_acsl_mmodel.c")
175
    basename 
176
    (Utils.fprintf_list ~sep:" " (fun fmt lib -> fprintf fmt "-l%s" lib)) 
177
    (C_backend_makefile.lib_dependencies dependencies)
178
  ;
179
  fprintf fmt "@.";
180

  
181
module MakefileMod =
182
struct
183
  let other_targets = makefile_targets
184
    
471
module MakefileMod = struct
472

  
473
  let other_targets fmt basename _nodename dependencies =
474
    fprintf fmt "FRAMACEACSL=`frama-c -print-share-path`/e-acsl@.";
475
    (* EACSL version of library file . c *)
476
    fprintf fmt "%s_eacsl.c: %s.c %s.h@." basename basename basename;
477
    fprintf fmt
478
      "\tframa-c -e-acsl-full-mmodel -machdep x86_64 -e-acsl %s.c -then-on e-acsl -print -ocode %s_eacsl.c@."
479
      basename basename;
480
    fprintf fmt "@.";
481
    fprintf fmt "@.";
482

  
483
    (* EACSL version of library file . c + main .c  *)
484
    fprintf fmt "%s_main_eacsl.c: %s.c %s.h %s_main.c@." basename basename basename basename;
485
    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@."
486
      basename basename basename;
487
    (* Ugly hack to deal with eacsl bugs *)
488
    fprintf fmt "\tgrep -v _fc_stdout %s_main_eacsl.i > %s_main_eacsl.c" basename basename;
489
    fprintf fmt "@.";
490
    fprintf fmt "@.";
491

  
492
    (* EACSL version of binary *)
493
    fprintf fmt "%s_main_eacsl: %s_main_eacsl.c@." basename basename;
494
    fprintf fmt "\t${GCC} -Wno-attributes -I${INC} -I. -c %s_main_eacsl.c@." basename; (* compiling instrumented lib + main *)
495
    C_backend_makefile.fprintf_dependencies fmt dependencies;
496
    fprintf fmt "\t${GCC} -Wno-attributes -o %s_main_eacsl io_frontend.o %a %s %s_main_eacsl.o %a@."
497
      basename
498
      (Utils.fprintf_list ~sep:" " (fun fmt dep -> Format.fprintf fmt "%s.o" dep.name))
499
      (C_backend_makefile.compiled_dependencies dependencies)
500
      ("${FRAMACEACSL}/e_acsl.c "
501
       ^ "${FRAMACEACSL}/memory_model/e_acsl_bittree.c "
502
       ^ "${FRAMACEACSL}/memory_model/e_acsl_mmodel.c")
503
      basename
504
      (Utils.fprintf_list ~sep:" " (fun fmt lib -> fprintf fmt "-l%s" lib))
505
      (C_backend_makefile.lib_dependencies dependencies)
506
    ;
507
    fprintf fmt "@."
508

  
185 509
end
186 510

  
187 511
(* Local Variables: *)

Also available in: Unified diff