Project

General

Profile

Download (33.5 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

    
20
module Mpfr = Lustrec_mpfr
21

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

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

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

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

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

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

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

    
40
module EmptyMod = struct
41
  module GhostProto = EmptyGhostProto
42

    
43
  let pp_predicates _ _ = ()
44

    
45
  let pp_set_reset_spec _ _ _ _ = ()
46

    
47
  let pp_clear_reset_spec _ _ _ _ = ()
48

    
49
  let pp_step_spec _ _ _ _ _ = ()
50

    
51
  let pp_step_instr_spec _ _ _ _ _ = ()
52

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

    
56
module Main =
57
functor
58
  (Mod : MODIFIERS_SRC)
59
  ->
60
  struct
61
    module Protos = Protos (Mod.GhostProto)
62

    
63
    (********************************************************************************************)
64
    (* Instruction Printing functions *)
65
    (********************************************************************************************)
66

    
67
    let rec merge_static_loop_profiles lp1 lp2 =
68
      match lp1, lp2 with
69
      | [], _ ->
70
        lp2
71
      | _, [] ->
72
        lp1
73
      | p1 :: q1, p2 :: q2 ->
74
        (p1 || p2) :: merge_static_loop_profiles q1 q2
75

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

    
99
    and static_loop_profile_cst cst =
100
      match cst with
101
      | Const_array cl ->
102
        List.fold_right
103
          (fun c lp ->
104
            merge_static_loop_profiles lp (static_loop_profile_cst c))
105
          cl []
106
      | _ ->
107
        []
108

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

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

    
143
    let pp_machine_set_reset m self mem fmt inst =
144
      pp_machine_ pp_machine_set_reset_name "pp_machine_set_reset" m fmt ~inst
145
        self mem
146

    
147
    let pp_machine_clear_reset m self mem fmt =
148
      pp_machine_ pp_machine_clear_reset_name "pp_machine_clear_reset" m fmt
149
        self mem
150

    
151
    let pp_machine_init m self mem fmt inst =
152
      pp_machine_ pp_machine_init_name "pp_machine_init" m fmt ~inst self mem
153

    
154
    let pp_machine_clear m self mem fmt inst =
155
      pp_machine_ pp_machine_clear_name "pp_machine_clear" m fmt ~inst self mem
156

    
157
    let pp_call m self mem pp_read pp_write fmt i inputs outputs =
158
      try
159
        (* stateful node instance *)
160
        let n, _ = List.assoc i m.minstances in
161
        fprintf fmt "%a(%a%a%s->%s)%a;" pp_machine_step_name (node_name n)
162
          (pp_comma_list ~pp_eol:pp_print_comma (pp_c_val m self pp_read))
163
          inputs
164
          (pp_comma_list ~pp_eol:pp_print_comma pp_write)
165
          outputs self i
166
          (Mod.pp_ghost_parameter mem)
167
          (Some i)
168
      with Not_found ->
169
        (* stateless node instance *)
170
        let n, _ = List.assoc i m.mcalls in
171
        fprintf fmt "%a(%a%a);" pp_machine_step_name (node_name n)
172
          (pp_comma_list ~pp_eol:pp_print_comma (pp_c_val m self pp_read))
173
          inputs (pp_comma_list pp_write) outputs
174

    
175
    let pp_basic_instance_call m self mem =
176
      pp_call m self mem (pp_c_var_read m) (pp_c_var_write m)
177

    
178
    let pp_arrow_call m self mem fmt i outputs =
179
      match outputs with
180
      | [ x ] ->
181
        fprintf fmt "%a = %a(%s->%s)%a;" (pp_c_var_read m) x
182
          pp_machine_step_name Arrow.arrow_id self i
183
          (Mod.pp_ghost_parameter mem)
184
          (Some i)
185
      | _ ->
186
        assert false
187

    
188
    let pp_instance_call m self mem fmt i inputs outputs =
189
      let pp_offset pp_var indices fmt var =
190
        fprintf fmt "%a%a" pp_var var
191
          (pp_print_list ~pp_sep:pp_print_nothing (fun fmt ->
192
               fprintf fmt "[%s]"))
193
          indices
194
      in
195
      let rec aux indices fmt typ =
196
        if Types.is_array_type typ then
197
          let dim = Types.array_type_dimension typ in
198
          let idx = mk_loop_var m () in
199
          fprintf fmt "@[<v 2>{@,int %s;@,for(%s=0;%s<%a;%s++)@,%a @]@,}" idx
200
            idx idx pp_c_dimension dim idx
201
            (aux (idx :: indices))
202
            (Types.array_element_type typ)
203
        else
204
          let pp_read = pp_offset (pp_c_var_read m) indices in
205
          let pp_write = pp_offset (pp_c_var_write m) indices in
206
          pp_call m self mem pp_read pp_write fmt i inputs outputs
207
      in
208
      reset_loop_counter ();
209
      aux [] fmt (List.hd inputs).Machine_code_types.value_type
210

    
211
    let rec pp_conditional dependencies m self mem fmt c tl el =
212
      let pp_machine_instrs =
213
        pp_print_list ~pp_open_box:pp_open_vbox0 ~pp_prologue:pp_print_cut
214
          (pp_machine_instr dependencies m self mem)
215
      in
216
      let pp_cond = pp_c_val m self (pp_c_var_read m) in
217
      match tl, el with
218
      | [], _ :: _ ->
219
        fprintf fmt "@[<v 2>if (!%a) {%a@]@,}" pp_cond c pp_machine_instrs el
220
      | _, [] ->
221
        fprintf fmt "@[<v 2>if (%a) {%a@]@,}" pp_cond c pp_machine_instrs tl
222
      | _, _ ->
223
        fprintf fmt "@[<v 2>if (%a) {%a@]@,@[<v 2>} else {%a@]@,}" pp_cond c
224
          pp_machine_instrs tl pp_machine_instrs el
225

    
226
    and pp_machine_instr dependencies m self mem fmt instr =
227
      let pp_instr fmt instr =
228
        match get_instr_desc instr with
229
        | MNoReset _ ->
230
          ()
231
        | MSetReset inst ->
232
          pp_machine_set_reset m self mem fmt inst
233
        | MClearReset ->
234
          if not (fst (get_stateless_status m)) then
235
            fprintf fmt "%t@,%a"
236
              (pp_machine_clear_reset m self mem)
237
              pp_label reset_label
238
        | MResetAssign b ->
239
          pp_reset_assign self fmt b
240
        | MLocalAssign (i, v) ->
241
          pp_assign m self (pp_c_var_read m) fmt (i, v)
242
        | MStateAssign (i, v) ->
243
          pp_assign m self (pp_c_var_read m) fmt (i, v)
244
        | MStep ([ i0 ], i, vl)
245
          when Basic_library.is_value_internal_fun
246
                 (mk_val (Fun (i, vl)) i0.var_type) ->
247
          pp_machine_instr dependencies m self mem fmt
248
            (update_instr_desc instr
249
               (MLocalAssign (i0, mk_val (Fun (i, vl)) i0.var_type)))
250
        | MStep (il, i, vl) when !Options.mpfr && Mpfr.is_homomorphic_fun i ->
251
          pp_instance_call m self mem fmt i vl il
252
        | MStep ([ i0 ], i, vl) when has_c_prototype i dependencies ->
253
          fprintf fmt "%a = %s%a;"
254
            (pp_c_val m self (pp_c_var_read m))
255
            (mk_val (Var i0) i0.var_type)
256
            i
257
            (pp_print_parenthesized (pp_c_val m self (pp_c_var_read m)))
258
            vl
259
        | MStep (il, i, vl) ->
260
          let td, _ = List.assoc i m.minstances in
261
          if Arrow.td_is_arrow td then pp_arrow_call m self mem fmt i il
262
          else pp_basic_instance_call m self mem fmt i vl il
263
        | MBranch (_, []) ->
264
          eprintf "internal error: C_backend_src.pp_machine_instr %a@."
265
            (pp_instr m) instr;
266
          assert false
267
        | MBranch (g, hl) ->
268
          if
269
            let t = fst (List.hd hl) in
270
            t = tag_true || t = tag_false
271
          then
272
            (* boolean case, needs special treatment in C because truth value is
273
               not unique *)
274
            (* may disappear if we optimize code by replacing last branch test
275
               with default *)
276
            let tl = try List.assoc tag_true hl with Not_found -> [] in
277
            let el = try List.assoc tag_false hl with Not_found -> [] in
278
            let no_noreset =
279
              List.filter (fun i ->
280
                  match i.instr_desc with MNoReset _ -> false | _ -> true)
281
            in
282
            pp_conditional dependencies m self mem fmt g (no_noreset tl)
283
              (no_noreset el)
284
          else
285
            (* enum type case *)
286
            (*let g_typ = Typing.type_const Location.dummy_loc (Const_tag (fst
287
              (List.hd hl))) in*)
288
            fprintf fmt "@[<v 2>switch(%a) {@,%a@,}@]"
289
              (pp_c_val m self (pp_c_var_read m))
290
              g
291
              (pp_print_list ~pp_open_box:pp_open_vbox0
292
                 (pp_machine_branch dependencies m self mem))
293
              hl
294
        | MSpec s ->
295
          fprintf fmt "@[/*@@ %s */@]@ " s
296
        | MComment s ->
297
          fprintf fmt "/*%s*/@ " s
298
      in
299
      fprintf fmt "%a%a" pp_instr instr
300
        (Mod.pp_step_instr_spec m self mem)
301
        instr
302

    
303
    and pp_machine_branch dependencies m self mem fmt (t, h) =
304
      fprintf fmt "@[<v 2>case %a:@,%a@,break;@]" pp_c_tag t
305
        (pp_print_list ~pp_open_box:pp_open_vbox0
306
           (pp_machine_instr dependencies m self mem))
307
        h
308

    
309
    (* let pp_machine_nospec_instr dependencies m self fmt instr =
310
     *   pp_machine_instr dependencies m self fmt instr
311
     *
312
     * let pp_machine_step_instr dependencies m self mem fmt instr =
313
     *   fprintf fmt "%a%a"
314
     *     (pp_machine_instr dependencies m self) instr
315
     *     (Mod.pp_step_instr_spec m self mem) instr *)
316

    
317
    (********************************************************************************************)
318
    (* C file Printing functions *)
319
    (********************************************************************************************)
320

    
321
    let print_const_def fmt tdecl =
322
      let cdecl = const_of_top tdecl in
323
      if
324
        !Options.mpfr && Types.(is_real_type (array_base_type cdecl.const_type))
325
      then
326
        fprintf fmt "%a;" (pp_c_type cdecl.const_id)
327
          (Types.dynamic_type cdecl.const_type)
328
      else
329
        fprintf fmt "%a = %a;" (pp_c_type cdecl.const_id) cdecl.const_type
330
          pp_c_const cdecl.const_value
331

    
332
    let print_alloc_instance fmt (i, (m, static)) =
333
      fprintf fmt "_alloc->%s = %a %a;" i pp_machine_alloc_name (node_name m)
334
        (pp_print_parenthesized Dimension.pp)
335
        static
336

    
337
    let print_dealloc_instance fmt (i, (m, _)) =
338
      fprintf fmt "%a (_alloc->%s);" pp_machine_dealloc_name (node_name m) i
339

    
340
    let const_locals m =
341
      List.filter (fun vdecl -> vdecl.var_dec_const) m.mstep.step_locals
342

    
343
    let pp_c_decl_array_mem self fmt id =
344
      fprintf fmt "%a = (%a) (%s->_reg.%s)"
345
        (pp_c_type (sprintf "(*%s)" id.var_id))
346
        id.var_type (pp_c_type "(*)") id.var_type self id.var_id
347

    
348
    let print_alloc_const fmt m =
349
      pp_print_list ~pp_sep:(pp_print_endcut ";") ~pp_eol:(pp_print_endcut ";")
350
        (pp_c_decl_local_var m) fmt (const_locals m)
351

    
352
    let print_alloc_array fmt vdecl =
353
      let base_type = Types.array_base_type vdecl.var_type in
354
      let size_types = Types.array_type_multi_dimension vdecl.var_type in
355
      let size_type =
356
        Dimension.multi_product vdecl.var_loc size_types
357
      in
358
      fprintf fmt
359
        "_alloc->_reg.%s = (%a*) malloc((%a)*sizeof(%a));@,assert(_alloc->%s);"
360
        vdecl.var_id (pp_c_type "") base_type Dimension.pp size_type
361
        (pp_c_type "") base_type vdecl.var_id
362

    
363
    let print_dealloc_array fmt vdecl =
364
      fprintf fmt "free (_alloc->_reg.%s);" vdecl.var_id
365

    
366
    let array_mems m =
367
      List.filter (fun v -> Types.is_array_type v.var_type) m.mmemory
368

    
369
    let print_alloc_code fmt m =
370
      fprintf fmt
371
        "%a *_alloc;@,\
372
         _alloc = (%a *) malloc(sizeof(%a));@,\
373
         assert(_alloc);@,\
374
         %a%areturn _alloc;"
375
        (pp_machine_memtype_name ~ghost:false)
376
        m.mname.node_id
377
        (pp_machine_memtype_name ~ghost:false)
378
        m.mname.node_id
379
        (pp_machine_memtype_name ~ghost:false)
380
        m.mname.node_id
381
        (pp_print_list ~pp_sep:pp_print_nothing print_alloc_array)
382
        (array_mems m)
383
        (pp_print_list ~pp_sep:pp_print_nothing print_alloc_instance)
384
        m.minstances
385

    
386
    let print_dealloc_code fmt m =
387
      fprintf fmt "%a%afree (_alloc);@,return;"
388
        (pp_print_list ~pp_sep:pp_print_nothing print_dealloc_array)
389
        (array_mems m)
390
        (pp_print_list ~pp_sep:pp_print_nothing print_dealloc_instance)
391
        m.minstances
392

    
393
    (* let print_stateless_init_code fmt m self =
394
     *   let minit = List.map (fun i -> match get_instr_desc i with MReset i -> i | _ -> assert false) m.minit in
395
     *   let array_mems = List.filter (fun v -> Types.is_array_type v.var_type) m.mmemory in
396
     *   fprintf fmt "@[<v 2>%a {@,%a%t%a%t%a%treturn;@]@,}@.@."
397
     *     (print_init_prototype self) (m.mname.node_id, m.mstatic)
398
     *     (\* array mems *\)
399
     *     (Utils.fprintf_list ~sep:";@," (pp_c_decl_array_mem self)) array_mems
400
     *     (Utils.pp_final_char_if_non_empty ";@," array_mems)
401
     *     (\* memory initialization *\)
402
     *     (Utils.fprintf_list ~sep:"@," (pp_initialize m self (pp_c_var_read m))) m.mmemory
403
     *     (Utils.pp_newline_if_non_empty m.mmemory)
404
     *     (\* sub-machines initialization *\)
405
     *     (Utils.fprintf_list ~sep:"@," (pp_machine_init m self)) minit
406
     *     (Utils.pp_newline_if_non_empty m.minit)
407
     *
408
     * let print_stateless_clear_code fmt m self =
409
     *   let minit = List.map (fun i -> match get_instr_desc i with MReset i -> i | _ -> assert false) m.minit in
410
     *   let array_mems = List.filter (fun v -> Types.is_array_type v.var_type) m.mmemory in
411
     *   fprintf fmt "@[<v 2>%a {@,%a%t%a%t%a%treturn;@]@,}@.@."
412
     *     (print_clear_prototype self) (m.mname.node_id, m.mstatic)
413
     *     (\* array mems *\)
414
     *     (Utils.fprintf_list ~sep:";@," (pp_c_decl_array_mem self)) array_mems
415
     *     (Utils.pp_final_char_if_non_empty ";@," array_mems)
416
     *     (\* memory clear *\)
417
     *     (Utils.fprintf_list ~sep:"@," (pp_clear m self (pp_c_var_read m))) m.mmemory
418
     *     (Utils.pp_newline_if_non_empty m.mmemory)
419
     *     (\* sub-machines clear*\)
420
     *     (Utils.fprintf_list ~sep:"@," (pp_machine_clear m self)) minit
421
     *     (Utils.pp_newline_if_non_empty m.minit) *)
422

    
423
    let pp_c_check m self fmt (loc, check) =
424
      fprintf fmt "@[<v>%a@,assert (%a);@]" Location.pp_c loc
425
        (pp_c_val m self (pp_c_var_read m))
426
        check
427

    
428
    let pp_print_function ~pp_prototype ~prototype ?(pp_spec = pp_print_nothing)
429
        ?(pp_local = pp_print_nothing) ?(base_locals = [])
430
        ?(pp_array_mem = pp_print_nothing) ?(array_mems = [])
431
        ?(pp_init_mpfr_local = pp_print_nothing)
432
        ?(pp_clear_mpfr_local = pp_print_nothing) ?(mpfr_locals = [])
433
        ?(pp_check = pp_print_nothing) ?(checks = [])
434
        ?(pp_extra = pp_print_nothing)
435
        ?(pp_instr = fun fmt _ -> pp_print_nothing fmt ()) ?(instrs = []) fmt =
436
      fprintf fmt "%a@[<v 2>%a {@,%a%a%a%a%a%a%areturn;@]@,}" pp_spec ()
437
        pp_prototype prototype
438
        (* locals *)
439
        (pp_print_list ~pp_open_box:pp_open_vbox0 ~pp_sep:pp_print_semicolon
440
           ~pp_eol:pp_print_semicolon pp_local)
441
        base_locals
442
        (* array mems *)
443
        (pp_print_list ~pp_open_box:pp_open_vbox0 ~pp_sep:pp_print_semicolon
444
           ~pp_eol:pp_print_semicolon pp_array_mem)
445
        array_mems
446
        (* locals initialization *)
447
        (pp_print_list ~pp_epilogue:pp_print_cut pp_init_mpfr_local)
448
        (mpfr_vars mpfr_locals)
449
        (* check assertions *)
450
        (pp_print_list pp_check)
451
        checks
452
        (* instrs *)
453
        (pp_print_list ~pp_open_box:pp_open_vbox0 ~pp_epilogue:pp_print_cut
454
           pp_instr)
455
        instrs
456
        (* locals clear *)
457
        (pp_print_list ~pp_epilogue:pp_print_cut pp_clear_mpfr_local)
458
        (mpfr_vars mpfr_locals) (* extra *)
459
        pp_extra ()
460

    
461
    let node_of_machine m =
462
      {
463
        top_decl_desc = Node m.mname;
464
        top_decl_loc = Location.dummy;
465
        top_decl_owner = "";
466
        top_decl_itf = false;
467
      }
468

    
469
    let print_stateless_code machines dependencies fmt m =
470
      let self = "__ERROR__" in
471
      if not (!Options.ansi && is_generic_node (node_of_machine m)) then
472
        (* C99 code *)
473
        pp_print_function
474
          ~pp_spec:(fun fmt () -> Mod.pp_step_spec fmt machines self self m)
475
          ~pp_prototype:Protos.print_stateless_prototype
476
          ~prototype:(m.mname.node_id, m.mstep.step_inputs, m.mstep.step_outputs)
477
          ~pp_local:(pp_c_decl_local_var m) ~base_locals:m.mstep.step_locals
478
          ~pp_init_mpfr_local:(pp_initialize m self (pp_c_var_read m))
479
          ~pp_clear_mpfr_local:(pp_clear m self (pp_c_var_read m))
480
          ~mpfr_locals:m.mstep.step_locals ~pp_check:(pp_c_check m self)
481
          ~checks:m.mstep.step_checks
482
          ~pp_instr:(pp_machine_instr dependencies m self self)
483
          ~instrs:m.mstep.step_instrs fmt
484
      else
485
        (* C90 code *)
486
        let gen_locals, base_locals =
487
          List.partition
488
            (fun v -> Types.is_generic_type v.var_type)
489
            m.mstep.step_locals
490
        in
491
        let gen_calls =
492
          List.map
493
            (fun e ->
494
              let id, _, _ = call_of_expr e in
495
              mk_call_var_decl e.expr_loc id)
496
            m.mname.node_gencalls
497
        in
498
        pp_print_function ~pp_prototype:Protos.print_stateless_prototype
499
          ~prototype:
500
            ( m.mname.node_id,
501
              m.mstep.step_inputs @ gen_locals @ gen_calls,
502
              m.mstep.step_outputs )
503
          ~pp_local:(pp_c_decl_local_var m) ~base_locals
504
          ~pp_init_mpfr_local:(pp_initialize m self (pp_c_var_read m))
505
          ~pp_clear_mpfr_local:(pp_clear m self (pp_c_var_read m))
506
          ~mpfr_locals:m.mstep.step_locals ~pp_check:(pp_c_check m self)
507
          ~checks:m.mstep.step_checks
508
          ~pp_instr:(pp_machine_instr dependencies m self self)
509
          ~instrs:m.mstep.step_instrs fmt
510

    
511
    let print_clear_reset_code dependencies self mem fmt m =
512
      pp_print_function
513
        ~pp_spec:(fun fmt () -> Mod.pp_clear_reset_spec fmt self mem m)
514
        ~pp_prototype:(Protos.print_clear_reset_prototype self mem)
515
        ~prototype:(m.mname.node_id, m.mstatic)
516
        ~pp_local:(pp_c_decl_local_var m) ~base_locals:(const_locals m)
517
        ~pp_instr:(pp_machine_instr dependencies m self mem)
518
        ~instrs:
519
          [
520
            mk_branch
521
              (mk_val ResetFlag Type_predef.type_bool)
522
              [ "true", mkinstr (MResetAssign false) :: m.minit ];
523
          ]
524
        fmt
525

    
526
    let print_set_reset_code dependencies self mem fmt m =
527
      pp_print_function
528
        ~pp_spec:(fun fmt () -> Mod.pp_set_reset_spec fmt self mem m)
529
        ~pp_prototype:(Protos.print_set_reset_prototype self mem)
530
        ~prototype:(m.mname.node_id, m.mstatic)
531
        ~pp_instr:(pp_machine_instr dependencies m self mem)
532
        ~instrs:[ mkinstr (MResetAssign true) ]
533
        fmt
534

    
535
    let print_init_code self fmt m =
536
      let minit =
537
        List.map
538
          (fun i ->
539
            match get_instr_desc i with MSetReset i -> i | _ -> assert false)
540
          m.minit
541
      in
542
      pp_print_function
543
        ~pp_prototype:(Protos.print_init_prototype self)
544
        ~prototype:(m.mname.node_id, m.mstatic)
545
        ~pp_array_mem:(pp_c_decl_array_mem self) ~array_mems:(array_mems m)
546
        ~pp_init_mpfr_local:(pp_initialize m self (pp_c_var_read m))
547
        ~mpfr_locals:m.mmemory
548
        ~pp_extra:(fun fmt () ->
549
          pp_print_list ~pp_open_box:pp_open_vbox0 ~pp_epilogue:pp_print_cut
550
            (pp_machine_init m self self)
551
            fmt minit)
552
        fmt
553

    
554
    let print_clear_code self fmt m =
555
      let minit =
556
        List.map
557
          (fun i ->
558
            match get_instr_desc i with MSetReset i -> i | _ -> assert false)
559
          m.minit
560
      in
561
      pp_print_function
562
        ~pp_prototype:(Protos.print_clear_prototype self)
563
        ~prototype:(m.mname.node_id, m.mstatic)
564
        ~pp_array_mem:(pp_c_decl_array_mem self) ~array_mems:(array_mems m)
565
        ~pp_clear_mpfr_local:(pp_clear m self (pp_c_var_read m))
566
        ~mpfr_locals:m.mmemory
567
        ~pp_extra:(fun fmt () ->
568
          pp_print_list ~pp_open_box:pp_open_vbox0 ~pp_epilogue:pp_print_cut
569
            (pp_machine_clear m self self)
570
            fmt minit)
571
        fmt
572

    
573
    let print_step_code machines dependencies self mem fmt m =
574
      if not (!Options.ansi && is_generic_node (node_of_machine m)) then
575
        (* C99 code *)
576
        pp_print_function
577
          ~pp_spec:(fun fmt () -> Mod.pp_step_spec fmt machines self mem m)
578
          ~pp_prototype:(Protos.print_step_prototype self mem)
579
          ~prototype:(m.mname.node_id, m.mstep.step_inputs, m.mstep.step_outputs)
580
          ~pp_local:(pp_c_decl_local_var m) ~base_locals:m.mstep.step_locals
581
          ~pp_array_mem:(pp_c_decl_array_mem self) ~array_mems:(array_mems m)
582
          ~pp_init_mpfr_local:(pp_initialize m self (pp_c_var_read m))
583
          ~pp_clear_mpfr_local:(pp_clear m self (pp_c_var_read m))
584
          ~mpfr_locals:m.mstep.step_locals ~pp_check:(pp_c_check m self)
585
          ~checks:m.mstep.step_checks
586
          ~pp_instr:(pp_machine_instr dependencies m self mem)
587
          ~instrs:m.mstep.step_instrs fmt
588
      else
589
        (* C90 code *)
590
        let gen_locals, base_locals =
591
          List.partition
592
            (fun v -> Types.is_generic_type v.var_type)
593
            m.mstep.step_locals
594
        in
595
        let gen_calls =
596
          List.map
597
            (fun e ->
598
              let id, _, _ = call_of_expr e in
599
              mk_call_var_decl e.expr_loc id)
600
            m.mname.node_gencalls
601
        in
602
        pp_print_function
603
          ~pp_spec:(fun fmt () -> Mod.pp_step_spec fmt machines self mem m)
604
          ~pp_prototype:(Protos.print_step_prototype self mem)
605
          ~prototype:
606
            ( m.mname.node_id,
607
              m.mstep.step_inputs @ gen_locals @ gen_calls,
608
              m.mstep.step_outputs )
609
          ~pp_local:(pp_c_decl_local_var m) ~base_locals
610
          ~pp_init_mpfr_local:(pp_initialize m self (pp_c_var_read m))
611
          ~pp_clear_mpfr_local:(pp_clear m self (pp_c_var_read m))
612
          ~mpfr_locals:m.mstep.step_locals ~pp_check:(pp_c_check m self)
613
          ~checks:m.mstep.step_checks
614
          ~pp_instr:(pp_machine_instr dependencies m self mem)
615
          ~instrs:m.mstep.step_instrs fmt
616

    
617
    (********************************************************************************************)
618
    (* MAIN C file Printing functions *)
619
    (********************************************************************************************)
620

    
621
    let pp_const_initialize m pp_var fmt const =
622
      let var =
623
        Machine_code_common.mk_val
624
          (Var (Corelang.var_decl_of_const const))
625
          const.const_type
626
      in
627
      let rec aux indices value fmt typ =
628
        if Types.is_array_type typ then
629
          let dim = Types.array_type_dimension typ in
630
          let szl = Utils.enumerate (Dimension.size_const dim) in
631
          let typ' = Types.array_element_type typ in
632
          let value =
633
            match value with Const_array ca -> List.nth ca | _ -> assert false
634
          in
635
          pp_print_list
636
            (fun fmt i -> aux (string_of_int i :: indices) (value i) fmt typ')
637
            fmt szl
638
        else
639
          let indices = List.rev indices in
640
          let pp_var_suffix fmt var =
641
            fprintf fmt "%a%a" (pp_c_val m "" pp_var) var pp_array_suffix
642
              indices
643
          in
644
          fprintf fmt "%a@,%a"
645
            (Mpfr.pp_inject_init pp_var_suffix)
646
            var
647
            (Mpfr.pp_inject_real pp_var_suffix pp_c_const)
648
            (var, value)
649
      in
650
      reset_loop_counter ();
651
      aux [] const.const_value fmt const.const_type
652

    
653
    let pp_const_clear pp_var fmt const =
654
      let m = Machine_code_common.empty_machine in
655
      let var = Corelang.var_decl_of_const const in
656
      let rec aux indices fmt typ =
657
        if Types.is_array_type typ then
658
          let dim = Types.array_type_dimension typ in
659
          let idx = mk_loop_var m () in
660
          fprintf fmt "@[<v 2>{@,int %s;@,for(%s=0;%s<%a;%s++)@,%a @]@,}" idx
661
            idx idx pp_c_dimension dim idx
662
            (aux (idx :: indices))
663
            (Types.array_element_type typ)
664
        else
665
          let indices = List.rev indices in
666
          let pp_var_suffix fmt var =
667
            fprintf fmt "%a%a" (pp_c_var m "" pp_var) var pp_array_suffix
668
              indices
669
          in
670
          Mpfr.pp_inject_clear pp_var_suffix fmt var
671
      in
672
      reset_loop_counter ();
673
      aux [] fmt var.var_type
674

    
675
    let print_import_init fmt dep =
676
      let baseNAME = file_to_module_name dep.name in
677
      fprintf fmt "%a();" pp_global_init_name baseNAME
678

    
679
    let print_import_clear fmt dep =
680
      let baseNAME = file_to_module_name dep.name in
681
      fprintf fmt "%a();" pp_global_clear_name baseNAME
682

    
683
    let print_global_init_code fmt (basename, prog, dependencies) =
684
      let baseNAME = file_to_module_name basename in
685
      let constants = List.map const_of_top (get_consts prog) in
686
      fprintf fmt
687
        "@[<v 2>%a {@,\
688
         static %s init = 0;@,\
689
         @[<v 2>if (!init) { @,\
690
         init = 1;%a%a@]@,\
691
         }@,\
692
         return;@]@,\
693
         }"
