Project

General

Profile

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

    
12
open Utils
13
open Format
14
open Lustre_types
15
open Machine_code_types
16
open Corelang
17
open Machine_code_common
18
open C_backend_common
19
module Mpfr = Lustrec_mpfr
20

    
21
module type MODIFIERS_SRC = sig
22
  module GhostProto : MODIFIERS_GHOST_PROTO
23

    
24
  val pp_predicates : formatter -> machine_t list -> unit
25

    
26
  val pp_set_reset_spec : formatter -> ident -> ident -> machine_t -> unit
27

    
28
  val pp_clear_reset_spec : formatter -> ident -> ident -> machine_t -> unit
29

    
30
  val pp_step_spec :
31
    formatter -> machine_t list -> ident -> ident -> machine_t -> unit
32

    
33
  val pp_step_instr_spec :
34
    machine_t -> ident -> ident -> formatter -> instr_t -> unit
35

    
36
  val pp_ghost_parameter : ident -> formatter -> ident option -> unit
37
end
38

    
39
module EmptyMod = struct
40
  module GhostProto = EmptyGhostProto
41

    
42
  let pp_predicates _ _ = ()
43

    
44
  let pp_set_reset_spec _ _ _ _ = ()
45

    
46
  let pp_clear_reset_spec _ _ _ _ = ()
47

    
48
  let pp_step_spec _ _ _ _ _ = ()
49

    
50
  let pp_step_instr_spec _ _ _ _ _ = ()
51

    
52
  let pp_ghost_parameter _ _ _ = ()
53
end
54

    
55
module Main (Mod : MODIFIERS_SRC) = struct
56
  module Protos = Protos (Mod.GhostProto)
57

    
58
  (********************************************************************************************)
59
  (* Instruction Printing functions *)
60
  (********************************************************************************************)
61

    
62
  (* XXX: UNUSED *)
63
  (* let rec merge_static_loop_profiles lp1 lp2 =
64
   *   match lp1, lp2 with
65
   *   | [], _ ->
66
   *     lp2
67
   *   | _, [] ->
68
   *     lp1
69
   *   | p1 :: q1, p2 :: q2 ->
70
   *     (p1 || p2) :: merge_static_loop_profiles q1 q2 *)
71

    
72
  (* XXX: UNUSED *)
73
  (* Returns a list of bool values, indicating whether the indices must be
74
     static or not *)
75
  (* let rec static_loop_profile v =
76
   *   match v.value_desc with
77
   *   | Cst cst ->
78
   *     static_loop_profile_cst cst
79
   *   | Var _ | ResetFlag ->
80
   *     []
81
   *   | Fun (_, vl) ->
82
   *     List.fold_right
83
   *       (fun v lp -> merge_static_loop_profiles lp (static_loop_profile v))
84
   *       vl []
85
   *   | Array vl ->
86
   *     true
87
   *     ::
88
   *     List.fold_right
89
   *       (fun v lp -> merge_static_loop_profiles lp (static_loop_profile v))
90
   *       vl []
91
   *   | Access (v, _) -> (
92
   *       match static_loop_profile v with [] -> [] | _ :: q -> q)
93
   *   | Power (v, _) ->
94
   *     false :: static_loop_profile v
95
   *
96
   * and static_loop_profile_cst cst =
97
   *   match cst with
98
   *   | Const_array cl ->
99
   *     List.fold_right
100
   *       (fun c lp ->
101
   *          merge_static_loop_profiles lp (static_loop_profile_cst c))
102
   *       cl []
103
   *   | _ ->
104
   *     [] *)
105

    
106
  (* Subsumes C_backend_common.pp_c_val to cope with aggressive substitution
107
     which may yield constant arrays in expressions. Type is needed to correctly
108
     print constant arrays. *)
109
  let pp_c_val m self pp_var fmt v =
110
    pp_value_suffix m self v.value_type [] pp_var fmt v
111

    
112
  let pp_machine_ pp_machine_name fn_name m fmt ?inst self mem =
113
    let name, is_arrow, static =
114
      match inst with
115
      | Some inst ->
116
        let node, static =
117
          try List.assoc inst m.minstances
118
          with Not_found ->
119
            eprintf
120
              "internal error: %s %s %s %s:@."
121
              fn_name
122
              m.mname.node_id
123
              self
124
              inst;
125
            raise Not_found
126
        in
127
        node_name node, Arrow.td_is_arrow node, static
128
      | None ->
129
        m.mname.node_id, false, []
130
    in
131
    let is_arrow_reset = is_arrow && fn_name = "pp_machine_set_reset" in
132
    fprintf
133
      fmt
134
      "%a(%a%s%a)%a;"
135
      (if is_arrow_reset then fun fmt -> fprintf fmt "%s_reset"
136
      else pp_machine_name)
137
      name
138
      (pp_comma_list ~pp_eol:pp_print_comma Dimension.pp)
139
      static
140
      self
141
      (pp_print_option (fun fmt -> fprintf fmt "->%s"))
142
      inst
143
      (if is_arrow_reset then pp_print_nothing else Mod.pp_ghost_parameter mem)
144
      inst
145

    
146
  let pp_machine_set_reset m self mem fmt inst =
147
    pp_machine_
148
      pp_machine_set_reset_name
149
      "pp_machine_set_reset"
150
      m
151
      fmt
152
      ~inst
153
      self
154
      mem
155

    
156
  let pp_machine_clear_reset m self mem fmt =
157
    pp_machine_
158
      pp_machine_clear_reset_name
159
      "pp_machine_clear_reset"
