Project

General

Profile

Download (39.4 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 Corelang
16
open Machine_code_types
17
open Machine_code_common
18
module Mpfr = Lustrec_mpfr
19

    
20
let pp_print_version fmt () =
21
  fprintf
22
    fmt
23
    "/* @[<v>C code generated by %s@,\
24
     Version number %s@,\
25
     Code is %s compliant@,\
26
     Using %s numbers */@,\
27
     @]"
28
    (Filename.basename Sys.executable_name)
29
    Version.number
30
    (if !Options.ansi then "ANSI C90" else "C99")
31
    (if !Options.mpfr then "MPFR multi-precision"
32
    else "(double) floating-point")
33

    
34
let protect_filename s = Str.global_replace (Str.regexp "\\.\\|\\ ") "_" s
35

    
36
let file_to_module_name basename =
37
  let baseNAME = Ocaml_utils.uppercase basename in
38
  let baseNAME = protect_filename baseNAME in
39
  baseNAME
40

    
41
let pp_ptr fmt = fprintf fmt "*%s"
42

    
43
let reset_label = "Reset"
44

    
45
let pp_label fmt = fprintf fmt "%s:"
46

    
47
let var_is name v = v.var_id = name
48

    
49
let mk_local n m =
50
  let used name =
51
    let open List in
52
    exists (var_is name) m.mstep.step_inputs
53
    || exists (var_is name) m.mstep.step_outputs
54
    || exists (var_is name) m.mstep.step_locals
55
    || exists (var_is name) m.mmemory
56
  in
57
  mk_new_name used n
58

    
59
(* Generation of a non-clashing name for the self memory variable (for step and
60
   reset functions) *)
61
let mk_self = mk_local "self"
62

    
63
let mk_mem = mk_local "mem"
64

    
65
let mk_mem_c = mk_local "mem_c"
66

    
67
let mk_mem_in = mk_local "mem_in"
68

    
69
let mk_mem_out = mk_local "mem_out"
70

    
71
let mk_mem_in_c = mk_local "mem_in_c"
72

    
73
let mk_mem_out_c = mk_local "mem_out_c"
74

    
75
let mk_mem_reset = mk_local "mem_reset"
76

    
77
(* Generation of a non-clashing name for the instance variable of static
78
   allocation macro *)
79
let mk_instance m =
80
  let used name =
81
    let open List in
82
    exists (var_is name) m.mstep.step_inputs || exists (var_is name) m.mmemory
83
  in
84
  mk_new_name used "inst"
85

    
86
(* Generation of a non-clashing name for the attribute variable of static
87
   allocation macro *)
88
let mk_attribute m =
89
  let used name =
90
    let open List in
91
    exists (var_is name) m.mstep.step_inputs || exists (var_is name) m.mmemory
92
  in
93
  mk_new_name used "attr"
94

    
95
let mk_call_var_decl loc id =
96
  {
97
    var_id = id;
98
    var_orig = false;
99
    var_dec_type = mktyp Location.dummy Tydec_any;
100
    var_dec_clock = mkclock Location.dummy Ckdec_any;
101
    var_dec_const = false;
102
    var_dec_value = None;
103
    var_parent_nodeid = None;
104
    var_type = Type_predef.type_arrow (Types.new_var ()) (Types.new_var ());
105
    var_clock = Clocks.new_var true;
106
    var_loc = loc;
107
    var_is_contract = false;
108
  }
109

    
110
(* counter for loop variable creation *)
111
let loop_cpt = ref (-1)
112

    
113
let reset_loop_counter () = loop_cpt := -1
114

    
115
let mk_loop_var m () =
116
  let vars =
117
    m.mstep.step_inputs @ m.mstep.step_outputs @ m.mstep.step_locals @ m.mmemory
118
  in
119
  let rec aux () =
120
    incr loop_cpt;
121
    let s = sprintf "__%s_%d" "i" !loop_cpt in
122
    if List.exists (var_is s) vars then aux () else s
123
  in
124
  aux ()
125

    
126
(* let addr_cpt = ref (-1)
127

    
128
   let reset_addr_counter () = addr_cpt := -1
129

    
130
   let mk_addr_var m var = let vars = m.mmemory in let rec aux () = incr
131
   addr_cpt; let s = Printf.sprintf "%s_%s_%d" var "addr" !addr_cpt in if
132
   List.exists (fun v -> v.var_id = s) vars then aux () else s in aux () *)
133
let pp_global_init_name fmt id = fprintf fmt "%s_INIT" id
134

    
135
let pp_global_clear_name fmt id = fprintf fmt "%s_CLEAR" id
136

    
137
let pp_machine_memtype_name ?(ghost = false) fmt id =
138
  fprintf fmt "struct %s_mem%s" id (if ghost then "_ghost" else "")
139

    
140
let pp_machine_decl ?(ghost = false) pp_var fmt (id, var) =
141
  fprintf fmt "%a %a" (pp_machine_memtype_name ~ghost) id pp_var var
142

    
143
let pp_machine_decl' ?(ghost = false) fmt =
144
  pp_machine_decl ~ghost pp_print_string fmt
145

    
146
let pp_machine_regtype_name fmt id = fprintf fmt "struct %s_reg" id
147

    
148
let pp_machine_alloc_name fmt id = fprintf fmt "%s_alloc" id
149

    
150
let pp_machine_dealloc_name fmt id = fprintf fmt "%s_dealloc" id
151

    
152
let pp_machine_static_declare_name ?(ghost = false) fmt id =
153
  fprintf fmt "%s_DECLARE%s" id (if ghost then "_GHOST" else "")
154

    
155
let pp_machine_static_link_name ?(ghost = false) fmt id =
156
  fprintf fmt "%s_LINK%s" id (if ghost then "_GHOST" else "")
157

    
158
let pp_machine_static_alloc_name ?(ghost = false) fmt id =
159
  fprintf fmt "%s_ALLOC%s" id (if ghost then "_GHOST" else "")
160

    
161
let pp_machine_set_reset_name fmt id = fprintf fmt "%s_set_reset" id
162

    
163
let pp_machine_clear_reset_name fmt id = fprintf fmt "%s_clear_reset" id
164

    
165
let pp_machine_init_name fmt id = fprintf fmt "%s_init" id
166

    
167
let pp_machine_clear_name fmt id = fprintf fmt "%s_clear" id
168

    
169
let pp_machine_step_name fmt id = fprintf fmt "%s_step" id
170

    
171
let pp_mod pp_val v1 v2 fmt =
172
  if !Options.integer_div_euclidean then
173
    (* (a mod_C b) + (a mod_C b < 0 ? abs(b) : 0) *)
174
    fprintf
175
      fmt
176
      "((%a %% %a) + ((%a %% %a) < 0?(abs(%a)):0))"
177
      pp_val
178
      v1
179
      pp_val
180
      v2
181
      pp_val
182
      v1
183
      pp_val
184
      v2
185
      pp_val
186
      v2
187
  else