694
        pp_global_init_prototype baseNAME
695
        (pp_c_basic_type_desc Type_predef.type_bool)
696
        (* constants *)
697
        (pp_print_list ~pp_prologue:pp_print_cut
698
           (pp_const_initialize empty_machine (pp_c_var_read empty_machine)))
699
        (mpfr_consts constants)
700
        (* dependencies initialization *)
701
        (pp_print_list ~pp_prologue:pp_print_cut print_import_init)
702
        (List.filter (fun dep -> dep.local) dependencies)
703

    
704
    let print_global_clear_code fmt (basename, prog, dependencies) =
705
      let baseNAME = file_to_module_name basename in
706
      let constants = List.map const_of_top (get_consts prog) in
707
      fprintf fmt
708
        "@[<v 2>%a {@,\
709
         static %s clear = 0;@,\
710
         @[<v 2>if (!clear) { @,\
711
         clear = 1;%a%a@]@,\
712
         }@,\
713
         return;@]@,\
714
         }"
715
        pp_global_clear_prototype baseNAME
716
        (pp_c_basic_type_desc Type_predef.type_bool)
717
        (* constants *)
718
        (pp_print_list ~pp_prologue:pp_print_cut
719
           (pp_const_clear (pp_c_var_read empty_machine)))
720
        (mpfr_consts constants)