160
      m
161
      fmt
162
      self
163
      mem
164

    
165
  let pp_machine_init m self mem fmt inst =
166
    pp_machine_ pp_machine_init_name "pp_machine_init" m fmt ~inst self mem
167

    
168
  let pp_machine_clear m self mem fmt inst =
169
    pp_machine_ pp_machine_clear_name "pp_machine_clear" m fmt ~inst self mem
170

    
171
  let pp_call m self mem pp_read pp_write fmt i inputs outputs =
172
    try
173
      (* stateful node instance *)
174
      let n, _ = List.assoc i m.minstances in
175
      fprintf
176
        fmt
177
        "%a(%a%a%s->%s)%a;"
178
        pp_machine_step_name
179
        (node_name n)
180
        (pp_comma_list ~pp_eol:pp_print_comma (pp_c_val m self pp_read))
181
        inputs
182
        (pp_comma_list ~pp_eol:pp_print_comma pp_write)
183
        outputs
184
        self
185
        i
186
        (Mod.pp_ghost_parameter mem)
187
        (Some i)
188
    with Not_found ->
189
      (* stateless node instance *)
190
      let n, _ = List.assoc i m.mcalls in
191
      fprintf
192
        fmt
193
        "%a(%a%a);"
194
        pp_machine_step_name
195
        (node_name n)
196
        (pp_comma_list ~pp_eol:pp_print_comma (pp_c_val m self pp_read))
197
        inputs
198
        (pp_comma_list pp_write)
199
        outputs
200

    
201
  let pp_basic_instance_call m self mem =
202
    pp_call m self mem (pp_c_var_read m) (pp_c_var_write m)
203

    
204
  let pp_arrow_call m self mem fmt i outputs =
205
    match outputs with
206
    | [ x ] ->
207
      fprintf
208
        fmt
209
        "%a = %a(%s->%s)%a;"
210
        (pp_c_var_read m)
211
        x
212
        pp_machine_step_name
213
        Arrow.arrow_id
214
        self
215
        i
216
        (Mod.pp_ghost_parameter mem)
217
        (Some i)
218
    | _ ->
219
      assert false
220

    
221
  let pp_instance_call m self mem fmt i inputs outputs =
222
    let pp_offset pp_var indices fmt var =
223
      fprintf
224
        fmt
225
        "%a%a"
226
        pp_var
227
        var
228
        (pp_print_list ~pp_sep:pp_print_nothing (fun fmt -> fprintf fmt "[%s]"))
229
        indices
230
    in
231
    let rec aux indices fmt typ =
232
      if Types.is_array_type typ then
233
        let dim = Types.array_type_dimension typ in
234
        let idx = mk_loop_var m () in
235
        fprintf
236
          fmt
237
          "@[<v 2>{@,int %s;@,for(%s=0;%s<%a;%s++)@,%a @]@,}"
238
          idx
239
          idx
240
          idx
241
          pp_c_dimension
242
          dim
243
          idx
244
          (aux (idx :: indices))
245
          (Types.array_element_type typ)
246
      else
247
        let pp_read = pp_offset (pp_c_var_read m) indices in
248
        let pp_write = pp_offset (pp_c_var_write m) indices in
249
        pp_call m self mem pp_read pp_write fmt i inputs outputs
250
    in
251
    reset_loop_counter ();
252
    aux [] fmt (List.hd inputs).Machine_code_types.value_type
253

    
254
  let rec pp_conditional dependencies m self mem fmt c tl el =
255
    let pp_machine_instrs =
256
      pp_print_list
257
        ~pp_open_box:pp_open_vbox0
258
        ~pp_prologue:pp_print_cut
259
        (pp_machine_instr dependencies m self mem)
260
    in
261
    let pp_cond = pp_c_val m self (pp_c_var_read m) in
262
    match tl, el with
263
    | [], _ :: _ ->
264
      fprintf fmt "@[<v 2>if (!%a) {%a@]@,}" pp_cond c pp_machine_instrs el
265
    | _, [] ->
266
      fprintf fmt "@[<v 2>if (%a) {%a@]@,}" pp_cond c pp_machine_instrs tl
267
    | _, _ ->
268
      fprintf
269
        fmt
270
        "@[<v 2>if (%a) {%a@]@,@[<v 2>} else {%a@]@,}"
271
        pp_cond
272
        c
273
        pp_machine_instrs
274
        tl
275
        pp_machine_instrs
276
        el
277

    
278
  and pp_machine_instr dependencies m self mem fmt instr =
279
    let pp_instr fmt instr =
280
      match get_instr_desc instr with
281
      | MNoReset _ ->
282
        ()
283
      | MSetReset inst ->
284
        pp_machine_set_reset m self mem fmt inst
285
      | MClearReset ->
286
        if not (fst (get_stateless_status m)) then
287
          fprintf
288
            fmt
289
            "%t@,%a"
290
            (pp_machine_clear_reset m self mem)
291
            pp_label
292
            reset_label
293
      | MResetAssign b ->
294
        pp_reset_assign self fmt b
295
      | MLocalAssign (i, v) ->
296
        pp_assign m self (pp_c_var_read m) fmt (i, v)
297
      | MStateAssign (i, v) ->
298
        pp_assign m self (pp_c_var_read m) fmt (i, v)
299
      | MStep ([ i0 ], i, vl)
300
        when Basic_library.is_value_internal_fun
301
               (mk_val (Fun (i, vl)) i0.var_type) ->
302
        pp_machine_instr
303
          dependencies
304
          m
305
          self
