2 * Copyright 2012-2013 Ecole Normale Superieure
4 * Use of this software is governed by the MIT license
6 * Written by Sven Verdoolaege,
7 * Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
14 #include <isl/ast_build.h>
15 #include <isl/printer.h>
20 __isl_give isl_printer
*ppcg_start_block(__isl_take isl_printer
*p
)
22 p
= isl_printer_start_line(p
);
23 p
= isl_printer_print_str(p
, "{");
24 p
= isl_printer_end_line(p
);
25 p
= isl_printer_indent(p
, 2);
29 __isl_give isl_printer
*ppcg_end_block(__isl_take isl_printer
*p
)
31 p
= isl_printer_indent(p
, -2);
32 p
= isl_printer_start_line(p
);
33 p
= isl_printer_print_str(p
, "}");
34 p
= isl_printer_end_line(p
);
38 /* Names of notes that keep track of whether min/max
39 * macro definitions have already been printed.
41 static const char *ppcg_max_printed
= "ppcg_max_printed";
42 static const char *ppcg_min_printed
= "ppcg_min_printed";
44 /* Has the macro definition corresponding to "note_name" been printed
46 * That is, does "p" have an associated "note_name" note?
48 static isl_bool
printed_before(__isl_keep isl_printer
*p
, const char *note_name
)
55 return isl_bool_error
;
57 ctx
= isl_printer_get_ctx(p
);
58 id
= isl_id_alloc(ctx
, note_name
, NULL
);
59 printed
= isl_printer_has_note(p
, id
);
65 /* Keep track of the fact that the macro definition corresponding
66 * to "note_name" has been printed to "p" by attaching a note with
67 * that name. The value of the note is of no importance, but it
68 * has to be a valid isl_id, so the note identifier is reused
71 static __isl_give isl_printer
*mark_printed(__isl_take isl_printer
*p
,
72 const char *note_name
)
80 ctx
= isl_printer_get_ctx(p
);
81 id
= isl_id_alloc(ctx
, note_name
, NULL
);
82 return isl_printer_set_note(p
, id
, isl_id_copy(id
));
85 /* Print a macro definition "def" for the macro "name" to "p",
86 * unless such a macro definition has been printed to "p" before.
87 * "note_name" is used as the name of the note that keeps track
88 * of whether this printing has happened.
90 static __isl_give isl_printer
*print_ppcg_macro(__isl_take isl_printer
*p
,
91 const char *name
, const char *def
, const char *note_name
)
95 printed
= printed_before(p
, note_name
);
97 return isl_printer_free(p
);
101 p
= isl_printer_start_line(p
);
102 p
= isl_printer_print_str(p
, "#define ");
103 p
= isl_printer_print_str(p
, name
);
104 p
= isl_printer_print_str(p
, def
);
105 p
= isl_printer_end_line(p
);
107 p
= mark_printed(p
, note_name
);
112 /* Structure for keeping track of definitions of some macros.
119 /* Free the memory allocated by a struct ppcg_macros.
121 static void ppcg_macros_free(void *user
)
126 /* Default macro definitions (when GNU extensions are allowed).
128 struct ppcg_macros ppcg_macros_default
= {
130 "({ __typeof__(x) _x = (x); __typeof__(y) _y = (y); "
131 "_x < _y ? _x : _y; })",
133 "({ __typeof__(x) _x = (x); __typeof__(y) _y = (y); "
134 "_x > _y ? _x : _y; })",
137 /* Name used for the note that keeps track of macro definitions.
139 static const char *ppcg_macros
= "ppcg_macros";
141 /* Set the macro definitions for isl_ast_op_min and isl_ast_op_max
142 * to "min" and "max" and store them in "p".
144 * In particular, create a ppcg_macros object and attach it
145 * as a note to the printer.
147 __isl_give isl_printer
*ppcg_set_macros(__isl_take isl_printer
*p
,
148 const char *min
, const char *max
)
151 isl_id
*id
, *macros_id
;
152 struct ppcg_macros
*macros
;
157 ctx
= isl_printer_get_ctx(p
);
158 macros
= isl_alloc_type(ctx
, struct ppcg_macros
);
160 return isl_printer_free(p
);
163 id
= isl_id_alloc(ctx
, ppcg_macros
, NULL
);
164 macros_id
= isl_id_alloc(ctx
, NULL
, macros
);
166 ppcg_macros_free(macros
);
168 macros_id
= isl_id_set_free_user(macros_id
, &ppcg_macros_free
);
170 p
= isl_printer_set_note(p
, id
, macros_id
);
175 /* Return the ppcg_macros object that holds the currently active
176 * macro definitions in "p".
177 * If "p" has a note with macro definitions, then return those.
178 * Otherwise, return the default macro definitions.
180 static struct ppcg_macros
*get_macros(__isl_keep isl_printer
*p
)
184 struct ppcg_macros
*macros
;
186 id
= isl_id_alloc(isl_printer_get_ctx(p
), ppcg_macros
, NULL
);
187 has_macros
= isl_printer_has_note(p
, id
);
188 if (has_macros
< 0 || !has_macros
) {
192 return &ppcg_macros_default
;
194 id
= isl_printer_get_note(p
, id
);
195 macros
= isl_id_get_user(id
);
201 /* Print the currently active macro definition for ppcg_max.
203 static __isl_give isl_printer
*print_max(__isl_take isl_printer
*p
)
205 struct ppcg_macros
*macros
;
207 macros
= get_macros(p
);
209 return isl_printer_free(p
);
210 return print_ppcg_macro(p
, ppcg_max
, macros
->max
, ppcg_max_printed
);
213 /* Print the currently active macro definition for ppcg_min.
215 static __isl_give isl_printer
*print_min(__isl_take isl_printer
*p
)
217 struct ppcg_macros
*macros
;
219 macros
= get_macros(p
);
221 return isl_printer_free(p
);
222 return print_ppcg_macro(p
, ppcg_min
, macros
->min
, ppcg_min_printed
);
225 /* Print a macro definition for "type" to "p".
226 * If GNU extensions are allowed, then print a specialized definition
227 * for isl_ast_op_min and isl_ast_op_max.
228 * Otherwise, use the default isl definition.
230 __isl_give isl_printer
*ppcg_print_macro(enum isl_ast_op_type type
,
231 __isl_take isl_printer
*p
)
234 struct ppcg_options
*options
;
239 ctx
= isl_printer_get_ctx(p
);
240 options
= isl_ctx_peek_options(ctx
, &ppcg_options_args
);
241 if (!options
|| !options
->allow_gnu_extensions
)
242 return isl_ast_op_type_print_macro(type
, p
);
250 return isl_ast_op_type_print_macro(type
, p
);
254 /* isl_ast_expr_foreach_ast_op_type or isl_ast_node_foreach_ast_op_type
255 * callback that prints a macro definition for "type".
257 static isl_stat
print_macro(enum isl_ast_op_type type
, void *user
)
259 isl_printer
**p
= user
;
261 *p
= ppcg_print_macro(type
, *p
);
263 return isl_stat_error
;
268 /* Print the required macros for "expr".
270 __isl_give isl_printer
*ppcg_ast_expr_print_macros(
271 __isl_keep isl_ast_expr
*expr
, __isl_take isl_printer
*p
)
273 if (isl_ast_expr_foreach_ast_op_type(expr
, &print_macro
, &p
) < 0)
274 return isl_printer_free(p
);
278 /* isl_id_to_ast_expr_foreach callback that prints the required
279 * macro definitions for "val".
281 static isl_stat
print_expr_macros(__isl_take isl_id
*key
,
282 __isl_take isl_ast_expr
*val
, void *user
)
284 isl_printer
**p
= user
;
286 *p
= ppcg_ast_expr_print_macros(val
, *p
);
288 isl_ast_expr_free(val
);
291 return isl_stat_error
;
295 /* Print the required macro definitions for the body of a statement in which
296 * the access expressions are replaced by the isl_ast_expr objects
299 __isl_give isl_printer
*ppcg_print_body_macros(__isl_take isl_printer
*p
,
300 __isl_keep isl_id_to_ast_expr
*ref2expr
)
302 if (isl_id_to_ast_expr_foreach(ref2expr
, &print_expr_macros
, &p
) < 0)
303 return isl_printer_free(p
);
307 /* Print the required macros for "node".
309 __isl_give isl_printer
*ppcg_print_macros(__isl_take isl_printer
*p
,
310 __isl_keep isl_ast_node
*node
)
312 if (isl_ast_node_foreach_ast_op_type(node
, &print_macro
, &p
) < 0)
313 return isl_printer_free(p
);
317 /* Names used for the macros that may appear in a printed isl AST.
319 const char *ppcg_min
= "ppcg_min";
320 const char *ppcg_max
= "ppcg_max";
321 const char *ppcg_fdiv_q
= "ppcg_fdiv_q";
323 /* Set the names of the macros that may appear in a printed isl AST.
325 __isl_give isl_printer
*ppcg_set_macro_names(__isl_take isl_printer
*p
)
327 p
= isl_ast_op_type_set_print_name(p
, isl_ast_op_min
, ppcg_min
);
328 p
= isl_ast_op_type_set_print_name(p
, isl_ast_op_max
, ppcg_max
);
329 p
= isl_ast_op_type_set_print_name(p
, isl_ast_op_fdiv_q
, ppcg_fdiv_q
);
334 /* Given a multi affine expression "mpa" without domain, modify it to have
335 * the schedule space of "build" as domain.
337 * If the schedule space of "build" is a parameter space, then nothing
339 * Otherwise, "mpa" is first given a 0D domain and then it is combined
340 * with a mapping from the schedule space of "build" to the same 0D domain.
342 __isl_give isl_multi_pw_aff
*ppcg_attach_multi_pw_aff(
343 __isl_take isl_multi_pw_aff
*mpa
, __isl_keep isl_ast_build
*build
)
349 space
= isl_ast_build_get_schedule_space(build
);
350 params
= isl_space_is_params(space
);
351 if (params
< 0 || params
) {
352 isl_space_free(space
);
354 return isl_multi_pw_aff_free(mpa
);
357 space
= isl_space_from_domain(space
);
358 ma
= isl_multi_aff_zero(space
);
359 mpa
= isl_multi_pw_aff_from_range(mpa
);
360 mpa
= isl_multi_pw_aff_pullback_multi_aff(mpa
, ma
);
365 /* Build an access AST expression from "size" using "build".
366 * "size" does not have a domain, but "build" may have a proper schedule space.
367 * First modify "size" to have that schedule space as domain.
369 __isl_give isl_ast_expr
*ppcg_build_size_expr(__isl_take isl_multi_pw_aff
*size
,
370 __isl_keep isl_ast_build
*build
)
372 size
= ppcg_attach_multi_pw_aff(size
, build
);
373 return isl_ast_build_access_from_multi_pw_aff(build
, size
);
376 /* Print a declaration for an array with element type "base_type" and
377 * size "size" to "p".
379 __isl_give isl_printer
*ppcg_print_declaration_with_size(
380 __isl_take isl_printer
*p
, const char *base_type
,
381 __isl_keep isl_ast_expr
*size
)
383 if (!base_type
|| !size
)
384 return isl_printer_free(p
);
386 p
= ppcg_ast_expr_print_macros(size
, p
);
387 p
= isl_printer_start_line(p
);
388 p
= isl_printer_print_str(p
, base_type
);
389 p
= isl_printer_print_str(p
, " ");
390 p
= isl_printer_print_ast_expr(p
, size
);
391 p
= isl_printer_print_str(p
, ";");
392 p
= isl_printer_end_line(p
);
397 /* Print a declaration for array "array" to "p", using "build"
398 * to simplify any size expressions.
400 * The size is computed from the extent of the array and is
401 * subsequently converted to an "access expression" by "build".
403 __isl_give isl_printer
*ppcg_print_declaration(__isl_take isl_printer
*p
,
404 struct pet_array
*array
, __isl_keep isl_ast_build
*build
)
406 isl_multi_pw_aff
*size
;
410 return isl_printer_free(p
);
412 size
= ppcg_size_from_extent(isl_set_copy(array
->extent
));
413 expr
= isl_ast_build_access_from_multi_pw_aff(build
, size
);
414 p
= ppcg_print_declaration_with_size(p
, array
->element_type
, expr
);
415 isl_ast_expr_free(expr
);
420 /* Print declarations for the arrays in "scop" that are declared
421 * and that are exposed (if exposed == 1) or not exposed (if exposed == 0).
423 static __isl_give isl_printer
*print_declarations(__isl_take isl_printer
*p
,
424 struct ppcg_scop
*scop
, int exposed
)
427 isl_ast_build
*build
;
430 return isl_printer_free(p
);
432 build
= isl_ast_build_from_context(isl_set_copy(scop
->context
));
433 for (i
= 0; i
< scop
->pet
->n_array
; ++i
) {
434 struct pet_array
*array
= scop
->pet
->arrays
[i
];
436 if (!array
->declared
)
438 if (array
->exposed
!= exposed
)
441 p
= ppcg_print_declaration(p
, array
, build
);
443 isl_ast_build_free(build
);
448 /* Print declarations for the arrays in "scop" that are declared
449 * and exposed to the code after the scop.
451 __isl_give isl_printer
*ppcg_print_exposed_declarations(
452 __isl_take isl_printer
*p
, struct ppcg_scop
*scop
)
454 return print_declarations(p
, scop
, 1);
457 /* Print declarations for the arrays in "scop" that are declared,
458 * but not exposed to the code after the scop.
460 __isl_give isl_printer
*ppcg_print_hidden_declarations(
461 __isl_take isl_printer
*p
, struct ppcg_scop
*scop
)
463 return print_declarations(p
, scop
, 0);