721
        (* dependencies initialization *)
722
        (pp_print_list ~pp_prologue:pp_print_cut print_import_clear)
723
        (List.filter (fun dep -> dep.local) dependencies)
724

    
725
    let print_alloc_function fmt m =
726
      if not !Options.static_mem then
727
        (* Alloc functions, only if non static mode *)
728
        fprintf fmt "@[<v 2>%a {@,%a%a@]@,}@,@[<v 2>%a {@,%a%a@]@,@,"
729
          pp_alloc_prototype
730
          (m.mname.node_id, m.mstatic)
731
          print_alloc_const m print_alloc_code m pp_dealloc_prototype
732
          m.mname.node_id print_alloc_const m print_dealloc_code m
733

    
734
    let print_mpfr_code self fmt m =
735
      if !Options.mpfr then
736
        fprintf fmt "@,@[<v>%a@,%a@]"
737
          (* Init function *)
738
          (print_init_code self)
739
          m
740
          (* Clear function *)
741
          (print_clear_code self)
742
          m
743

    
744
    (* TODO: ACSL - a contract machine shall not be directly printed in the C
745
       source - but a regular machine associated to a contract machine shall
746
       integrate the associated statements, updating its memories, at the end of
747
       the function body. - last one may print intermediate comment/acsl if/when
748
       they are present in the sequence of instruction *)