188
    (* Regular behavior: printing a % *)
189
    fprintf fmt "(%a %% %a)" pp_val v1 pp_val v2
190

    
191
let pp_div pp_val v1 v2 fmt =
192
  if !Options.integer_div_euclidean then
193
    (* (a - ((a mod_C b) + (a mod_C b < 0 ? abs(b) : 0))) div_C b *)
194
    fprintf fmt "(%a - %t) / %a" pp_val v1 (pp_mod pp_val v1 v2) pp_val v2
195
  else
196
    (* Regular behavior: printing a / *)
197
    fprintf fmt "(%a / %a)" pp_val v1 pp_val v2
198

    
199
let pp_basic_lib_fun is_int i pp_val fmt vl =
200
  match i, vl with
201
  (* | "ite", [v1; v2; v3] -> fprintf fmt "(%a?(%a):(%a))" pp_val v1 pp_val v2
202
     pp_val v3 *)
203
  | "uminus", [ v ] ->
204
    fprintf fmt "(- %a)" pp_val v
205
  | "not", [ v ] ->
206
    fprintf fmt "(!%a)" pp_val v
207
  | "impl", [ v1; v2 ] ->
208
    fprintf fmt "(!%a || %a)" pp_val v1 pp_val v2
209
  | "=", [ v1; v2 ] ->
210
    fprintf fmt "(%a == %a)" pp_val v1 pp_val v2
211
  | "mod", [ v1; v2 ] ->
212
    if is_int then pp_mod pp_val v1 v2 fmt
213
    else fprintf fmt "(%a %% %a)" pp_val v1 pp_val v2
214
  | "equi", [ v1; v2 ] ->
215
    fprintf fmt "(!%a == !%a)" pp_val v1 pp_val v2
216
  | "xor", [ v1; v2 ] ->
217
    fprintf fmt "(!%a != !%a)" pp_val v1 pp_val v2
218
  | "/", [ v1; v2 ] ->
219
    if is_int then pp_div pp_val v1 v2 fmt
220
    else fprintf fmt "(%a / %a)" pp_val v1 pp_val v2
221
  | _, [ v1; v2 ] ->
222
    fprintf fmt "(%a %s %a)" pp_val v1 i pp_val v2
223
  | _ ->
224
    (* TODO: raise proper error *)
225
    eprintf "internal error: C_backend_common.pp_basic_lib_fun %s@." i;
226
    assert false
227

    
228
let rec pp_c_dimension fmt dim =
229
  let open Dimension in
230
  match dim.dim_desc with
231
  | Dident id ->
232
    fprintf fmt "%s" id
233
  | Dint i ->
234
    fprintf fmt "%d" i
235
  | Dbool b ->
236
    fprintf fmt "%B" b
237
  | Dite (i, t, e) ->
238
    fprintf
239
      fmt
240
      "((%a)?%a:%a)"
241
      pp_c_dimension
242
      i
243
      pp_c_dimension
244
      t
245
      pp_c_dimension
246
      e
247
  | Dappl (f, args) ->
248
    fprintf
249
      fmt
250
      "%a"
251
      (pp_basic_lib_fun (Basic_library.is_numeric_operator f) f pp_c_dimension)
252
      args
253
  | Dlink dim' ->
254
    fprintf fmt "%a" pp_c_dimension dim'
255
  | Dvar ->
256
    fprintf fmt "_%s" (Utils.name_of_dimension dim.dim_id)
257
  | Dunivar ->
258
    fprintf fmt "'%s" (Utils.name_of_dimension dim.dim_id)
259

    
260
let is_basic_c_type t =
261
  Types.(is_int_type t || is_real_type t || is_bool_type t)
262

    
263
let pp_c_basic_type_desc t_desc =
264
  if Types.is_bool_type t_desc then if !Options.cpp then "bool" else "_Bool"
265
  else if Types.is_int_type t_desc then !Options.int_type
266
  else if Types.is_real_type t_desc then
267
    if !Options.mpfr then Mpfr.mpfr_t else !Options.real_type
268
  else assert false
269
(* Not a basic C type. Do not handle arrays or pointers *)
270

    
271
let pp_basic_c_type ?(pp_c_basic_type_desc = pp_c_basic_type_desc) ?var_opt fmt
272
    t =
273
  match var_opt with
274
  | Some v when Machine_types.is_exportable v ->
275
    Machine_types.pp_c_var_type fmt v
276
  | _ ->
277
    fprintf fmt "%s" (pp_c_basic_type_desc t)
278

    
279
let pp_c_type ?(var_is_contract = false) ?pp_c_basic_type_desc ?var_opt var_id
280
    fmt t =
281
  let rec aux t pp_suffix =
282
    if is_basic_c_type t then
283
      fprintf
284
        fmt
285
        "%a %s%s%a"
286
        (pp_basic_c_type ?pp_c_basic_type_desc ?var_opt)
287
        t
288
        (if var_is_contract then "\\ghost " else "")
289
        var_id
290
        pp_suffix
291
        ()
292
    else
293
      let open Types in
294
      match (repr t).tdesc with
295
      | Tclock t' ->
296
        aux t' pp_suffix