306
          mem
307
          fmt
308
          (update_instr_desc
309
             instr
310
             (MLocalAssign (i0, mk_val (Fun (i, vl)) i0.var_type)))
311
      | MStep (il, i, vl) when !Options.mpfr && Mpfr.is_homomorphic_fun i ->
312
        pp_instance_call m self mem fmt i vl il
313
      | MStep ([ i0 ], i, vl) when has_c_prototype i dependencies ->
314
        fprintf
315
          fmt
316
          "%a = %s%a;"
317
          (pp_c_val m self (pp_c_var_read m))
318
          (mk_val (Var i0) i0.var_type)
319
          i
320
          (pp_print_parenthesized (pp_c_val m self (pp_c_var_read m)))
321
          vl
322
      | MStep (il, i, vl) ->
323
        let td, _ = List.assoc i m.minstances in
324
        if Arrow.td_is_arrow td then pp_arrow_call m self mem fmt i il
325
        else pp_basic_instance_call m self mem fmt i vl il
326
      | MBranch (_, []) ->
327
        eprintf
328
          "internal error: C_backend_src.pp_machine_instr %a@."
329
          (pp_instr m)
330
          instr;
331
        assert false
332
      | MBranch (g, hl) ->
333
        if
334
          let t = fst (List.hd hl) in
335
          t = tag_true || t = tag_false
336
        then
337
          (* boolean case, needs special treatment in C because truth value is
338
             not unique *)
339
          (* may disappear if we optimize code by replacing last branch test
340
             with default *)
341
          let tl = try List.assoc tag_true hl with Not_found -> [] in
342
          let el = try List.assoc tag_false hl with Not_found -> [] in
343
          let no_noreset =
344
            List.filter (fun i ->
345
                match i.instr_desc with MNoReset _ -> false | _ -> true)
346
          in
347
          pp_conditional
348
            dependencies
349
            m
350
            self
351
            mem
352
            fmt
353
            g
354
            (no_noreset tl)
355
            (no_noreset el)
356
        else
357
          (* enum type case *)
358
          (*let g_typ = Typing.type_const Location.dummy_loc (Const_tag (fst
359
            (List.hd hl))) in*)
360
          fprintf
361
            fmt
362
            "@[<v 2>switch(%a) {@,%a@,}@]"
363
            (pp_c_val m self (pp_c_var_read m))
364
            g
365
            (pp_print_list
366
               ~pp_open_box:pp_open_vbox0
367
               (pp_machine_branch dependencies m self mem))
368
            hl
369
      | MSpec s ->
370
        fprintf fmt "@[/*@@ %s */@]@ " s
371
      | MComment s ->
372
        fprintf fmt "/*%s*/@ " s
373
    in
374
    fprintf fmt "%a%a" pp_instr instr (Mod.pp_step_instr_spec m self mem) instr
375

    
376
  and pp_machine_branch dependencies m self mem fmt (t, h) =
377
    fprintf
378
      fmt
379
      "@[<v 2>case %a:@,%a@,break;@]"
380
      pp_c_tag
381
      t
382
      (pp_print_list
383
         ~pp_open_box:pp_open_vbox0
384
         (pp_machine_instr dependencies m self mem))
385
      h
386

    
387
  (* let pp_machine_nospec_instr dependencies m self fmt instr =
388
   *   pp_machine_instr dependencies m self fmt instr
389
   *
390
   * let pp_machine_step_instr dependencies m self mem fmt instr =
391
   *   fprintf fmt "%a%a"
392
   *     (pp_machine_instr dependencies m self) instr
393
   *     (Mod.pp_step_instr_spec m self mem) instr *)
394

    
395
  (********************************************************************************************)
396
  (* C file Printing functions *)
397
  (********************************************************************************************)
398

    
399
  let pp_const_def fmt tdecl =
400
    let cdecl = const_of_top tdecl in
401
    if !Options.mpfr && Types.(is_real_type (array_base_type cdecl.const_type))
402
    then
403
      fprintf
404
        fmt
405
        "%a;"
406
        (pp_c_type cdecl.const_id)
407
        (Types.dynamic_type cdecl.const_type)
408
    else
409
      fprintf
410
        fmt
411
        "%a = %a;"
412
        (pp_c_type cdecl.const_id)
413
        cdecl.const_type
414
        pp_c_const
415
        cdecl.const_value
416

    
417
  let pp_alloc_instance fmt (i, (m, static)) =
418
    fprintf
419
      fmt
420
      "_alloc->%s = %a %a;"
421
      i
422
      pp_machine_alloc_name
423
      (node_name m)
424
      (pp_print_parenthesized Dimension.pp)
425
      static
426

    
427
  let pp_dealloc_instance fmt (i, (m, _)) =
428
    fprintf fmt "%a (_alloc->%s);" pp_machine_dealloc_name (node_name m) i
429

    
430
  let const_locals m =
431
    List.filter (fun vdecl -> vdecl.var_dec_const) m.mstep.step_locals
432

    
433
  let pp_c_decl_array_mem self fmt id =
434
    fprintf
435
      fmt
436
      "%a = (%a) (%s->_reg.%s)"
437
      (pp_c_type (sprintf "(*%s)" id.var_id))
438
      id.var_type
439
      (pp_c_type "(*)")
440
      id.var_type
441
      self
442
      id.var_id
443

    
444
  let pp_alloc_const fmt m =
445
    pp_print_list
446
      ~pp_sep:(pp_print_endcut ";")
447
      ~pp_eol:(pp_print_endcut ";")
