Revision 4b596770
Added by Lélio Brun about 4 years ago
src/backends/C/c_backend_src.ml | ||
---|---|---|
37 | 37 |
(********************************************************************************************) |
38 | 38 |
|
39 | 39 |
|
40 |
(* Computes the depth to which multi-dimension array assignments should be expanded. |
|
41 |
It equals the maximum number of nested static array constructions accessible from root [v]. |
|
42 |
*) |
|
43 |
let rec expansion_depth v = |
|
44 |
match v.value_desc with |
|
45 |
| Cst cst -> expansion_depth_cst cst |
|
46 |
| Var _ -> 0 |
|
47 |
| Fun (_, vl) -> List.fold_right (fun v -> max (expansion_depth v)) vl 0 |
|
48 |
| Array vl -> 1 + List.fold_right (fun v -> max (expansion_depth v)) vl 0 |
|
49 |
| Access (v, _) -> max 0 (expansion_depth v - 1) |
|
50 |
| Power _ -> 0 (*1 + expansion_depth v*) |
|
51 |
and expansion_depth_cst c = |
|
52 |
match c with |
|
53 |
| Const_array cl -> |
|
54 |
1 + List.fold_right (fun c -> max (expansion_depth_cst c)) cl 0 |
|
55 |
| _ -> 0 |
|
56 |
|
|
57 | 40 |
let rec merge_static_loop_profiles lp1 lp2 = |
58 | 41 |
match lp1, lp2 with |
59 | 42 |
| [] , _ -> lp2 |
... | ... | |
82 | 65 |
cl [] |
83 | 66 |
| _ -> [] |
84 | 67 |
|
85 |
let rec is_const_index v = |
|
86 |
match v.value_desc with |
|
87 |
| Cst (Const_int _) -> true |
|
88 |
| Fun (_, vl) -> List.for_all is_const_index vl |
|
89 |
| _ -> false |
|
90 |
|
|
91 |
type loop_index = LVar of ident | LInt of int ref | LAcc of value_t |
|
92 |
(* |
|
93 |
let rec value_offsets v offsets = |
|
94 |
match v, offsets with |
|
95 |
| _ , [] -> v |
|
96 |
| Power (v, n) , _ :: q -> value_offsets v q |
|
97 |
| Array vl , LInt r :: q -> value_offsets (List.nth vl !r) q |
|
98 |
| Cst (Const_array cl) , LInt r :: q -> value_offsets (Cst (List.nth cl !r)) q |
|
99 |
| Fun (f, vl) , _ -> Fun (f, List.map (fun v -> value_offsets v offsets) vl) |
|
100 |
| _ , LInt r :: q -> value_offsets (Access (v, Cst (Const_int !r))) q |
|
101 |
| _ , LVar i :: q -> value_offsets (Access (v, Var i)) q |
|
102 |
*) |
|
103 |
(* Computes the list of nested loop variables together with their dimension bounds. |
|
104 |
- LInt r stands for loop expansion (no loop variable, but int loop index) |
|
105 |
- LVar v stands for loop variable v |
|
106 |
*) |
|
107 |
let rec mk_loop_variables m ty depth = |
|
108 |
match (Types.repr ty).Types.tdesc, depth with |
|
109 |
| Types.Tarray (d, ty'), 0 -> |
|
110 |
let v = mk_loop_var m () in |
|
111 |
(d, LVar v) :: mk_loop_variables m ty' 0 |
|
112 |
| Types.Tarray (d, ty'), _ -> |
|
113 |
let r = ref (-1) in |
|
114 |
(d, LInt r) :: mk_loop_variables m ty' (depth - 1) |
|
115 |
| _, 0 -> [] |
|
116 |
| _ -> assert false |
|
117 |
|
|
118 |
let reorder_loop_variables loop_vars = |
|
119 |
let (int_loops, var_loops) = |
|
120 |
List.partition (function (_, LInt _) -> true | _ -> false) loop_vars |
|
121 |
in |
|
122 |
var_loops @ int_loops |
|
123 |
|
|
124 |
(* Prints a one loop variable suffix for arrays *) |
|
125 |
let pp_loop_var pp_val fmt lv = |
|
126 |
match snd lv with |
|
127 |
| LVar v -> fprintf fmt "[%s]" v |
|
128 |
| LInt r -> fprintf fmt "[%d]" !r |
|
129 |
| LAcc i -> fprintf fmt "[%a]" pp_val i |
|
130 |
|
|
131 |
(* Prints a suffix of loop variables for arrays *) |
|
132 |
let pp_suffix pp_val = |
|
133 |
pp_print_list ~pp_sep:pp_print_nothing (pp_loop_var pp_val) |
|
134 |
|
|
135 |
(* Prints a value expression [v], with internal function calls only. |
|
136 |
[pp_var] is a printer for variables (typically [pp_c_var_read]), |
|
137 |
but an offset suffix may be added for array variables |
|
138 |
*) |
|
139 |
(* Prints a constant value before a suffix (needs casting) *) |
|
140 |
let rec pp_c_const_suffix var_type fmt c = |
|
141 |
match c with |
|
142 |
| Const_int i -> |
|
143 |
pp_print_int fmt i |
|
144 |
| Const_real r -> |
|
145 |
Real.pp fmt r |
|
146 |
| Const_tag t -> |
|
147 |
pp_c_tag fmt t |
|
148 |
| Const_array ca -> |
|
149 |
let var_type = Types.array_element_type var_type in |
|
150 |
fprintf fmt "(%a[])%a" |
|
151 |
(pp_c_type "") var_type |
|
152 |
(pp_print_braced (pp_c_const_suffix var_type)) ca |
|
153 |
| Const_struct fl -> |
|
154 |
pp_print_braced |
|
155 |
(fun fmt (f, c) -> |
|
156 |
(pp_c_const_suffix (Types.struct_field_type var_type f)) fmt c) |
|
157 |
fmt fl |
|
158 |
| Const_string _ |
|
159 |
| Const_modeid _ -> assert false (* string occurs in annotations not in C *) |
|
160 |
|
|
161 |
(* Prints a [value] of type [var_type] indexed by the suffix list [loop_vars] *) |
|
162 |
let rec pp_value_suffix m self var_type loop_vars pp_var fmt value = |
|
163 |
(*eprintf "pp_value_suffix: %a %a %a@." Types.print_ty var_type Machine_code.pp_val value pp_suffix loop_vars;*) |
|
164 |
let pp_suffix = pp_suffix (pp_value_suffix m self var_type [] pp_var) in |
|
165 |
match loop_vars, value.value_desc with |
|
166 |
| (x, LAcc i) :: q, _ when is_const_index i -> |
|
167 |
let r = ref (Dimension.size_const_dimension (dimension_of_value i)) in |
|
168 |
pp_value_suffix m self var_type ((x, LInt r)::q) pp_var fmt value |
|
169 |
| (_, LInt r) :: q, Cst (Const_array cl) -> |
|
170 |
let var_type = Types.array_element_type var_type in |
|
171 |
pp_value_suffix m self var_type q pp_var fmt |
|
172 |
(mk_val (Cst (List.nth cl !r)) Type_predef.type_int) |
|
173 |
| (_, LInt r) :: q, Array vl -> |
|
174 |
let var_type = Types.array_element_type var_type in |
|
175 |
pp_value_suffix m self var_type q pp_var fmt (List.nth vl !r) |
|
176 |
| loop_var :: q, Array vl -> |
|
177 |
let var_type = Types.array_element_type var_type in |
|
178 |
fprintf fmt "(%a[])%a%a" |
|
179 |
(pp_c_type "") var_type |
|
180 |
(pp_print_braced (pp_value_suffix m self var_type q pp_var)) vl |
|
181 |
pp_suffix [loop_var] |
|
182 |
| [], Array vl -> |
|
183 |
let var_type = Types.array_element_type var_type in |
|
184 |
fprintf fmt "(%a[])%a" |
|
185 |
(pp_c_type "") var_type |
|
186 |
(pp_print_braced (pp_value_suffix m self var_type [] pp_var)) vl |
|
187 |
| _ :: q, Power (v, _) -> |
|
188 |
pp_value_suffix m self var_type q pp_var fmt v |
|
189 |
| _, Fun (n, vl) -> |
|
190 |
pp_basic_lib_fun (Types.is_int_type value.value_type) n |
|
191 |
(pp_value_suffix m self var_type loop_vars pp_var) fmt vl |
|
192 |
| _, Access (v, i) -> |
|
193 |
let var_type = Type_predef.type_array (Dimension.mkdim_var ()) var_type in |
|
194 |
pp_value_suffix m self var_type |
|
195 |
((Dimension.mkdim_var (), LAcc i) :: loop_vars) pp_var fmt v |
|
196 |
| _, Var v -> |
|
197 |
if is_memory m v then |
|
198 |
(* array memory vars are represented by an indirection to a local var with the right type, |
|
199 |
in order to avoid casting everywhere. *) |
|
200 |
if Types.is_array_type v.var_type |
|
201 |
then fprintf fmt "%a%a" pp_var v pp_suffix loop_vars |
|
202 |
else fprintf fmt "%s->_reg.%a%a" self pp_var v pp_suffix loop_vars |
|
203 |
else |
|
204 |
fprintf fmt "%a%a" pp_var v pp_suffix loop_vars |
|
205 |
| _, Cst cst -> |
|
206 |
pp_c_const_suffix var_type fmt cst |
|
207 |
| _, _ -> |
|
208 |
eprintf "internal error: C_backend_src.pp_value_suffix %a %a %a@." |
|
209 |
Types.print_ty var_type (pp_val m) value pp_suffix loop_vars; |
|
210 |
assert false |
|
211 | 68 |
|
212 | 69 |
(* Subsumes C_backend_common.pp_c_val to cope with aggressive substitution |
213 | 70 |
which may yield constant arrays in expressions. |
... | ... | |
393 | 250 |
pp_machine_instr dependencies m self fmt instr |
394 | 251 |
|
395 | 252 |
let pp_machine_step_instr dependencies m self fmt i instr = |
396 |
fprintf fmt "%a%a%a" |
|
253 |
fprintf fmt "%a@,%a%a"
|
|
397 | 254 |
(if i = 0 then |
398 |
(fun fmt () -> Mod.pp_step_instr_spec m self fmt (i-1, instr))
|
|
255 |
(fun fmt () -> Mod.pp_step_instr_spec m self fmt (i, instr)) |
|
399 | 256 |
else |
400 | 257 |
pp_print_nothing) () |
401 | 258 |
(pp_machine_instr dependencies m self) instr |
402 |
(Mod.pp_step_instr_spec m self) (i, instr) |
|
259 |
(Mod.pp_step_instr_spec m self) (i+1, instr)
|
|
403 | 260 |
|
404 | 261 |
(********************************************************************************************) |
405 | 262 |
(* C file Printing functions *) |
Also available in: Unified diff
first draft: to be tested with frama-c