749
    let print_machine machines dependencies fmt m =
750
      if fst (get_stateless_status m) then
751
        (* Step function *)
752
        print_stateless_code machines dependencies fmt m
753
      else
754
        let self = mk_self m in
755
        let mem = mk_mem m in
756
        fprintf fmt "@[<v>%a%a@,@,%a@,@,%a%a@]" print_alloc_function m
757
          (* Reset functions *)
758
          (print_clear_reset_code dependencies self mem)
759
          m
760
          (print_set_reset_code dependencies self mem)
761
          m
762
          (* Step function *)
763
          (print_step_code machines dependencies self mem)
764
          m (print_mpfr_code self) m
765

    
766
    let print_import_standard source_fmt () =
767
      fprintf source_fmt "@[<v>#include <assert.h>@,%a%a%a@]"
768
        (if Machine_types.has_machine_type () then
769
         pp_print_endcut "#include <stdint.h>"
770
        else pp_print_nothing)
771
        ()
772
        (if not !Options.static_mem then pp_print_endcut "#include <stdlib.h>"
773
        else pp_print_nothing)
774
        ()
775
        (if !Options.mpfr then pp_print_endcut "#include <mpfr.h>"
776
        else pp_print_nothing)
777
        ()
778

    
779
    let print_extern_alloc_prototype fmt ind =