448
      (pp_c_decl_local_var m)
449
      fmt
450
      (const_locals m)
451

    
452
  let pp_alloc_array fmt vdecl =
453
    let base_type = Types.array_base_type vdecl.var_type in
454
    let size_types = Types.array_type_multi_dimension vdecl.var_type in
455
    let size_type = Dimension.multi_product vdecl.var_loc size_types in
456
    fprintf
457
      fmt
458
      "_alloc->_reg.%s = (%a*) malloc((%a)*sizeof(%a));@,assert(_alloc->%s);"
459
      vdecl.var_id
460
      (pp_c_type "")
461
      base_type
462
      Dimension.pp
463
      size_type
464
      (pp_c_type "")
465
      base_type
466
      vdecl.var_id
467

    
468
  let pp_dealloc_array fmt vdecl =
469
    fprintf fmt "free (_alloc->_reg.%s);" vdecl.var_id
470

    
471
  let array_mems m =
472
    List.filter (fun v -> Types.is_array_type v.var_type) m.mmemory
473

    
474
  let pp_alloc_code fmt m =
475
    fprintf
476
      fmt
477
      "%a *_alloc;@,\
478
       _alloc = (%a *) malloc(sizeof(%a));@,\
479
       assert(_alloc);@,\
480
       %a%areturn _alloc;"
481
      (pp_machine_memtype_name ~ghost:false)
482
      m.mname.node_id
483
      (pp_machine_memtype_name ~ghost:false)
484
      m.mname.node_id
485
      (pp_machine_memtype_name ~ghost:false)
486
      m.mname.node_id
487
      (pp_print_list ~pp_sep:pp_print_nothing pp_alloc_array)
488
      (array_mems m)
489
      (pp_print_list ~pp_sep:pp_print_nothing pp_alloc_instance)
490
      m.minstances
491

    
492
  let pp_dealloc_code fmt m =
493
    fprintf
494
      fmt
495
      "%a%afree (_alloc);@,return;"
496
      (pp_print_list ~pp_sep:pp_print_nothing pp_dealloc_array)
497
      (array_mems m)
498
      (pp_print_list ~pp_sep:pp_print_nothing pp_dealloc_instance)
499
      m.minstances
500

    
501
  (* let print_stateless_init_code fmt m self =
502
   *   let minit = List.map (fun i -> match get_instr_desc i with MReset i -> i | _ -> assert false) m.minit in
503
   *   let array_mems = List.filter (fun v -> Types.is_array_type v.var_type) m.mmemory in
504
   *   fprintf fmt "@[<v 2>%a {@,%a%t%a%t%a%treturn;@]@,}@.@."
505
   *     (print_init_prototype self) (m.mname.node_id, m.mstatic)
506
   *     (\* array mems *\)
507
   *     (Utils.fprintf_list ~sep:";@," (pp_c_decl_array_mem self)) array_mems
508
   *     (Utils.pp_final_char_if_non_empty ";@," array_mems)
509
   *     (\* memory initialization *\)
510
   *     (Utils.fprintf_list ~sep:"@," (pp_initialize m self (pp_c_var_read m))) m.mmemory
511
   *     (Utils.pp_newline_if_non_empty m.mmemory)
512
   *     (\* sub-machines initialization *\)
513
   *     (Utils.fprintf_list ~sep:"@," (pp_machine_init m self)) minit
514
   *     (Utils.pp_newline_if_non_empty m.minit)
515
   *
516
   * let print_stateless_clear_code fmt m self =
517
   *   let minit = List.map (fun i -> match get_instr_desc i with MReset i -> i | _ -> assert false) m.minit in
518
   *   let array_mems = List.filter (fun v -> Types.is_array_type v.var_type) m.mmemory in
519
   *   fprintf fmt "@[<v 2>%a {@,%a%t%a%t%a%treturn;@]@,}@.@."
520
   *     (print_clear_prototype self) (m.mname.node_id, m.mstatic)
521
   *     (\* array mems *\)
522
   *     (Utils.fprintf_list ~sep:";@," (pp_c_decl_array_mem self)) array_mems
523
   *     (Utils.pp_final_char_if_non_empty ";@," array_mems)
524
   *     (\* memory clear *\)
525
   *     (Utils.fprintf_list ~sep:"@," (pp_clear m self (pp_c_var_read m))) m.mmemory
526
   *     (Utils.pp_newline_if_non_empty m.mmemory)
527
   *     (\* sub-machines clear*\)
528
   *     (Utils.fprintf_list ~sep:"@," (pp_machine_clear m self)) minit
529
   *     (Utils.pp_newline_if_non_empty m.minit) *)
530

    
531
  let pp_c_check m self fmt (loc, check) =
532
    fprintf
533
      fmt
534
      "@[<v>%a@,assert (%a);@]"
535
      Location.pp_c
536
      loc
537
      (pp_c_val m self (pp_c_var_read m))
538
      check
539

    
540
  let pp_print_function ~pp_prototype ~prototype ?(pp_spec = pp_print_nothing)
541
      ?(pp_local = pp_print_nothing) ?(base_locals = [])
542
      ?(pp_array_mem = pp_print_nothing) ?(array_mems = [])
543
      ?(pp_init_mpfr_local = pp_print_nothing)
544
      ?(pp_clear_mpfr_local = pp_print_nothing) ?(mpfr_locals = [])
545
      ?(pp_check = pp_print_nothing) ?(checks = [])
546
      ?(pp_extra = pp_print_nothing)
547
      ?(pp_instr = fun fmt _ -> pp_print_nothing fmt ()) ?(instrs = []) fmt =