297
      | Tarray (d, t') ->
298
        let pp_suffix' fmt () =
299
          fprintf fmt "%a[%a]" pp_suffix () pp_c_dimension d
300
        in
301
        aux t' pp_suffix'
302
      | Tstatic (_, t') ->
303
        fprintf fmt "const ";
304
        aux t' pp_suffix
305
      | Tconst ty ->
306
        fprintf fmt "%s %s" ty var_id
307
      | Tarrow (_, _) ->
308
        fprintf fmt "void (*%s)()" var_id
309
      | _ ->
310
        (* TODO: raise proper error *)
311
        eprintf "internal error: C_backend_common.pp_c_type %a@." pp t;
312
        assert false
313
  in
314
  aux t (fun _ () -> ())
315

    
316
(* let rec pp_c_initialize fmt t = match (Types.repr t).Types.tdesc with |
317
   Types.Tint -> pp_print_string fmt "0" | Types.Tclock t' -> pp_c_initialize
318
   fmt t' | Types.Tbool -> pp_print_string fmt "0" | Types.Treal when not
319
   !Options.mpfr -> pp_print_string fmt "0." | Types.Tarray (d, t') when
320
   Dimension.is_dimension_const d -> fprintf fmt "{%a}" (Utils.fprintf_list
321
   ~sep:"," (fun fmt _ -> pp_c_initialize fmt t')) (Utils.duplicate 0
322
   (Dimension.size_const_dimension d)) | _ -> assert false *)
323
let pp_c_tag fmt t =
324
  pp_print_string
325
    fmt
326
    (if t = tag_true then "1" else if t = tag_false then "0" else t)
327

    
328
(* Prints a constant value *)
329
let rec pp_c_const fmt c =
330
  match c with
331
  | Const_int i ->
332
    pp_print_int fmt i
333
  | Const_real r ->
334
    Real.pp fmt r
335
  (* | Const_float r -> pp_print_float fmt r *)
336
  | Const_tag t ->
337
    pp_c_tag fmt t
338
  | Const_array ca ->
339
    pp_print_braced pp_c_const fmt ca
340
  | Const_struct fl ->
341
    pp_print_braced (fun fmt (_, c) -> pp_c_const fmt c) fmt fl
342
  | Const_string _ | Const_modeid _ ->
343
    assert false
344
(* string occurs in annotations not in C *)
345

    
346
let reset_flag_name = "_reset"
347

    
348
let pp_reset_flag ?(indirect = true) pp_stru fmt stru =
349
  fprintf
350
    fmt
351
    "%a%s%s"
352
    pp_stru
353
    stru
354
    (if indirect then "->" else ".")
355
    reset_flag_name
356

    
357
let pp_reset_flag' ?indirect fmt = pp_reset_flag ?indirect pp_print_string fmt
358

    
359
let pp_reset_assign self fmt b =
360
  fprintf
361
    fmt
362
    "%a = %i;"
363
    (pp_reset_flag' ~indirect:true)
364
    self
365
    (if b then 1 else 0)
366

    
367
(* Prints a value expression [v], with internal function calls only. [pp_var] is
368
   a printer for variables (typically [pp_c_var_read]), but an offset suffix may
369
   be added for array variables *)
370
let rec pp_c_val m self pp_var fmt v =
371
  let pp_c_val = pp_c_val m self pp_var in
372
  match v.value_desc with
373
  | Cst c ->
374
    pp_c_const fmt c
375
  | Array vl ->
376
    pp_print_braced pp_c_val fmt vl
377
  | Access (t, i) ->
378
    fprintf fmt "%a[%a]" pp_c_val t pp_c_val i
379
  | Power (v, _) ->
380
    (* TODO: raise proper error *)
381
    eprintf
382
      "internal error: C_backend_common.pp_c_val %a@."
383
      (Machine_code_common.pp_val m)
384
      v;
385
    assert false
386
  | Var v ->
387
    if Machine_code_common.is_memory m v then
388
      (* array memory vars are represented by an indirection to a local var
389
       *  with the right type, in order to avoid casting everywhere. *)
390
      if
391
        Types.is_array_type v.var_type
392
        && not (Types.is_real_type v.var_type && !Options.mpfr)
393
      then fprintf fmt "%a" pp_var v
394
      else fprintf fmt "%s->_reg.%a" self pp_var v
395
    else pp_var fmt v
396
  | Fun (n, vl) ->
397
    pp_basic_lib_fun (Types.is_int_type v.value_type) n pp_c_val fmt vl
398
  | ResetFlag ->
399
    pp_reset_flag' fmt self
400

    
401
(* Access to the value of a variable: - if it's not a scalar output, then its
402
   name is enough - otherwise, dereference it (it has been declared as a
403
   pointer, despite its scalar Lustre type) - moreover, dereference memory array
404
   variables. *)
405
let pp_c_var_read ?(test_output = true) m fmt id =
406
  (* mpfr_t is a static array, not treated as general arrays *)
407
  if Types.is_address_type id.var_type then
408
    if
409
      Machine_code_common.is_memory m id
410
      && not (Types.is_real_type id.var_type && !Options.mpfr)
411
    then fprintf fmt "(*%s)" id.var_id
412
    else fprintf fmt "%s" id.var_id
413
  else if test_output && Machine_code_common.is_output m id then
414
    fprintf fmt "*%s" id.var_id
415
  else fprintf fmt "%s" id.var_id
416

    
417
(* Addressable value of a variable, the one that is passed around in calls: - if
418
   it's not a scalar non-output, then its name is enough - otherwise, reference
419
   it (it must be passed as a pointer, despite its scalar Lustre type) *)
420
let pp_c_var_write m fmt id =
421
  if Types.is_address_type id.var_type then fprintf fmt "%s" id.var_id
422
  else if Machine_code_common.is_output m id then fprintf fmt "%s" id.var_id
423
  else fprintf fmt "&%s" id.var_id
424

    
425
(* Declaration of an input variable: - if its type is array/matrix/etc, then
426
   declare it as a mere pointer, in order to cope with unknown/parametric array
427
   dimensions, as it is the case for generics *)
428
let pp_c_decl_input_var fmt id =
429
  if !Options.ansi && Types.is_address_type id.var_type then
430
    pp_c_type
431
      ~var_opt:id
432
      (sprintf "(*%s)" id.var_id)
433
      fmt
434
      (Types.array_base_type id.var_type)
435
  else pp_c_type ~var_opt:id id.var_id fmt id.var_type
436

    
437
(* Declaration of an output variable: - if its type is scalar, then pass its
438
   address - if its type is array/matrix/struct/etc, then declare it as a mere
439
   pointer, in order to cope with unknown/parametric array dimensions, as it is
440
   the case for generics *)
441
let pp_c_decl_output_var fmt id =
442
  if (not !Options.ansi) && Types.is_address_type id.var_type then
443
    pp_c_type
444
      ~var_is_contract:id.var_is_contract
445
      ~var_opt:id
446
      id.var_id
447
      fmt
448
      id.var_type
449
  else
450
    pp_c_type
451
      ~var_is_contract:id.var_is_contract
452
      ~var_opt:id
453
      (sprintf "(*%s)" id.var_id)
454
      fmt
455
      (Types.array_base_type id.var_type)
456

    
457
(* Declaration of a local/mem variable: - if it's an array/matrix/etc, its
458
   size(s) should be known in order to statically allocate memory, so we print
459
   the full type *)
460
let pp_c_decl_local_var ?pp_c_basic_type_desc m fmt id =
461
  if id.var_dec_const then
462
    fprintf
463
      fmt
464
      "%a = %a"
465
      (pp_c_type ?pp_c_basic_type_desc ~var_opt:id id.var_id)
466
      id.var_type
467
      (pp_c_val m "" (pp_c_var_read m))
468
      (Machine_code_common.get_const_assign m id)
469
  else
470
    fprintf
471
      fmt
472
      "%a"
473
      (pp_c_type ?pp_c_basic_type_desc ~var_opt:id id.var_id)
474
      id.var_type
475

    
476
(* Declaration of a struct variable: - if it's an array/matrix/etc, we declare
477
   it as a pointer *)
478
let pp_c_decl_struct_var fmt id =
479
  if Types.is_array_type id.var_type then
480
    pp_c_type
481
      (sprintf "(*%s)" id.var_id)
482
      fmt
483
      (Types.array_base_type id.var_type)
484
  else pp_c_type id.var_id fmt id.var_type
485

    
486
let pp_c_decl_instance_var ?(ghost = false) fmt (name, (node, _)) =
487
  fprintf
488
    fmt
489
    "%a %s%s"
490
    (pp_machine_memtype_name ~ghost)
491
    (node_name node)
492
    (if ghost then "" else "*")
493
    name
494

    
495
(* let pp_c_checks self fmt m =
496
 *   pp_print_list
497
 *     (fun fmt (loc, check) ->
498
 *        fprintf fmt
499
 *          "@[<v>%a@,assert (%a);@]"
500
 *          Location.pp_c_loc loc
501
 *          (pp_c_val m self (pp_c_var_read m)) check)
502
 *     fmt
503
 *     m.mstep.step_checks *)
504

    
505
let has_c_prototype funname dependencies =
506
  (* We select the last imported node with the name funname. The order of
507
     evaluation of dependencies should be compatible with overloading. (Not
508
     checked yet) *)
509
  let imported_node_opt =
510
    List.fold_left
511
      (fun res dep ->
512
        match res with
513
        | Some _ ->
514
          res
515
        | None ->
516
          let decls = dep.content in
517
          let matched t =
518
            match t.top_decl_desc with
519
            | ImportedNode nd ->
520
              nd.nodei_id = funname
521
            | _ ->
522
              false
523
          in
524
          if List.exists matched decls then
525
            match (List.find matched decls).top_decl_desc with
526
            | ImportedNode nd ->
527
              Some nd
528
            | _ ->
529
              assert false
530
          else None)
531
      None
532
      dependencies
533
  in
534
  match imported_node_opt with
535
  | None ->
536
    false
537
  | Some nd -> (
538
    match nd.nodei_prototype with Some "C" -> true | _ -> false)
539

    
540
(* Computes the depth to which multi-dimension array assignments should be
541
   expanded. It equals the maximum number of nested static array constructions
542
   accessible from root [v]. *)
543
let rec expansion_depth v =
544
  match v.value_desc with
545
  | Cst cst ->
546
    expansion_depth_cst cst
547
  | Var _ ->
548
    0
549
  | Fun (_, vl) ->
550
    List.fold_right (fun v -> max (expansion_depth v)) vl 0
551
  | Array vl ->
552
    1 + List.fold_right (fun v -> max (expansion_depth v)) vl 0
553
  | Access (v, _) ->
554
    max 0 (expansion_depth v - 1)
555
  | Power _ ->
556
    0 (*1 + expansion_depth v*)
557
  | ResetFlag ->
558
    0
559

    
560
and expansion_depth_cst c =
561
  match c with
562
  | Const_array cl ->
563
    1 + List.fold_right (fun c -> max (expansion_depth_cst c)) cl 0
564
  | _ ->
565
    0
566

    
567
type loop_index = LVar of ident | LInt of int ref | LAcc of value_t
568

    
569
(* let rec value_offsets v offsets = match v, offsets with | _ , [] -> v | Power
570
   (v, n) , _ :: q -> value_offsets v q | Array vl , LInt r :: q ->
571
   value_offsets (List.nth vl !r) q | Cst (Const_array cl) , LInt r :: q ->
572
   value_offsets (Cst (List.nth cl !r)) q | Fun (f, vl) , _ -> Fun (f, List.map
573
   (fun v -> value_offsets v offsets) vl) | _ , LInt r :: q -> value_offsets
574
   (Access (v, Cst (Const_int !r))) q | _ , LVar i :: q -> value_offsets (Access
575
   (v, Var i)) q *)
576
(* Computes the list of nested loop variables together with their dimension
577
   bounds.
578
 *  - LInt r stands for loop expansion (no loop variable, but int loop
579
      index)
580
 *  - LVar v stands for loop variable v *)
581
let rec mk_loop_variables m ty depth =
582
  match (Types.repr ty).Types.tdesc, depth with
583
  | Types.Tarray (d, ty'), 0 ->
584
    let v = mk_loop_var m () in
585
    (d, LVar v) :: mk_loop_variables m ty' 0
586
  | Types.Tarray (d, ty'), _ ->
587
    let r = ref (-1) in
588
    (d, LInt r) :: mk_loop_variables m ty' (depth - 1)
589
  | _, 0 ->
590
    []
591
  | _ ->
592
    assert false
593

    
594
let reorder_loop_variables loop_vars =
595
  let int_loops, var_loops =
596
    List.partition (function _, LInt _ -> true | _ -> false) loop_vars
597
  in
598
  var_loops @ int_loops
599

    
600
(* Prints a one loop variable suffix for arrays *)
601
let pp_loop_var pp_val fmt lv =
602
  match snd lv with
603
  | LVar v ->
604
    fprintf fmt "[%s]" v
605
  | LInt r ->
606
    fprintf fmt "[%d]" !r
607
  | LAcc i ->
608
    fprintf fmt "[%a]" pp_val i
609

    
610
(* Prints a suffix of loop variables for arrays *)
611
let pp_suffix pp_val =
612
  pp_print_list ~pp_sep:pp_print_nothing (pp_loop_var pp_val)
613

    
614
let rec is_const_index v =
615
  match v.value_desc with
616
  | Cst (Const_int _) ->
617
    true
618
  | Fun (_, vl) ->
619
    List.for_all is_const_index vl
620
  | _ ->
621
    false
622

    
623
(* Prints a value expression [v], with internal function calls only. [pp_var] is
624
   a printer for variables (typically [pp_c_var_read]), but an offset suffix may
625
   be added for array variables *)
626
(* Prints a constant value before a suffix (needs casting) *)
627
let rec pp_c_const_suffix var_type fmt c =
628
  match c with
629
  | Const_int i ->
630
    pp_print_int fmt i
631
  | Const_real r ->
632
    Real.pp fmt r
633
  | Const_tag t ->
634
    pp_c_tag fmt t
635
  | Const_array ca ->
636
    let var_type = Types.array_element_type var_type in
637
    fprintf
638
      fmt
639
      "(%a[])%a"
640
      (pp_c_type "")
641
      var_type
642
      (pp_print_braced (pp_c_const_suffix var_type))
643
      ca
644
  | Const_struct fl ->
645
    pp_print_braced
646
      (fun fmt (f, c) ->
647
        (pp_c_const_suffix (Types.struct_field_type var_type f)) fmt c)
648
      fmt
649
      fl
650
  | Const_string _ | Const_modeid _ ->
651
    assert false
652
(* string occurs in annotations not in C *)
653

    
654
(* Prints a [value] of type [var_type] indexed by the suffix list [loop_vars] *)
655
let rec pp_value_suffix ?(indirect = true) m self var_type loop_vars pp_var fmt
656
    value =
657
  (*eprintf "pp_value_suffix: %a %a %a@." Types.pp var_type Machine_code.pp_val
658
    value pp_suffix loop_vars;*)
659
  let pp_suffix =
660
    pp_suffix (pp_value_suffix ~indirect m self var_type [] pp_var)
661
  in
662
  match loop_vars, value.value_desc with
663
  | (x, LAcc i) :: q, _ when is_const_index i ->
664
    let r = ref (Dimension.size_const (dimension_of_value i)) in
665
    pp_value_suffix
666
      ~indirect
667
      m
668
      self
669
      var_type
670
      ((x, LInt r) :: q)
671
      pp_var
672
      fmt
673
      value
674
  | (_, LInt r) :: q, Cst (Const_array cl) ->
675
    let var_type = Types.array_element_type var_type in
676
    pp_value_suffix
677
      ~indirect
678
      m
679
      self
680
      var_type
681
      q
682
      pp_var
683
      fmt
684
      (mk_val (Cst (List.nth cl !r)) Type_predef.type_int)
685
  | (_, LInt r) :: q, Array vl ->
686
    let var_type = Types.array_element_type var_type in
687
    pp_value_suffix ~indirect m self var_type q pp_var fmt (List.nth vl !r)
688
  | loop_var :: q, Array vl ->
689
    let var_type = Types.array_element_type var_type in
690
    fprintf
691
      fmt
692
      "(%a[])%a%a"
693
      (pp_c_type "")
694
      var_type
695
      (pp_print_braced (pp_value_suffix ~indirect m self var_type q pp_var))
696
      vl
697
      pp_suffix
698
      [ loop_var ]
699
  | [], Array vl ->
700
    let var_type = Types.array_element_type var_type in
701
    fprintf
702
      fmt
703
      "(%a[])%a"
704
      (pp_c_type "")
705
      var_type
706
      (pp_print_braced (pp_value_suffix ~indirect m self var_type [] pp_var))
707
      vl
708
  | _ :: q, Power (v, _) ->
709
    pp_value_suffix ~indirect m self var_type q pp_var fmt v
710
  | _, Fun (n, vl) ->
711
    pp_basic_lib_fun
712
      (Types.is_int_type value.value_type)
713
      n
714
      (pp_value_suffix ~indirect m self var_type loop_vars pp_var)
715
      fmt
716
      vl
717
  | _, Access (v, i) ->
718
    let var_type = Type_predef.type_array (Dimension.mkdim_var ()) var_type in
719
    pp_value_suffix
720
      m
721
      self
722
      var_type
723
      ((Dimension.mkdim_var (), LAcc i) :: loop_vars)
724
      pp_var
725
      fmt
726
      v
727
  | _, Var v ->
728
    if is_memory m v then
729
      (* array memory vars are represented by an indirection to a local var with
730
         the right type, in order to avoid casting everywhere. *)
731
      if Types.is_array_type v.var_type then
732
        fprintf fmt "%a%a" pp_var v pp_suffix loop_vars
733
      else
734
        fprintf
735
          fmt
736
          "%s%s_reg.%a%a"
737
          self
738
          (if indirect then "->" else ".")
739
          pp_var
740
          v
741
          pp_suffix
742
          loop_vars
743
    else if is_reset_flag v then
744
      fprintf
745
        fmt
746
        "%s%s%a%a"
747
        self
748
        (if indirect then "->" else ".")
749
        pp_var
750
        v
751
        pp_suffix
752
        loop_vars
753
    else fprintf fmt "%a%a" pp_var v pp_suffix loop_vars
754
  | _, Cst cst ->
755
    pp_c_const_suffix var_type fmt cst
756
  | _, ResetFlag ->
757
    pp_reset_flag' fmt self
758
  | _, _ ->
759
    eprintf
760
      "internal error: C_backend_common.pp_value_suffix %a %a %a@."
761
      Types.pp
762
      var_type
763
      (pp_val m)
764
      value
765
      pp_suffix
766
      loop_vars;
767
    assert false
768

    
769
(********************************************************************************************)
770
(* Struct Printing functions *)
771
(********************************************************************************************)
772

    
773
(* let pp_registers_struct fmt m =
774
 *   pp_print_braced
775
 *     ~pp_prologue:(fun fmt () ->
776
 *         fprintf fmt "@[%a " pp_machine_regtype_name m.mname.node_id)
777
 *     ~pp_open_box:pp_open_vbox0
778
 *     ~pp_sep:pp_print_semicolon
779
 *     ~pp_eol:pp_print_semicolon
780
 *     ~pp_epilogue:(fun fmt () -> pp_print_string fmt "@] _reg;")
781
 *     pp_c_decl_struct_var
782
 *     fmt m.mmemory *)
783

    
784
let pp_machine_struct ?(ghost = false) fmt m =
785
  if not (fst (Machine_code_common.get_stateless_status m)) then
786
    (* Define struct *)
787
    fprintf
788
      fmt
789
      "@[<v 2>%a {@,_Bool _reset;%a%a@]@,};"
790
      (pp_machine_memtype_name ~ghost)
791
      m.mname.node_id
792
      (if ghost && not m.mis_contract then
793
       fun fmt -> function
794
         | [] ->
795
           pp_print_nothing fmt ()
796
         | _ ->
797
           fprintf fmt "@,%a _reg;" pp_machine_regtype_name m.mname.node_id
798
      else
799
        pp_print_list
800
          ~pp_open_box:pp_open_vbox0
801
          ~pp_prologue:(fun fmt () ->
802
            fprintf fmt "@,@[%a {" pp_machine_regtype_name m.mname.node_id)
803
          ~pp_sep:pp_print_semicolon
804
          ~pp_eol:pp_print_semicolon'
805
          ~pp_epilogue:(fun fmt () -> fprintf fmt "}@] _reg;")
806
          pp_c_decl_struct_var)
807
      m.mmemory
808
      (pp_print_list
809
         ~pp_open_box:pp_open_vbox0
810
         ~pp_prologue:pp_print_cut
811
         ~pp_sep:pp_print_semicolon
812
         ~pp_eol:pp_print_semicolon'
813
         (pp_c_decl_instance_var ~ghost))
814
      m.minstances
815

    
816
(********************************************************************************************)
817
(* Prototype Printing functions *)
818
(********************************************************************************************)
819

    
820
let pp_global_init_prototype fmt baseNAME =
821
  fprintf fmt "void %a ()" pp_global_init_name baseNAME
822

    
823
let pp_global_clear_prototype fmt baseNAME =
824
  fprintf fmt "void %a ()" pp_global_clear_name baseNAME
825

    
826
let pp_alloc_prototype fmt (name, static) =
827
  fprintf
828
    fmt
829
    "%a * %a %a"
830
    (pp_machine_memtype_name ~ghost:false)
831
    name
832
    pp_machine_alloc_name
833
    name
834
    (pp_print_parenthesized pp_c_decl_input_var)
835
    static
836

    
837
let pp_dealloc_prototype fmt name =
838
  fprintf
839
    fmt
840
    "void %a (%a * _alloc)"
841
    pp_machine_dealloc_name
842
    name
843
    (pp_machine_memtype_name ~ghost:false)
844
    name
845

    
846
module type MODIFIERS_GHOST_PROTO = sig
847
  val pp_ghost_parameters :
848
    ?cut:bool ->
849
    formatter ->
850
    (string * (formatter -> string -> unit)) list ->
851
    unit
852
end
853

    
854
module EmptyGhostProto : MODIFIERS_GHOST_PROTO = struct
855
  let pp_ghost_parameters ?cut _ _ = ignore cut
856
end
857

    
858
module Protos (Mod : MODIFIERS_GHOST_PROTO) = struct
859
  let pp_mem_ghost name fmt mem =
860
    pp_machine_decl
861
      ~ghost:true
862
      (fun fmt mem -> fprintf fmt "\\ghost %a" pp_ptr mem)
863
      fmt
864
      (name, mem)
865

    
866
  let pp_clear_reset_prototype self mem fmt (name, static) =
867
    fprintf
868
      fmt
869
      "@[<v>void %a (%a%a *%s)%a@]"
870
      pp_machine_clear_reset_name
871
      name
872
      (pp_comma_list ~pp_eol:pp_print_comma pp_c_decl_input_var)
873
      static
874
      (pp_machine_memtype_name ~ghost:false)
875
      name
876
      self
877
      (Mod.pp_ghost_parameters ~cut:true)
878
      [ mem, pp_mem_ghost name ]
879

    
880
  let pp_set_reset_prototype self mem fmt (name, static) =
881
    fprintf
882
      fmt
883
      "@[<v>void %a (%a%a *%s)%a@]"
884
      pp_machine_set_reset_name
885
      name
886
      (pp_comma_list ~pp_eol:pp_print_comma pp_c_decl_input_var)
887
      static
888
      (pp_machine_memtype_name ~ghost:false)
889
      name
890
      self
891
      (Mod.pp_ghost_parameters ~cut:true)
892
      [ mem, pp_mem_ghost name ]
893

    
894
  let pp_step_prototype self mem fmt (name, inputs, outputs) =
895
    fprintf
896
      fmt
897
      "@[<v>void %a (@[<v>%a%a%a *%s@])%a@]"
898
      pp_machine_step_name
899
      name
900
      (pp_comma_list pp_c_decl_input_var)
901
      inputs
902
      (pp_comma_list
903
         ~pp_prologue:pp_print_comma
904
         ~pp_eol:pp_print_comma
905
         ~pp_epilogue:pp_print_cut
906
         pp_c_decl_output_var)
907
      outputs
908
      (pp_machine_memtype_name ~ghost:false)
909
      name
910
      self
911
      (Mod.pp_ghost_parameters ~cut:true)
912
      [ mem, pp_mem_ghost name ]
913

    
914
  let pp_init_prototype self fmt (name, static) =
915
    fprintf
916
      fmt
917
      "void %a (%a%a *%s)"
918
      pp_machine_init_name
919
      name
920
      (pp_comma_list ~pp_eol:pp_print_comma pp_c_decl_input_var)
921
      static
922
      (pp_machine_memtype_name ~ghost:false)
923
      name
924
      self
925

    
926
  let pp_clear_prototype self fmt (name, static) =
927
    fprintf
928
      fmt
929
      "void %a (%a%a *%s)"
930
      pp_machine_clear_name
931
      name
932
      (pp_comma_list ~pp_eol:pp_print_comma pp_c_decl_input_var)
933
      static
934
      (pp_machine_memtype_name ~ghost:false)
935
      name
936
      self
937

    
938
  let pp_stateless_prototype fmt (name, inputs, outputs) =
939
    fprintf
940
      fmt
941
      "void %a (@[<v>%a%a@])"
942
      pp_machine_step_name
943
      name
944
      (pp_comma_list pp_c_decl_input_var)
945
      inputs
946
      (pp_comma_list ~pp_prologue:pp_print_comma pp_c_decl_output_var)
947
      outputs
948
end
949

    
950
let pp_import_prototype fmt dep = fprintf fmt "#include \"%s.h\"" dep.name
951

    
952
let pp_import_alloc_prototype fmt dep =
953
  if dep.is_stateful then fprintf fmt "#include \"%s_alloc.h\"" dep.name
954

    
955
let pp_c_var m self pp_var fmt var =
956
  pp_c_val m self pp_var fmt (Machine_code_common.mk_val (Var var) var.var_type)
957

    
958
let pp_array_suffix =
959
  pp_print_list ~pp_sep:pp_print_nothing (fun fmt v -> fprintf fmt "[%s]" v)
960

    
961
let mpfr_vars vars =
962
  if !Options.mpfr then
963
    List.filter
964
      (fun v -> Types.(is_real_type (array_base_type v.var_type)))
965
      vars
966
  else []
967

    
968
let mpfr_consts consts =
969
  if !Options.mpfr then
970
    List.filter
971
      (fun c -> Types.(is_real_type (array_base_type c.const_type)))
972
      consts
973
  else []
974

    
975
(* type directed initialization: useless wrt the lustre compilation model,
976
   except for MPFR injection, where values are dynamically allocated *)
977
let pp_initialize m self pp_var fmt var =
978
  let rec aux indices fmt typ =
979
    if Types.is_array_type typ then
980
      let dim = Types.array_type_dimension typ in
981
      let idx = mk_loop_var m () in
982
      fprintf
983
        fmt
984
        "@[<v 2>{@,int %s;@,for(%s=0;%s<%a;%s++)@,%a @]@,}"
985
        idx
986
        idx
987
        idx
988
        pp_c_dimension
989
        dim
990
        idx
991
        (aux (idx :: indices))
992
        (Types.array_element_type typ)
993
    else
994
      let indices = List.rev indices in
995
      let pp_var_suffix fmt var =
996
        fprintf fmt "%a%a" (pp_c_var m self pp_var) var pp_array_suffix indices
997
      in
998
      Mpfr.pp_inject_init pp_var_suffix fmt var
999
  in
1000
  reset_loop_counter ();
1001
  aux [] fmt var.var_type
1002

    
1003
(* type directed clear: useless wrt the lustre compilation model, except for
1004
   MPFR injection, where values are dynamically allocated *)
1005
let pp_clear m self pp_var fmt var =
1006
  let rec aux indices fmt typ =
1007
    if Types.is_array_type typ then
1008
      let dim = Types.array_type_dimension typ in
1009
      let idx = mk_loop_var m () in
1010
      fprintf
1011
        fmt
1012
        "@[<v 2>{@,int %s;@,for(%s=0;%s<%a;%s++)@,%a @]@,}"
1013
        idx
1014
        idx
1015
        idx
1016
        pp_c_dimension
1017
        dim
1018
        idx
1019
        (aux (idx :: indices))
1020
        (Types.array_element_type typ)
1021
    else
1022
      let indices = List.rev indices in
1023
      let pp_var_suffix fmt var =
1024
        fprintf fmt "%a%a" (pp_c_var m self pp_var) var pp_array_suffix indices
1025
      in
1026
      Mpfr.pp_inject_clear pp_var_suffix fmt var
1027
  in
1028
  reset_loop_counter ();
1029
  aux [] fmt var.var_type
1030

    
1031
(*** Common functions for main ***)
1032

    
1033
let pp_file file_suffix fmt (typ, arg) =
1034
  fprintf
1035
    fmt
1036
    "@[<v 2>if (traces) {@,fprintf(f_%s, \"%%%s\\n\", %s);@,fflush(f_%s);@]@,}"
1037
    file_suffix
1038
    typ
1039
    arg
1040
    file_suffix
1041

    
1042
let pp_put_var fmt file_suffix name var_type var_id =
1043
  let opt = !Options.c_main_options in
1044
  let pp_file fmt =
1045
    if opt then fprintf fmt "@,%a" (pp_file ("out" ^ file_suffix))
1046
    else pp_print_nothing fmt
1047
  in
1048
  let unclocked_t = Types.unclock_type var_type in
1049
  fprintf
1050
    fmt
1051
    "@[<v>%a@]"
1052
    (fun fmt () ->
1053
      if Types.is_int_type unclocked_t then
1054
        fprintf fmt "_put_int(\"%s\", %s);%a" name var_id pp_file ("d", var_id)
1055
      else if Types.is_bool_type unclocked_t then
1056
        fprintf fmt "_put_bool(\"%s\", %s);%a" name var_id pp_file ("i", var_id)
1057
      else if Types.is_real_type unclocked_t then
1058
        if !Options.mpfr then
1059
          fprintf
1060
            fmt
1061
            "_put_double(\"%s\", mpfr_get_d(%s, %s), %i);%a"
1062
            name
1063
            var_id
1064
            (Mpfr.mpfr_rnd ())
1065
            !Options.print_prec_double
1066
            pp_file
1067
            ( ".*f",
1068
              string_of_int !Options.print_prec_double
1069
              ^ ", mpfr_get_d(" ^ var_id ^ ", MPFR_RNDN)" )
1070
        else
1071
          fprintf
1072
            fmt
1073
            "_put_double(\"%s\", %s, %i);%a"
1074
            name
1075
            var_id
1076
            !Options.print_prec_double
1077
            pp_file
1078
            (".*f", string_of_int !Options.print_prec_double ^ ", " ^ var_id)
1079
      else (
1080
        eprintf
1081
          "Impossible to print the _put_xx for type %a@.@?"
1082
          Types.pp
1083
          var_type;
1084
        assert false))
1085
    ()
1086

    
1087
let pp_file_decl fmt inout idx =
1088
  let idx = idx + 1 in
1089
  (* we start from 1: in1, in2, ... *)
1090
  fprintf fmt "FILE *f_%s%i;" inout idx
1091

    
1092
let pp_file_open fmt inout idx =
1093
  let idx = idx + 1 in
1094
  (* we start from 1: in1, in2, ... *)
1095
  fprintf
1096
    fmt
1097
    "@[<v>const char* cst_char_suffix_%s%i = \"_simu.%s%i\";@,\
1098
     size_t l%s%i = strlen(dir) + strlen(prefix) + \
1099
     strlen(cst_char_suffix_%s%i);@,\
1100
     char* f_%s%i_name = malloc((l%s%i+2) * sizeof(char));@,\
1101
     strcpy (f_%s%i_name, dir);@,\
1102
     strcat(f_%s%i_name, \"/\");@,\
1103
     strcat(f_%s%i_name, prefix);@,\
1104
     strcat(f_%s%i_name, cst_char_suffix_%s%i);@,\
1105
     f_%s%i = fopen(f_%s%i_name, \"w\");@,\
1106
     free(f_%s%i_name);@]"
1107
    inout
1108
    idx
1109
    inout
1110
    idx
1111
    inout
1112
    idx
1113
    inout
1114
    idx
1115
    inout
1116
    idx
1117
    inout
1118
    idx
1119
    inout
1120
    idx
1121
    inout
1122
    idx
1123
    inout
1124
    idx
1125
    inout
1126
    idx
1127
    inout
1128
    idx
1129
    inout
1130
    idx
1131
    inout
1132
    idx
1133
    inout
1134
    idx;
1135
  "f_" ^ inout ^ string_of_int idx
1136

    
1137
let pp_basic_assign pp_var fmt typ var_name value =
1138
  if Types.is_real_type typ && !Options.mpfr then
1139
    Mpfr.pp_inject_assign pp_var fmt (var_name, value)
1140
  else fprintf fmt "%a = %a;" pp_var var_name pp_var value
1141

    
1142
(* type_directed assignment: array vs. statically sized type - [var_type]: type
1143
   of variable to be assigned - [var_name]: name of variable to be assigned -
1144
   [value]: assigned value - [pp_var]: printer for variables *)
1145
let pp_assign m self pp_var fmt (var, value) =
1146
  let depth = expansion_depth value in
1147
  let var_type = var.var_type in
1148
  let var = mk_val (Var var) var_type in
1149
  (*eprintf "pp_assign %a %a %a %d@." Types.pp var_type pp_val var_name pp_val
1150
    value depth;*)
1151
  let loop_vars = mk_loop_variables m var_type depth in
1152
  let reordered_loop_vars = reorder_loop_variables loop_vars in
1153
  let rec aux typ fmt vars =
1154
    match vars with
1155
    | [] ->
1156
      pp_basic_assign
1157
        (pp_value_suffix m self var_type loop_vars pp_var)
1158
        fmt
1159
        typ
1160
        var
1161
        value
1162
    | (d, LVar i) :: q ->
1163
      let typ' = Types.array_element_type typ in
1164
      (*eprintf "pp_aux %a %s@." Dimension.pp_dimension d i;*)
1165
      fprintf
1166
        fmt
1167
        "@[<v 2>{@,int %s;@,for(%s=0;%s<%a;%s++)@,%a @]@,}"
1168
        i
1169
        i
1170
        i
1171
        pp_c_dimension
1172
        d
1173
        i
1174
        (aux typ')
1175
        q
1176
    | (d, LInt r) :: q ->
1177
      (*eprintf "pp_aux %a %d@." Dimension.pp_dimension d (!r);*)
1178
      let typ' = Types.array_element_type typ in
1179
      let szl = Utils.enumerate (Dimension.size_const d) in
1180
      fprintf
1181
        fmt
1182
        "@[<v 2>{@,%a@]@,}"
1183
        (pp_print_list (fun fmt i ->
1184
             r := i;
1185
             aux typ' fmt q))
1186
        szl
1187
    | _ ->
1188
      assert false
1189
  in
1190
  reset_loop_counter ();
1191
  (*reset_addr_counter ();*)
1192
  aux var_type fmt reordered_loop_vars
1193
(*eprintf "end pp_assign@.";*)
1194

    
1195
let rec pp_static_val pp_var fmt v =
1196
  match v.value_desc with
1197
  | Cst c ->
1198
    pp_c_const fmt c
1199
  | Var v ->
1200
    pp_var fmt v
1201
  | Fun (n, vl) ->
1202
    pp_basic_lib_fun
1203
      (Types.is_int_type v.value_type)
1204
      n
1205
      (pp_static_val pp_var)
1206
      fmt
1207
      vl
1208
  | _ ->
1209
    (* TODO: raise proper error *)
1210
    eprintf "Internal error: C_backend_common.pp_static_val";
1211
    assert false
1212

    
1213
let concat x y =
1214
 x ^ "##" ^ y
1215

    
1216
let pp_constant_decl (m, attr, inst) pp_var fmt v =
1217
  fprintf
1218
    fmt
1219
    "%s %a = %a"
1220
    attr
1221
    (pp_c_type (concat inst v.var_id))
1222
    v.var_type
1223
    (pp_static_val pp_var)
1224
    (get_const_assign m v)
1225

    
1226
let pp_var inst const_locals fmt v =
1227
  pp_print_string fmt (if List.mem v const_locals then concat inst v.var_id else v.var_id)
1228

    
1229
let pp_static_constant_decl ((_, _, inst) as macro) fmt const_locals =
1230
  pp_print_list
1231
    ~pp_open_box:pp_open_vbox0
1232
    ~pp_sep:(pp_print_endcut ";\\")
1233
    ~pp_eol:(pp_print_endcut ";\\")
1234
    (pp_constant_decl macro (pp_var inst const_locals))
1235
    fmt
1236
    const_locals
1237

    
1238
let pp_static_declare_instance ?(ghost = false) (m, attr, inst) const_locals fmt
1239
    (i, (n, static)) =
1240
  let values = List.map (value_of_dimension m) static in
1241
  fprintf
1242
    fmt
1243
    "@[<h>%a(%s, %a%s)@]"
1244
    (pp_machine_static_declare_name ~ghost)
1245
    (node_name n)
1246
    attr
1247
    (pp_print_list
1248
       ~pp_open_box:pp_open_hbox
1249
       ~pp_sep:pp_print_comma
1250
       ~pp_eol:pp_print_comma
1251
       (pp_static_val (pp_var inst const_locals)))
1252
    values
1253
    i
1254

    
1255
let pp_static_declare_macro ?(ghost = false) fmt ((m, attr, inst) as macro) =
1256
  let const_locals =
1257
    List.filter (fun vdecl -> vdecl.var_dec_const) m.mstep.step_locals
1258
  in
1259
  let array_mem =
1260
    List.filter (fun v -> Types.is_array_type v.var_type) m.mmemory
1261
  in
1262
  fprintf
1263
    fmt
1264
    "@[<v 2>@[<h>#define %a(%s, %a%s)\\@]@,\
1265
     @[<h>%a%s %a %s;\\@]@,\
1266
     %a%a;@]"
1267
    (pp_machine_static_declare_name ~ghost)
1268
    m.mname.node_id
1269
    attr
1270
    (pp_print_list
1271
       ~pp_open_box:pp_open_hbox
1272
       ~pp_sep:pp_print_comma
1273
       ~pp_eol:pp_print_comma
1274
       (pp_c_var_read m))
1275
    m.mstatic
1276
    inst
1277
    (* constants *)
1278
    (pp_static_constant_decl macro)
1279
    const_locals
1280
    attr
1281
    (pp_machine_memtype_name ~ghost)
1282
    m.mname.node_id
1283
    inst
1284
    (pp_print_list
1285
       ~pp_open_box:pp_open_vbox0
1286
       ~pp_sep:(pp_print_endcut ";\\")
1287
       ~pp_eol:(pp_print_endcut ";\\")
1288
       (pp_c_decl_local_var m))
1289
    array_mem
1290
    (pp_print_list
1291
       ~pp_open_box:pp_open_vbox0
1292
       ~pp_sep:(pp_print_endcut ";\\")
1293
       (fun fmt (i', m') ->
1294
         let path = concat inst ("_" ^ i') in
1295
         pp_static_declare_instance ~ghost macro const_locals fmt (path, m')))
1296
    m.minstances
1297

    
1298
let pp_static_link_instance ?(ghost = false) fmt (i, (m, _)) =
1299
  fprintf fmt "%a(%s)" (pp_machine_static_link_name ~ghost) (node_name m) i
1300

    
1301
(* Allocation of a node struct: - if node memory is an array/matrix/etc, we cast
1302
   it to a pointer (see pp_registers_struct) *)
1303
let pp_static_link_macro ?(ghost = false) fmt (m, _, inst) =
1304
  let array_mem =
1305
    List.filter (fun v -> Types.is_array_type v.var_type) m.mmemory
1306
  in
1307
  fprintf
1308
    fmt
1309
    "@[<v>@[<v 2>#define %a(%s) do {\\@,\
1310
     @[<h>%a%a;\\@]@]@,} while (0)@]"
1311
    (pp_machine_static_link_name ~ghost)
1312
    m.mname.node_id
1313
    inst
1314
    (pp_print_list
1315
       ~pp_open_box:pp_open_vbox0
1316
       ~pp_sep:(pp_print_endcut ";\\")
1317
       ~pp_eol:(pp_print_endcut ";\\")
1318
       (fun fmt v ->
1319
         fprintf
1320
           fmt
1321
           "%s._reg.%s = (%a*) &%s"
1322
           inst
1323
           v.var_id
1324
           (fun fmt v -> pp_c_type "" fmt (Types.array_base_type v.var_type))
1325
           v
1326
           v.var_id))
1327
    array_mem
1328
    (pp_print_list
1329
       ~pp_open_box:pp_open_vbox0
1330
       ~pp_sep:(pp_print_endcut ";\\")
1331
       (fun fmt (i', m') ->
1332
         let path = concat inst ("_" ^ i') in
1333
         fprintf
1334
           fmt
1335
           "%a;\\@,%s.%s = %s%s"
1336
           (pp_static_link_instance ~ghost)
1337
           (path, m')
1338
           inst
1339
           i'
1340
           (if ghost then "" else "&")
1341
           path))
1342
    m.minstances
1343

    
1344
let pp_static_alloc_macro ?(ghost = false) fmt (m, attr, inst) =
1345
  fprintf
1346
    fmt
1347
    "@[<v>@[<v 2>@[<h>#define %a(%s, %a%s)\\@]@,\
1348
     @[<h>%a(%s, %a%s);\\@]@,\
1349
     @[<h>%a(%s);@]@]@]"
1350
    (pp_machine_static_alloc_name ~ghost)
1351
    m.mname.node_id
1352
    attr
1353
    (pp_print_list
1354
       ~pp_open_box:pp_open_hbox
1355
       ~pp_sep:pp_print_comma
1356
       ~pp_eol:pp_print_comma
1357
       (pp_c_var_read m))
1358
    m.mstatic
1359
    inst
1360
    (pp_machine_static_declare_name ~ghost)
1361
    m.mname.node_id
1362
    attr
1363
    (pp_print_list
1364
       ~pp_open_box:pp_open_hbox
1365
       ~pp_sep:pp_print_comma
1366
       ~pp_eol:pp_print_comma
1367
       (pp_c_var_read m))
1368
    m.mstatic
1369
    inst
1370
    (pp_machine_static_link_name ~ghost)
1371
    m.mname.node_id
1372
    inst
1373

    
1374
(* Local Variables: *)
1375
(* compile-command:"make -C ../../.." *)
1376
(* End: *)
(5-5/18)