780
      let static = List.filter (fun v -> v.var_dec_const) ind.nodei_inputs in
781
      fprintf fmt "extern %a;@,extern %a;" pp_alloc_prototype
782
        (ind.nodei_id, static) pp_dealloc_prototype ind.nodei_id
783

    
784
    let print_lib_c source_fmt basename prog machines dependencies =
785
      fprintf source_fmt "@[<v>%a%a@,@,%a@,%a%a%a%a%a%a%a@]@."
786
        print_import_standard () pp_import_prototype
787
        {
788
          local = true;
789
          name = basename;
790
          content = [];
791
          is_stateful = true (* assuming it is stateful *);
792
        }
793
        (* Print the svn version number and the supported C standard (C90 or
794
           C99) *)
795
        pp_print_version ()
796
        (* Print dependencies *)
797
        (pp_print_list ~pp_open_box:pp_open_vbox0
798
           ~pp_prologue:(pp_print_endcut "/* Import dependencies */")
799
           pp_import_prototype ~pp_epilogue:pp_print_cutcut)
800
        dependencies
801
        (* Print consts *)
802
        (pp_print_list ~pp_open_box:pp_open_vbox0
803
           ~pp_prologue:(pp_print_endcut "/* Global constants (definitions) */")
804
           print_const_def ~pp_epilogue:pp_print_cutcut)