548
    fprintf
549
      fmt
550
      "%a@[<v 2>%a {@,%a%a%a%a%a%a%areturn;@]@,}"
551
      pp_spec
552
      ()
553
      pp_prototype
554
      prototype
555
      (* locals *)
556
      (pp_print_list
557
         ~pp_open_box:pp_open_vbox0
558
         ~pp_sep:pp_print_semicolon
559
         ~pp_eol:pp_print_semicolon
560
         pp_local)
561
      base_locals
562
      (* array mems *)
563
      (pp_print_list
564
         ~pp_open_box:pp_open_vbox0
565
         ~pp_sep:pp_print_semicolon
566
         ~pp_eol:pp_print_semicolon
567
         pp_array_mem)
568
      array_mems
569
      (* locals initialization *)
570
      (pp_print_list ~pp_epilogue:pp_print_cut pp_init_mpfr_local)
571
      (mpfr_vars mpfr_locals)
572
      (* check assertions *)
573
      (pp_print_list pp_check)
574
      checks
575
      (* instrs *)
576
      (pp_print_list
577
         ~pp_open_box:pp_open_vbox0
578
         ~pp_epilogue:pp_print_cut
579
         pp_instr)
580
      instrs
581
      (* locals clear *)
582
      (pp_print_list ~pp_epilogue:pp_print_cut pp_clear_mpfr_local)
583
      (mpfr_vars mpfr_locals) (* extra *)
584
      pp_extra
585
      ()
586

    
587
  let node_of_machine m =
588
    {
589
      top_decl_desc = Node m.mname;
590
      top_decl_loc = Location.dummy;
591
      top_decl_owner = "";
592
      top_decl_itf = false;
593
    }
594

    
595
  let pp_stateless_code machines dependencies fmt m =
596
    let self = "__ERROR__" in
597
    if not (!Options.ansi && is_generic_node (node_of_machine m)) then
598
      (* C99 code *)
599
      pp_print_function
600
        ~pp_spec:(fun fmt () -> Mod.pp_step_spec fmt machines self self m)
601
        ~pp_prototype:Protos.pp_stateless_prototype
602
        ~prototype:(m.mname.node_id, m.mstep.step_inputs, m.mstep.step_outputs)
603
        ~pp_local:(pp_c_decl_local_var m)
604
        ~base_locals:m.mstep.step_locals
605
        ~pp_init_mpfr_local:(pp_initialize m self (pp_c_var_read m))
606
        ~pp_clear_mpfr_local:(pp_clear m self (pp_c_var_read m))
607
        ~mpfr_locals:m.mstep.step_locals
608
        ~pp_check:(pp_c_check m self)
609
        ~checks:m.mstep.step_checks
610
        ~pp_instr:(pp_machine_instr dependencies m self self)
611
        ~instrs:m.mstep.step_instrs
612
        fmt
613
    else
614
      (* C90 code *)
615
      let gen_locals, base_locals =
616
        List.partition
617
          (fun v -> Types.is_generic_type v.var_type)
618
          m.mstep.step_locals
619
      in
620
      let gen_calls =
621
        List.map
622
          (fun e ->
623
            let id, _, _ = call_of_expr e in
624
            mk_call_var_decl e.expr_loc id)
625
          m.mname.node_gencalls
626
      in
627
      pp_print_function
628
        ~pp_prototype:Protos.pp_stateless_prototype
629
        ~prototype:
630
          ( m.mname.node_id,
631
            m.mstep.step_inputs @ gen_locals @ gen_calls,
632
            m.mstep.step_outputs )
633
        ~pp_local:(pp_c_decl_local_var m)
634
        ~base_locals
635
        ~pp_init_mpfr_local:(pp_initialize m self (pp_c_var_read m))
636
        ~pp_clear_mpfr_local:(pp_clear m self (pp_c_var_read m))
637
        ~mpfr_locals:m.mstep.step_locals
638
        ~pp_check:(pp_c_check m self)
639
        ~checks:m.mstep.step_checks
640
        ~pp_instr:(pp_machine_instr dependencies m self self)
641
        ~instrs:m.mstep.step_instrs
642
        fmt
643

    
644
  let pp_clear_reset_code dependencies self mem fmt m =
645
    pp_print_function
646
      ~pp_spec:(fun fmt () -> Mod.pp_clear_reset_spec fmt self mem m)
647
      ~pp_prototype:(Protos.pp_clear_reset_prototype self mem)
648
      ~prototype:(m.mname.node_id, m.mstatic)
649
      ~pp_local:(pp_c_decl_local_var m)
650
      ~base_locals:(const_locals m)
651
      ~pp_instr:(pp_machine_instr dependencies m self mem)
652
      ~instrs:
653
        [
654
          mk_branch
655
            (mk_val ResetFlag Type_predef.type_bool)
656
            [ "true", mkinstr (MResetAssign false) :: m.minit ];
657
        ]
658
      fmt
659

    
660
  let pp_set_reset_code dependencies self mem fmt m =
661
    pp_print_function
662
      ~pp_spec:(fun fmt () -> Mod.pp_set_reset_spec fmt self mem m)
663
      ~pp_prototype:(Protos.pp_set_reset_prototype self mem)
664
      ~prototype:(m.mname.node_id, m.mstatic)
665
      ~pp_instr:(pp_machine_instr dependencies m self mem)
666
      ~instrs:[ mkinstr (MResetAssign true) ]
667
      fmt
668

    
669
  let pp_init_code self fmt m =
