Revision 4b596770
Added by Lélio Brun about 4 years ago
src/backends/C/c_backend_common.ml | ||
---|---|---|
13 | 13 |
open Lustre_types |
14 | 14 |
open Corelang |
15 | 15 |
open Machine_code_types |
16 |
(*open Machine_code_common*)
|
|
16 |
open Machine_code_common
|
|
17 | 17 |
module Mpfr = Lustrec_mpfr |
18 | 18 |
|
19 | 19 |
let pp_print_version fmt () = |
... | ... | |
447 | 447 |
| None -> false |
448 | 448 |
| Some nd -> (match nd.nodei_prototype with Some "C" -> true | _ -> false) |
449 | 449 |
|
450 |
(* Computes the depth to which multi-dimension array assignments should be expanded. |
|
451 |
It equals the maximum number of nested static array constructions accessible from root [v]. |
|
452 |
*) |
|
453 |
let rec expansion_depth v = |
|
454 |
match v.value_desc with |
|
455 |
| Cst cst -> expansion_depth_cst cst |
|
456 |
| Var _ -> 0 |
|
457 |
| Fun (_, vl) -> List.fold_right (fun v -> max (expansion_depth v)) vl 0 |
|
458 |
| Array vl -> 1 + List.fold_right (fun v -> max (expansion_depth v)) vl 0 |
|
459 |
| Access (v, _) -> max 0 (expansion_depth v - 1) |
|
460 |
| Power _ -> 0 (*1 + expansion_depth v*) |
|
461 |
and expansion_depth_cst c = |
|
462 |
match c with |
|
463 |
| Const_array cl -> |
|
464 |
1 + List.fold_right (fun c -> max (expansion_depth_cst c)) cl 0 |
|
465 |
| _ -> 0 |
|
466 |
|
|
467 |
type loop_index = LVar of ident | LInt of int ref | LAcc of value_t |
|
468 |
(* |
|
469 |
let rec value_offsets v offsets = |
|
470 |
match v, offsets with |
|
471 |
| _ , [] -> v |
|
472 |
| Power (v, n) , _ :: q -> value_offsets v q |
|
473 |
| Array vl , LInt r :: q -> value_offsets (List.nth vl !r) q |
|
474 |
| Cst (Const_array cl) , LInt r :: q -> value_offsets (Cst (List.nth cl !r)) q |
|
475 |
| Fun (f, vl) , _ -> Fun (f, List.map (fun v -> value_offsets v offsets) vl) |
|
476 |
| _ , LInt r :: q -> value_offsets (Access (v, Cst (Const_int !r))) q |
|
477 |
| _ , LVar i :: q -> value_offsets (Access (v, Var i)) q |
|
478 |
*) |
|
479 |
(* Computes the list of nested loop variables together with their dimension bounds. |
|
480 |
- LInt r stands for loop expansion (no loop variable, but int loop index) |
|
481 |
- LVar v stands for loop variable v |
|
482 |
*) |
|
483 |
let rec mk_loop_variables m ty depth = |
|
484 |
match (Types.repr ty).Types.tdesc, depth with |
|
485 |
| Types.Tarray (d, ty'), 0 -> |
|
486 |
let v = mk_loop_var m () in |
|
487 |
(d, LVar v) :: mk_loop_variables m ty' 0 |
|
488 |
| Types.Tarray (d, ty'), _ -> |
|
489 |
let r = ref (-1) in |
|
490 |
(d, LInt r) :: mk_loop_variables m ty' (depth - 1) |
|
491 |
| _, 0 -> [] |
|
492 |
| _ -> assert false |
|
493 |
|
|
494 |
let reorder_loop_variables loop_vars = |
|
495 |
let (int_loops, var_loops) = |
|
496 |
List.partition (function (_, LInt _) -> true | _ -> false) loop_vars |
|
497 |
in |
|
498 |
var_loops @ int_loops |
|
499 |
|
|
500 |
(* Prints a one loop variable suffix for arrays *) |
|
501 |
let pp_loop_var pp_val fmt lv = |
|
502 |
match snd lv with |
|
503 |
| LVar v -> fprintf fmt "[%s]" v |
|
504 |
| LInt r -> fprintf fmt "[%d]" !r |
|
505 |
| LAcc i -> fprintf fmt "[%a]" pp_val i |
|
506 |
|
|
507 |
(* Prints a suffix of loop variables for arrays *) |
|
508 |
let pp_suffix pp_val = |
|
509 |
pp_print_list ~pp_sep:pp_print_nothing (pp_loop_var pp_val) |
|
510 |
|
|
511 |
let rec is_const_index v = |
|
512 |
match v.value_desc with |
|
513 |
| Cst (Const_int _) -> true |
|
514 |
| Fun (_, vl) -> List.for_all is_const_index vl |
|
515 |
| _ -> false |
|
516 |
|
|
517 |
(* Prints a value expression [v], with internal function calls only. |
|
518 |
[pp_var] is a printer for variables (typically [pp_c_var_read]), |
|
519 |
but an offset suffix may be added for array variables |
|
520 |
*) |
|
521 |
(* Prints a constant value before a suffix (needs casting) *) |
|
522 |
let rec pp_c_const_suffix var_type fmt c = |
|
523 |
match c with |
|
524 |
| Const_int i -> |
|
525 |
pp_print_int fmt i |
|
526 |
| Const_real r -> |
|
527 |
Real.pp fmt r |
|
528 |
| Const_tag t -> |
|
529 |
pp_c_tag fmt t |
|
530 |
| Const_array ca -> |
|
531 |
let var_type = Types.array_element_type var_type in |
|
532 |
fprintf fmt "(%a[])%a" |
|
533 |
(pp_c_type "") var_type |
|
534 |
(pp_print_braced (pp_c_const_suffix var_type)) ca |
|
535 |
| Const_struct fl -> |
|
536 |
pp_print_braced |
|
537 |
(fun fmt (f, c) -> |
|
538 |
(pp_c_const_suffix (Types.struct_field_type var_type f)) fmt c) |
|
539 |
fmt fl |
|
540 |
| Const_string _ |
|
541 |
| Const_modeid _ -> assert false (* string occurs in annotations not in C *) |
|
542 |
|
|
543 |
(* Prints a [value] of type [var_type] indexed by the suffix list [loop_vars] *) |
|
544 |
let rec pp_value_suffix ?(indirect=true) m self var_type loop_vars pp_var fmt value = |
|
545 |
(*eprintf "pp_value_suffix: %a %a %a@." Types.print_ty var_type Machine_code.pp_val value pp_suffix loop_vars;*) |
|
546 |
let pp_suffix = pp_suffix (pp_value_suffix ~indirect m self var_type [] pp_var) in |
|
547 |
match loop_vars, value.value_desc with |
|
548 |
| (x, LAcc i) :: q, _ when is_const_index i -> |
|
549 |
let r = ref (Dimension.size_const_dimension (dimension_of_value i)) in |
|
550 |
pp_value_suffix ~indirect m self var_type ((x, LInt r)::q) pp_var fmt value |
|
551 |
| (_, LInt r) :: q, Cst (Const_array cl) -> |
|
552 |
let var_type = Types.array_element_type var_type in |
|
553 |
pp_value_suffix ~indirect m self var_type q pp_var fmt |
|
554 |
(mk_val (Cst (List.nth cl !r)) Type_predef.type_int) |
|
555 |
| (_, LInt r) :: q, Array vl -> |
|
556 |
let var_type = Types.array_element_type var_type in |
|
557 |
pp_value_suffix ~indirect m self var_type q pp_var fmt (List.nth vl !r) |
|
558 |
| loop_var :: q, Array vl -> |
|
559 |
let var_type = Types.array_element_type var_type in |
|
560 |
fprintf fmt "(%a[])%a%a" |
|
561 |
(pp_c_type "") var_type |
|
562 |
(pp_print_braced (pp_value_suffix ~indirect m self var_type q pp_var)) vl |
|
563 |
pp_suffix [loop_var] |
|
564 |
| [], Array vl -> |
|
565 |
let var_type = Types.array_element_type var_type in |
|
566 |
fprintf fmt "(%a[])%a" |
|
567 |
(pp_c_type "") var_type |
|
568 |
(pp_print_braced (pp_value_suffix ~indirect m self var_type [] pp_var)) vl |
|
569 |
| _ :: q, Power (v, _) -> |
|
570 |
pp_value_suffix ~indirect m self var_type q pp_var fmt v |
|
571 |
| _, Fun (n, vl) -> |
|
572 |
pp_basic_lib_fun (Types.is_int_type value.value_type) n |
|
573 |
(pp_value_suffix ~indirect m self var_type loop_vars pp_var) fmt vl |
|
574 |
| _, Access (v, i) -> |
|
575 |
let var_type = Type_predef.type_array (Dimension.mkdim_var ()) var_type in |
|
576 |
pp_value_suffix m self var_type |
|
577 |
((Dimension.mkdim_var (), LAcc i) :: loop_vars) pp_var fmt v |
|
578 |
| _, Var v -> |
|
579 |
if is_memory m v then |
|
580 |
(* array memory vars are represented by an indirection to a local var with the right type, |
|
581 |
in order to avoid casting everywhere. *) |
|
582 |
if Types.is_array_type v.var_type |
|
583 |
then fprintf fmt "%a%a" pp_var v pp_suffix loop_vars |
|
584 |
else fprintf fmt "%s%s_reg.%a%a" |
|
585 |
self (if indirect then "->" else ".") pp_var v pp_suffix loop_vars |
|
586 |
else |
|
587 |
fprintf fmt "%a%a" pp_var v pp_suffix loop_vars |
|
588 |
| _, Cst cst -> |
|
589 |
pp_c_const_suffix var_type fmt cst |
|
590 |
| _, _ -> |
|
591 |
eprintf "internal error: C_backend_src.pp_value_suffix %a %a %a@." |
|
592 |
Types.print_ty var_type (pp_val m) value pp_suffix loop_vars; |
|
593 |
assert false |
|
594 |
|
|
450 | 595 |
(********************************************************************************************) |
451 | 596 |
(* Struct Printing functions *) |
452 | 597 |
(********************************************************************************************) |
Also available in: Unified diff
first draft: to be tested with frama-c