Project

General

Profile

Download (13.6 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.Format
13
open Lustre_types
14
open Corelang
15
open Machine_code_types
16
open Machine_code_common
17
open C_backend_common
18
module Mpfr = Lustrec_mpfr
19

    
20
(********************************************************************************************)
21
(* Header Printing functions *)
22
(********************************************************************************************)
23

    
24
module type MODIFIERS_HDR = sig
25
  module GhostProto : MODIFIERS_GHOST_PROTO
26

    
27
  val pp_machine_decl_prefix : formatter -> machine_t -> unit
28

    
29
  val pp_predicates : formatter -> machine_t list -> unit
30

    
31
  val pp_import_arrow : formatter -> unit -> unit
32

    
33
  val pp_machine_alloc_decl : formatter -> machine_t -> unit
34
end
35

    
36
module EmptyMod = struct
37
  module GhostProto = EmptyGhostProto
38

    
39
  let pp_machine_decl_prefix _ _ = ()
40

    
41
  let pp_predicates _ _ = ()
42

    
43
  let pp_import_arrow fmt () =
44
    fprintf
45
      fmt
46
      "#include \"%s/arrow.h%s\""
47
      (Arrow.arrow_top_decl ()).top_decl_owner
48
      (if !Options.cpp then "pp" else "")
49

    
50
  let pp_machine_alloc_decl _ _ = ()
51
end
52

    
53
module Main =
54
functor
55
  (Mod : MODIFIERS_HDR)
56
  ->
57
  struct
58
    module Protos = Protos (Mod.GhostProto)
59

    
60
    let pp_import_standard fmt () =
61
      (* if Machine_types.has_machine_type () then *)
62
      fprintf
63
        fmt
64
        "#include <stdint.h>@,%a%a"
65
        (if !Options.mpfr then pp_print_endcut "#include <mpfr.h>"
66
        else pp_print_nothing)
67
        ()
68
        Mod.pp_import_arrow
69
        ()
70

    
71
    (* TODO: ACSL we do multiple things: - provide the semantics of the node as
72
       a predicate: function step and reset are associated to ACSL predicate -
73
       the node is associated to a refinement contract, wrt its ACSL sem - if
74
       the node is a regular node associated to a contract, print the contract
75
       as function contract. - do not print anything if this is a contract
76
       node *)
77
    let pp_machine_alloc_decl fmt m =
78
      Mod.pp_machine_decl_prefix fmt m;
79
      if not (fst (get_stateless_status m)) then
80
        if !Options.static_mem then
81
          (* Static allocation *)
82
          let macro = m, mk_attribute m, mk_instance m in
83
          fprintf
84
            fmt
85
            "%a@,%a@,%a"
86
            (fun x -> pp_static_declare_macro x)
87
            macro
88
            (fun x -> pp_static_link_macro x)
89
            macro
90
            (fun x -> pp_static_alloc_macro x)
91
            macro
92
        else
93
          (* Dynamic allocation *)
94
          fprintf
95
            fmt
96
            "extern %a;@,extern %a"
97
            pp_alloc_prototype
98
            (m.mname.node_id, m.mstatic)
99
            pp_dealloc_prototype
100
            m.mname.node_id
101

    
102
    let pp_machine_struct_top_decl_from_header fmt tdecl =
103
      let inode = imported_node_of_top tdecl in
104
      if not (inode.nodei_stateless || inode.nodei_iscontract) then
105
        (* Declare struct *)
106
        fprintf fmt "%a;" (pp_machine_memtype_name ~ghost:false) inode.nodei_id
107

    
108
    let pp_stateless_C_prototype fmt (name, inputs, outputs) =
109
      let output = match outputs with [ hd ] -> hd | _ -> assert false in
110
      fprintf
111
        fmt
112
        "%a %s %a"
113
        (fun x -> pp_basic_c_type ~pp_c_basic_type_desc x)
114
        output.var_type
115
        name
116
        (pp_print_parenthesized pp_c_decl_input_var)
117
        inputs
118

    
119
    let pp_machine_decl_top_decl_from_header fmt tdecl =
120
      let inode = imported_node_of_top tdecl in
121
      (*Mod.print_machine_decl_prefix fmt m;*)
122
      let prototype = inode.nodei_id, inode.nodei_inputs, inode.nodei_outputs in
123
      if not inode.nodei_iscontract then
124
        if inode.nodei_prototype = Some "C" then
125
          if inode.nodei_stateless then
126
            fprintf fmt "extern %a;" pp_stateless_C_prototype prototype
127
          else (
128
            (* TODO: raise proper error *)
129
            Format.eprintf
130
              "internal error: pp_machine_decl_top_decl_from_header";
131
            assert false)
132
        else if inode.nodei_stateless then
133
          fprintf fmt "extern %a;" Protos.pp_stateless_prototype prototype
134
        else
135
          let static_inputs =
136
            List.filter (fun v -> v.var_dec_const) inode.nodei_inputs
137
          in
138
          let used name =
139
            List.exists
140
              (fun v -> v.var_id = name)
141
              (inode.nodei_inputs @ inode.nodei_outputs)
142
          in
143
          let self = mk_new_name used "self" in
144
          let mem = mk_new_name used "mem" in
145
          let static_prototype = inode.nodei_id, static_inputs in
146
          fprintf
147
            fmt
148
            "extern %a;@,extern %a;@,extern %a;@,extern %a;@,extern %a;"
149
            (Protos.pp_set_reset_prototype self mem)
150
            static_prototype
151
            (Protos.pp_clear_reset_prototype self mem)
152
            static_prototype
153
            (Protos.pp_init_prototype self)
154
            static_prototype
155
            (Protos.pp_clear_prototype self)
156
            static_prototype
157
            (Protos.pp_step_prototype self mem)
158
            prototype
159

    
160
    let pp_const_top_decl fmt tdecl =
161
      let cdecl = const_of_top tdecl in
162
      fprintf
163
        fmt
164
        "extern %a;"
165
        (pp_c_type cdecl.const_id)
166
        (if
167
         !Options.mpfr
168
         && Types.(is_real_type (array_base_type cdecl.const_type))
169
        then Types.dynamic_type cdecl.const_type
170
        else cdecl.const_type)
171

    
172
    let rec pp_c_type_decl filename cpt var fmt tdecl =
173
      match tdecl with
174
      | Tydec_any ->
175
        assert false
176
      | Tydec_int ->
177
        fprintf fmt "int %s" var
178
      | Tydec_real when !Options.mpfr ->
179
        fprintf fmt "%s %s" Mpfr.mpfr_t var
180
      | Tydec_real ->
181
        fprintf fmt "double %s" var
182
      (* | Tydec_float -> fprintf fmt "float %s" var *)
183
      | Tydec_bool ->
184
        fprintf fmt "_Bool %s" var
185
      | Tydec_clock ty ->
186
        pp_c_type_decl filename cpt var fmt ty
187
      | Tydec_const c ->
188
        fprintf fmt "%s %s" c var
189
      | Tydec_array (d, ty) ->
190
        fprintf
191
          fmt
192
          "%a[%a]"
193
          (pp_c_type_decl filename cpt var)
194
          ty
195
          pp_c_dimension
196
          d
197
      | Tydec_enum tl ->
198
        incr cpt;
199
        fprintf
200
          fmt
201
          "enum _enum_%s_%d %a %s"
202
          (protect_filename filename)
203
          !cpt
204
          (pp_print_braced pp_print_string)
205
          tl
206
          var
207
      | Tydec_struct fl ->
208
        incr cpt;
209
        fprintf
210
          fmt
211
          "struct _struct_%s_%d %a %s"
212
          (protect_filename filename)
213
          !cpt
214
          (pp_print_braced ~pp_sep:pp_print_semicolon (fun fmt (label, tdesc) ->
215
               pp_c_type_decl filename cpt label fmt tdesc))
216
          fl
217
          var
218

    
219
    (* let print_type_definitions fmt filename =
220
     *   let cpt_type = ref 0 in
221
     *   Hashtbl.iter (fun typ decl ->
222
     *       match typ with
223
     *       | Tydec_const var ->
224
     *         begin match decl.top_decl_desc with
225
     *           | TypeDef tdef ->
226
     *             fprintf fmt "typedef %a;@.@."
227
     *               (pp_c_type_decl filename cpt_type var) tdef.tydef_desc
228
     *           | _ -> assert false
229
     *         end
230
     *       | _ -> ()) type_table *)
231

    
232
    let reset_type_definitions, pp_type_definition_top_decl_from_header =
233
      let cpt_type = ref 0 in
234
      ( (fun () -> cpt_type := 0),
235
        fun filename fmt tdecl ->
236
          let typ = typedef_of_top tdecl in
237
          fprintf
238
            fmt
239
            "typedef %a;"
240
            (pp_c_type_decl filename cpt_type typ.tydef_id)
241
            typ.tydef_desc )
242

    
243
    (********************************************************************************************)
244
    (* MAIN Header Printing functions *)
245
    (********************************************************************************************)
246

    
247
    let pp_alloc_header header_fmt basename machines dependencies =
248
      (* Include once: start *)
249
      let machines' = List.filter (fun m -> not m.mis_contract) machines in
250
      let baseNAME = file_to_module_name basename in
251
      fprintf
252
        header_fmt
253
        "@[<v>%a@,\
254
         #ifndef _%s_alloc@,\
255
         #define _%s_alloc@,\
256
         @,\
257
         /* Import header from %s */@,\
258
         %a@,\
259
         @,\
260
         %a%a%a%a%a#endif@]@."
261
        (* Print the svn version number and the supported C standard (C90 or
262
           C99) *)
263
        pp_print_version
264
        ()
265
        baseNAME
266
        baseNAME
267
        (* Import the header *) basename
268
        pp_import_prototype
269
        {
270
          local = true;
271
          name = basename;
272
          content = [];
273
          is_stateful = true (* assuming it is staful *);
274
        }
275
        (* Print dependencies *)
276
        (pp_print_list
277
           ~pp_open_box:pp_open_vbox0
278
           ~pp_prologue:(pp_print_endcut "/* Import dependencies */")
279
           pp_import_alloc_prototype
280
           ~pp_epilogue:pp_print_cutcut)
281
        dependencies
282
        (* Print the struct definitions of all machines. *)
283
        (pp_print_list
284
           ~pp_open_box:pp_open_vbox0
285
           ~pp_prologue:(pp_print_endcut "/* Struct definitions */")
286
           ~pp_sep:pp_print_cutcut
287
           pp_machine_struct
288
           ~pp_epilogue:pp_print_cutcut)
289
        machines'
290
        (* Copy the spec (valid and memory packs predicates). *)
291
        Mod.pp_predicates
292
        machines
293
        (* Print the prototypes of all machines *)
294
        (pp_print_list
295
           ~pp_open_box:pp_open_vbox0
296
           ~pp_prologue:
297
             (pp_print_endcut "/* Node allocation function/macro prototypes */")
298
           ~pp_sep:pp_print_cutcut
299
           pp_machine_alloc_decl
300
           ~pp_epilogue:pp_print_cutcut)
301
        machines'
302
        (* Print the spec prototypes of all machines *)
303
        (pp_print_list
304
           ~pp_open_box:pp_open_vbox0
305
           ~pp_prologue:
306
             (pp_print_endcut
307
                "/* Node allocation function/macro ghost prototypes */")
308
           ~pp_sep:pp_print_cutcut
309
           Mod.pp_machine_alloc_decl
310
           ~pp_epilogue:pp_print_cutcut)
311
        machines'
312
    (* Include once: end *)
313

    
314
    (* Function called when compiling a lusi file and generating the associated
315
       C header. *)
316
    let pp_header_from_header header_fmt basename header =
317
      (* Include once: start *)
318
      let baseNAME = file_to_module_name basename in
319
      let types = get_typedefs header in
320
      let consts = get_consts header in
321
      let nodes = get_imported_nodes header in
322
      let dependencies = get_dependencies header in
323
      reset_type_definitions ();
324
      fprintf
325
        header_fmt
326
        "@[<v>%a@,\
327
         #ifndef _%s@,\
328
         #define _%s@,\
329
         @,\
330
         /* Import standard library */@,\
331
         %a@,\
332
         @,\
333
         %a%a%a%a%a%a#endif@]@."
334
        (* Print the version number and the supported C standard (C90 or C99) *)
335
        pp_print_version
336
        ()
337
        baseNAME
338
        baseNAME
339
        (* imports standard library definitions (arrow) *)
340
        pp_import_standard
341
        ()
342
        (* imports dependencies *)
343
        (pp_print_list
344
           ~pp_open_box:pp_open_vbox0
345
           ~pp_prologue:(pp_print_endcut "/* Import dependencies */")
346
           (fun fmt dep ->
347
             let local, name = dependency_of_top dep in
348
             pp_import_prototype
349
               fmt
350
               {
351
                 local;
352
                 name;
353
                 content = [];
354
                 is_stateful = true (* assuming it is stateful *);
355
               })
356
           ~pp_epilogue:pp_print_cutcut)
357
        dependencies
358
        (* Print the type definitions from the type table *)
359
        (pp_print_list
360
           ~pp_open_box:pp_open_vbox0
361
           ~pp_prologue:(pp_print_endcut "/* Types definitions */")
362
           (pp_type_definition_top_decl_from_header basename)
363
           ~pp_epilogue:pp_print_cutcut)
364
        types
365
        (* Print the global constant declarations. *)
366
        (pp_print_list
367
           ~pp_open_box:pp_open_vbox0
368
           ~pp_prologue:
369
             (pp_print_endcut
370
                "/* Global constants (declarations, definitions are in C file) \
371
                 */")
372
           pp_const_top_decl
373
           ~pp_epilogue:pp_print_cutcut)
374
        consts
375
        (* MPFR *)
376
        (if !Options.mpfr then fun fmt () ->
377
         fprintf
378
           fmt
379
           "/* Global initialization declaration */@,\
380
            extern %a;@,\
381
            @,\
382
            /* Global clear declaration */@,\
383
            extern %a;@,\
384
            @,"
385
           pp_global_init_prototype
386
           baseNAME
387
           pp_global_clear_prototype
388
           baseNAME
389
        else pp_print_nothing)
390
        ()
391
        (* Print the struct declarations of all machines. *)
392
        (pp_print_list
393
           ~pp_open_box:pp_open_vbox0
394
           ~pp_prologue:(pp_print_endcut "/* Struct declarations */")
395
           pp_machine_struct_top_decl_from_header
396
           ~pp_epilogue:pp_print_cutcut)
397
        nodes
398
        (* Print the prototypes of all machines *)
399
        (pp_print_list
400
           ~pp_open_box:pp_open_vbox0
401
           ~pp_prologue:(pp_print_endcut "/* Nodes declarations */")
402
           ~pp_sep:pp_print_cutcut
403
           pp_machine_decl_top_decl_from_header
404
           ~pp_epilogue:pp_print_cutcut)
405
        nodes
406
  end
407
(* Local Variables: *)
408
(* compile-command:"make -C ../../.." *)
409
(* End: *)
(7-7/18)