670
    let minit =
671
      List.map
672
        (fun i ->
673
          match get_instr_desc i with MSetReset i -> i | _ -> assert false)
674
        m.minit
675
    in
676
    pp_print_function
677
      ~pp_prototype:(Protos.pp_init_prototype self)
678
      ~prototype:(m.mname.node_id, m.mstatic)
679
      ~pp_array_mem:(pp_c_decl_array_mem self)
680
      ~array_mems:(array_mems m)
681
      ~pp_init_mpfr_local:(pp_initialize m self (pp_c_var_read m))
682
      ~mpfr_locals:m.mmemory
683
      ~pp_extra:(fun fmt () ->
684
        pp_print_list
685
          ~pp_open_box:pp_open_vbox0
686
          ~pp_epilogue:pp_print_cut
687
          (pp_machine_init m self self)
688
          fmt
689
          minit)
690
      fmt
691

    
692
  let pp_clear_code self fmt m =
693
    let minit =
694
      List.map
695
        (fun i ->
696
          match get_instr_desc i with MSetReset i -> i | _ -> assert false)
697
        m.minit
698
    in
699
    pp_print_function
700
      ~pp_prototype:(Protos.pp_clear_prototype self)
701
      ~prototype:(m.mname.node_id, m.mstatic)
702
      ~pp_array_mem:(pp_c_decl_array_mem self)
703
      ~array_mems:(array_mems m)
704
      ~pp_clear_mpfr_local:(pp_clear m self (pp_c_var_read m))
705
      ~mpfr_locals:m.mmemory
706
      ~pp_extra:(fun fmt () ->
707
        pp_print_list
708
          ~pp_open_box:pp_open_vbox0
709
          ~pp_epilogue:pp_print_cut
710
          (pp_machine_clear m self self)
711
          fmt
712
          minit)
713
      fmt
714

    
715
  let pp_step_code machines dependencies self mem fmt m =
716
    if not (!Options.ansi && is_generic_node (node_of_machine m)) then
717
      (* C99 code *)
718
      pp_print_function
719
        ~pp_spec:(fun fmt () -> Mod.pp_step_spec fmt machines self mem m)
720
        ~pp_prototype:(Protos.pp_step_prototype self mem)
721
        ~prototype:(m.mname.node_id, m.mstep.step_inputs, m.mstep.step_outputs)
722
        ~pp_local:(pp_c_decl_local_var m)
723
        ~base_locals:m.mstep.step_locals
724
        ~pp_array_mem:(pp_c_decl_array_mem self)
725
        ~array_mems:(array_mems m)
726
        ~pp_init_mpfr_local:(pp_initialize m self (pp_c_var_read m))
727
        ~pp_clear_mpfr_local:(pp_clear m self (pp_c_var_read m))
728
        ~mpfr_locals:m.mstep.step_locals
729
        ~pp_check:(pp_c_check m self)
730
        ~checks:m.mstep.step_checks
731
        ~pp_instr:(pp_machine_instr dependencies m self mem)
732
        ~instrs:m.mstep.step_instrs
733
        fmt
734
    else
735
      (* C90 code *)
736
      let gen_locals, base_locals =
737
        List.partition
738
          (fun v -> Types.is_generic_type v.var_type)
739
          m.mstep.step_locals
740
      in
741
      let gen_calls =
742
        List.map
743
          (fun e ->
744
            let id, _, _ = call_of_expr e in
745
            mk_call_var_decl e.expr_loc id)
746
          m.mname.node_gencalls
747
      in
748
      pp_print_function
749
        ~pp_spec:(fun fmt () -> Mod.pp_step_spec fmt machines self mem m)
750
        ~pp_prototype:(Protos.pp_step_prototype self mem)
751
        ~prototype:
752
          ( m.mname.node_id,
753
            m.mstep.step_inputs @ gen_locals @ gen_calls,
754
            m.mstep.step_outputs )
755
        ~pp_local:(pp_c_decl_local_var m)
756
        ~base_locals
757
        ~pp_init_mpfr_local:(pp_initialize m self (pp_c_var_read m))
758
        ~pp_clear_mpfr_local:(pp_clear m self (pp_c_var_read m))
759
        ~mpfr_locals:m.mstep.step_locals
760
        ~pp_check:(pp_c_check m self)
761
        ~checks:m.mstep.step_checks
762
        ~pp_instr:(pp_machine_instr dependencies m self mem)
763
        ~instrs:m.mstep.step_instrs
764
        fmt
765

    
766
  (********************************************************************************************)
767
  (* MAIN C file Printing functions *)
768
  (********************************************************************************************)
769

    
770
  let pp_const_initialize m pp_var fmt const =
771
    let var =
772
      Machine_code_common.mk_val
773
        (Var (Corelang.var_decl_of_const const))
774
        const.const_type
775
    in
776
    let rec aux indices value fmt typ =
777
      if Types.is_array_type typ then
778
        let dim = Types.array_type_dimension typ in
779
        let szl = Utils.enumerate (Dimension.size_const dim) in
780
        let typ' = Types.array_element_type typ in
781
        let value =
782
          match value with Const_array ca -> List.nth ca | _ -> assert false
783
        in
784
        pp_print_list
