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: *)
|