805
        (get_consts prog)
806
        (* MPFR *)
807
        (if !Options.mpfr then fun fmt () ->
808
         fprintf fmt
809
           "@[<v>/* Global constants initialization */@,\
810
            %a@,\
811
            @,\
812
            /* Global constants clearing */@,\
813
            %a@]@,\
814
            @,"
815
           print_global_init_code
816
           (basename, prog, dependencies)
817
           print_global_clear_code
818
           (basename, prog, dependencies)
819
        else pp_print_nothing)
820
        ()
821
        (if not !Options.static_mem then fun fmt () ->
822
         fprintf fmt "@[<v>%a%a@]@,@,"
823
           (pp_print_list ~pp_open_box:pp_open_vbox0 ~pp_epilogue:pp_print_cut
824
              ~pp_prologue:
825
                (pp_print_endcut "/* External allocation function prototypes */")
826
              (fun fmt dep ->
827
                pp_print_list ~pp_open_box:pp_open_vbox0
828
                  ~pp_epilogue:pp_print_cut print_extern_alloc_prototype fmt
829
                  (List.filter_map
830
                     (fun decl ->
831
                       match decl.top_decl_desc with
832
                       | ImportedNode ind when not ind.nodei_stateless ->
833
                         Some ind
834
                       | _ ->
835
                         None)
836
                     dep.content)))
837
           dependencies
838
           (pp_print_list ~pp_open_box:pp_open_vbox0
839
              ~pp_prologue:
840
                (pp_print_endcut "/* Node allocation function prototypes */")
841
              ~pp_sep:pp_print_cutcut (fun fmt m ->
842
                fprintf fmt "%a;@,%a;" pp_alloc_prototype
843
                  (m.mname.node_id, m.mstatic)
844
                  pp_dealloc_prototype m.mname.node_id))
845
           machines
846
        else pp_print_nothing)
847
        ()
848
        (* Print the struct definitions of all machines. *)
849
        (pp_print_list ~pp_open_box:pp_open_vbox0
850
           ~pp_prologue:(pp_print_endcut "/* Struct definitions */")
851
           ~pp_sep:pp_print_cutcut pp_machine_struct
852
           ~pp_epilogue:pp_print_cutcut)
853
        machines (* Print the spec predicates *) Mod.pp_predicates machines
854
        (* Print nodes one by one (in the previous order) *)
855
        (pp_print_list ~pp_open_box:pp_open_vbox0 ~pp_sep:pp_print_cutcut
856
           (print_machine machines dependencies))
857
        machines
858
  end
859

    
860
(* Local Variables: *)
861
(* compile-command:"make -C ../../.." *)
862
(* End: *)
(17-17/18)