785
          (fun fmt i -> aux (string_of_int i :: indices) (value i) fmt typ')
786
          fmt
787
          szl
788
      else
789
        let indices = List.rev indices in
790
        let pp_var_suffix fmt var =
791
          fprintf fmt "%a%a" (pp_c_val m "" pp_var) var pp_array_suffix indices
792
        in
793
        fprintf
794
          fmt
795
          "%a@,%a"
796
          (Mpfr.pp_inject_init pp_var_suffix)
797
          var
798
          (Mpfr.pp_inject_real pp_var_suffix pp_c_const)
799
          (var, value)
800
    in
801
    reset_loop_counter ();
802
    aux [] const.const_value fmt const.const_type
803

    
804
  let pp_const_clear pp_var fmt const =
805
    let m = Machine_code_common.empty_machine in
806
    let var = Corelang.var_decl_of_const const in
807
    let rec aux indices fmt typ =
808
      if Types.is_array_type typ then
809
        let dim = Types.array_type_dimension typ in
810
        let idx = mk_loop_var m () in
811
        fprintf
812
          fmt
813
          "@[<v 2>{@,int %s;@,for(%s=0;%s<%a;%s++)@,%a @]@,}"
814
          idx
815
          idx
816
          idx
817
          pp_c_dimension
818
          dim
819
          idx
820
          (aux (idx :: indices))
821
          (Types.array_element_type typ)
822
      else
823
        let indices = List.rev indices in
824
        let pp_var_suffix fmt var =
825
          fprintf fmt "%a%a" (pp_c_var m "" pp_var) var pp_array_suffix indices
826
        in
827
        Mpfr.pp_inject_clear pp_var_suffix fmt var
828
    in
829
    reset_loop_counter ();
830
    aux [] fmt var.var_type
831

    
832
  let pp_import_init fmt dep =
833
    let baseNAME = file_to_module_name dep.name in
834
    fprintf fmt "%a();" pp_global_init_name baseNAME
835

    
836
  let pp_import_clear fmt dep =
837
    let baseNAME = file_to_module_name dep.name in
838
    fprintf fmt "%a();" pp_global_clear_name baseNAME
839

    
840
  let pp_global_init_code fmt (basename, prog, dependencies) =
841
    let baseNAME = file_to_module_name basename in
842
    let constants = List.map const_of_top (get_consts prog) in
843
    fprintf
844
      fmt
845
      "@[<v 2>%a {@,\
846
       static %s init = 0;@,\
847
       @[<v 2>if (!init) { @,\
848
       init = 1;%a%a@]@,\
849
       }@,\
850
       return;@]@,\
851
       }"
852
      pp_global_init_prototype
853
      baseNAME
854
      (pp_c_basic_type_desc Type_predef.type_bool)
855
      (* constants *)
856
      (pp_print_list
857
         ~pp_prologue:pp_print_cut
858
         (pp_const_initialize empty_machine (pp_c_var_read empty_machine)))
859
      (mpfr_consts constants)
860
      (* dependencies initialization *)
861
      (pp_print_list ~pp_prologue:pp_print_cut pp_import_init)
862
      (List.filter (fun dep -> dep.local) dependencies)
863

    
864
  let pp_global_clear_code fmt (basename, prog, dependencies) =
865
    let baseNAME = file_to_module_name basename in
866
    let constants = List.map const_of_top (get_consts prog) in
867
    fprintf
868
      fmt
869
      "@[<v 2>%a {@,\
870
       static %s clear = 0;@,\
871
       @[<v 2>if (!clear) { @,\
872
       clear = 1;%a%a@]@,\
873
       }@,\
874
       return;@]@,\
875
       }"
876
      pp_global_clear_prototype
877
      baseNAME
878
      (pp_c_basic_type_desc Type_predef.type_bool)
879
      (* constants *)
880
      (pp_print_list
881
         ~pp_prologue:pp_print_cut
882
         (pp_const_clear (pp_c_var_read empty_machine)))
883
      (mpfr_consts constants)
884
      (* dependencies initialization *)
885
      (pp_print_list ~pp_prologue:pp_print_cut pp_import_clear)
886
      (List.filter (fun dep -> dep.local) dependencies)
887

    
888
  let pp_alloc_function fmt m =
889
    if not !Options.static_mem then
890
      (* Alloc functions, only if non static mode *)
891
      fprintf
892
        fmt
893
        "@[<v 2>%a {@,%a%a@]@,}@,@[<v 2>%a {@,%a%a@]@,@,"
894
        pp_alloc_prototype
895
        (m.mname.node_id, m.mstatic)
896
        pp_alloc_const
897
        m
898
        pp_alloc_code
899
        m
900
        pp_dealloc_prototype
901
        m.mname.node_id
902
        pp_alloc_const
903
        m
904
        pp_dealloc_code
905
        m
906

    
907
  let pp_mpfr_code self fmt m =
908
    if !Options.mpfr then
909
      fprintf
910
        fmt
911
        "@,@[<v>%a@,%a@]"
912
        (* Init function *)
913
        (pp_init_code self)
914
        m
915
        (* Clear function *)
916
        (pp_clear_code self)
917
        m
918

    
919
  (* TODO: ACSL - a contract machine shall not be directly printed in the C
920
     source - but a regular machine associated to a contract machine shall
921
     integrate the associated statements, updating its memories, at the end of
922
     the function body. - last one may print intermediate comment/acsl if/when
923
     they are present in the sequence of instruction *)
924
  let pp_machine machines dependencies fmt m =
925
    if fst (get_stateless_status m) then
926
      (* Step function *)
927
      pp_stateless_code machines dependencies fmt m
928
    else
929
      let self = mk_self m in
930
      let mem = mk_mem m in
931
      fprintf
932
        fmt
933
        "@[<v>%a%a@,@,%a@,@,%a%a@]"
934
        pp_alloc_function
935
        m
936
        (* Reset functions *)
937
        (pp_clear_reset_code dependencies self mem)
938
        m
939
        (pp_set_reset_code dependencies self mem)
940
        m
941
        (* Step function *)
942
        (pp_step_code machines dependencies self mem)
943
        m
944
        (pp_mpfr_code self)
945
        m
946

    
947
  let pp_import_standard source_fmt () =
948
    fprintf
949
      source_fmt
950
      "@[<v>#include <assert.h>@,%a%a%a@]"
951
      (if Machine_types.has_machine_type () then
952
       pp_print_endcut "#include <stdint.h>"
953
      else pp_print_nothing)
954
      ()
955
      (if not !Options.static_mem then pp_print_endcut "#include <stdlib.h>"
956
      else pp_print_nothing)
957
      ()
958
      (if !Options.mpfr then pp_print_endcut "#include <mpfr.h>"
959
      else pp_print_nothing)
960
      ()
961

    
962
  let pp_extern_alloc_prototype fmt ind =
963
    let static = List.filter (fun v -> v.var_dec_const) ind.nodei_inputs in
964
    fprintf
965
      fmt
966
      "extern %a;@,extern %a;"
967
      pp_alloc_prototype
968
      (ind.nodei_id, static)
969
      pp_dealloc_prototype
970
      ind.nodei_id
971

    
972
  let pp_lib_c source_fmt basename prog machines dependencies =
973
    fprintf
974
      source_fmt
975
      "@[<v>%a%a@,@,%a@,%a%a%a%a%a%a%a@]@."
976
      pp_import_standard
977
      ()
978
      pp_import_prototype
979
      {
980
        local = true;
981
        name = basename;
982
        content = [];
983
        is_stateful = true (* assuming it is stateful *);
984
      }
985
      (* Print the svn version number and the supported C standard (C90 or C99) *)
986
      pp_print_version
987
      ()
988
      (* Print dependencies *)
989
      (pp_print_list
990
         ~pp_open_box:pp_open_vbox0
991
         ~pp_prologue:(pp_print_endcut "/* Import dependencies */")
992
         pp_import_prototype
993
         ~pp_epilogue:pp_print_cutcut)
994
      dependencies
995
      (* Print consts *)
996
      (pp_print_list
997
         ~pp_open_box:pp_open_vbox0
998
         ~pp_prologue:(pp_print_endcut "/* Global constants (definitions) */")
999
         pp_const_def
1000
         ~pp_epilogue:pp_print_cutcut)
1001
      (get_consts prog)
1002
      (* MPFR *)
1003
      (if !Options.mpfr then fun fmt () ->
1004
       fprintf
1005
         fmt
1006
         "@[<v>/* Global constants initialization */@,\
1007
          %a@,\
1008
          @,\
1009
          /* Global constants clearing */@,\
1010
          %a@]@,\
1011
          @,"
1012
         pp_global_init_code
1013
         (basename, prog, dependencies)
1014
         pp_global_clear_code
1015
         (basename, prog, dependencies)
1016
      else pp_print_nothing)
1017
      ()
1018
      (if not !Options.static_mem then fun fmt () ->
1019
       fprintf
1020
         fmt
1021
         "@[<v>%a%a@]@,@,"
1022
         (pp_print_list
1023
            ~pp_open_box:pp_open_vbox0
1024
            ~pp_epilogue:pp_print_cut
1025
            ~pp_prologue:
1026
              (pp_print_endcut "/* External allocation function prototypes */")
1027
            (fun fmt dep ->
1028
              pp_print_list
1029
                ~pp_open_box:pp_open_vbox0
1030
                ~pp_epilogue:pp_print_cut
1031
                pp_extern_alloc_prototype
1032
                fmt
1033
                (List.filter_map
1034
                   (fun decl ->
1035
                     match decl.top_decl_desc with
1036
                     | ImportedNode ind when not ind.nodei_stateless ->
1037
                       Some ind
1038
                     | _ ->
1039
                       None)
1040
                   dep.content)))
1041
         dependencies
1042
         (pp_print_list
1043
            ~pp_open_box:pp_open_vbox0
1044
            ~pp_prologue:
1045
              (pp_print_endcut "/* Node allocation function prototypes */")
1046
            ~pp_sep:pp_print_cutcut
1047
            (fun fmt m ->
1048
              fprintf
1049
                fmt
1050
                "%a;@,%a;"
1051
                pp_alloc_prototype
1052
                (m.mname.node_id, m.mstatic)
1053
                pp_dealloc_prototype
1054
                m.mname.node_id))
1055
         machines
1056
      else pp_print_nothing)
1057
      ()
1058
      (* Print the struct definitions of all machines. *)
1059
      (pp_print_list
1060
         ~pp_open_box:pp_open_vbox0
1061
         ~pp_prologue:(pp_print_endcut "/* Struct definitions */")
1062
         ~pp_sep:pp_print_cutcut
1063
         pp_machine_struct
1064
         ~pp_epilogue:pp_print_cutcut)
1065
      machines
1066
      (* Print the spec predicates *) Mod.pp_predicates
1067
      machines
1068
      (* Print nodes one by one (in the previous order) *)
1069
      (pp_print_list
1070
         ~pp_open_box:pp_open_vbox0
1071
         ~pp_sep:pp_print_cutcut
1072
         (pp_machine machines dependencies))
1073
      machines
1074
end
1075

    
1076
(* Local Variables: *)
1077
(* compile-command:"make -C ../../.." *)
1078
(* End: *)
(17-17/18)