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
11 #include <isl/ast_build.h>
16 __isl_give isl_printer
*ppcg_start_block(__isl_take isl_printer
*p
)
18 p
= isl_printer_start_line(p
);
19 p
= isl_printer_print_str(p
, "{");
20 p
= isl_printer_end_line(p
);
21 p
= isl_printer_indent(p
, 2);
25 __isl_give isl_printer
*ppcg_end_block(__isl_take isl_printer
*p
)
27 p
= isl_printer_indent(p
, -2);
28 p
= isl_printer_start_line(p
);
29 p
= isl_printer_print_str(p
, "}");
30 p
= isl_printer_end_line(p
);
34 /* Names of notes that keep track of whether min/max
35 * macro definitions have already been printed.
37 static const char *ppcg_max_printed
= "ppcg_max_printed";
38 static const char *ppcg_min_printed
= "ppcg_min_printed";
40 /* Has the macro definition corresponding to "note_name" been printed
42 * That is, does "p" have an associated "note_name" note?
44 static isl_bool
printed_before(__isl_keep isl_printer
*p
, const char *note_name
)
51 return isl_bool_error
;
53 ctx
= isl_printer_get_ctx(p
);
54 id
= isl_id_alloc(ctx
, note_name
, NULL
);
55 printed
= isl_printer_has_note(p
, id
);
61 /* Keep track of the fact that the macro definition corresponding
62 * to "note_name" has been printed to "p" by attaching a note with
63 * that name. The value of the note is of no importance, but it
64 * has to be a valid isl_id, so the note identifier is reused
67 static __isl_give isl_printer
*mark_printed(__isl_take isl_printer
*p
,
68 const char *note_name
)
76 ctx
= isl_printer_get_ctx(p
);
77 id
= isl_id_alloc(ctx
, note_name
, NULL
);
78 return isl_printer_set_note(p
, id
, isl_id_copy(id
));
81 /* Print a macro definition "def" for the macro "name" to "p",
82 * unless such a macro definition has been printed to "p" before.
83 * "note_name" is used as the name of the note that keeps track
84 * of whether this printing has happened.
86 static __isl_give isl_printer
*print_ppcg_macro(__isl_take isl_printer
*p
,
87 const char *name
, const char *def
, const char *note_name
)
91 printed
= printed_before(p
, note_name
);
93 return isl_printer_free(p
);
97 p
= isl_printer_start_line(p
);
98 p
= isl_printer_print_str(p
, "#define ");
99 p
= isl_printer_print_str(p
, name
);
100 p
= isl_printer_print_str(p
, def
);
101 p
= isl_printer_end_line(p
);
103 p
= mark_printed(p
, note_name
);
108 /* Structure for keeping track of definitions of some macros.
115 /* Free the memory allocated by a struct ppcg_macros.
117 static void ppcg_macros_free(void *user
)
122 /* Default macro definitions (when GNU extensions are allowed).
124 struct ppcg_macros ppcg_macros_default
= {
126 "({ __typeof__(x) _x = (x); __typeof__(y) _y = (y); "
127 "_x < _y ? _x : _y; })",
129 "({ __typeof__(x) _x = (x); __typeof__(y) _y = (y); "
130 "_x > _y ? _x : _y; })",
133 /* Name used for the note that keeps track of macro definitions.
135 static const char *ppcg_macros
= "ppcg_macros";
137 /* Set the macro definitions for isl_ast_op_min and isl_ast_op_max
138 * to "min" and "max" and store them in "p".
140 * In particular, create a ppcg_macros object and attach it
141 * as a note to the printer.
143 __isl_give isl_printer
*ppcg_set_macros(__isl_take isl_printer
*p
,
144 const char *min
, const char *max
)
147 isl_id
*id
, *macros_id
;
148 struct ppcg_macros
*macros
;
153 ctx
= isl_printer_get_ctx(p
);
154 macros
= isl_alloc_type(ctx
, struct ppcg_macros
);
156 return isl_printer_free(p
);
159 id
= isl_id_alloc(ctx
, ppcg_macros
, NULL
);
160 macros_id
= isl_id_alloc(ctx
, NULL
, macros
);
162 ppcg_macros_free(macros
);
164 macros_id
= isl_id_set_free_user(macros_id
, &ppcg_macros_free
);
166 p
= isl_printer_set_note(p
, id
, macros_id
);
171 /* Return the ppcg_macros object that holds the currently active
172 * macro definitions in "p".
173 * If "p" has a note with macro definitions, then return those.
174 * Otherwise, return the default macro definitions.
176 static struct ppcg_macros
*get_macros(__isl_keep isl_printer
*p
)
180 struct ppcg_macros
*macros
;
182 id
= isl_id_alloc(isl_printer_get_ctx(p
), ppcg_macros
, NULL
);
183 has_macros
= isl_printer_has_note(p
, id
);
184 if (has_macros
< 0 || !has_macros
) {
188 return &ppcg_macros_default
;
190 id
= isl_printer_get_note(p
, id
);
191 macros
= isl_id_get_user(id
);
197 /* Print the currently active macro definition for ppcg_max.
199 static __isl_give isl_printer
*print_max(__isl_take isl_printer
*p
)
201 struct ppcg_macros
*macros
;
203 macros
= get_macros(p
);
205 return isl_printer_free(p
);
206 return print_ppcg_macro(p
, ppcg_max
, macros
->max
, ppcg_max_printed
);
209 /* Print the currently active macro definition for ppcg_min.
211 static __isl_give isl_printer
*print_min(__isl_take isl_printer
*p
)
213 struct ppcg_macros
*macros
;
215 macros
= get_macros(p
);
217 return isl_printer_free(p
);
218 return print_ppcg_macro(p
, ppcg_min
, macros
->min
, ppcg_min_printed
);
221 /* Print a macro definition for "type" to "p".
222 * If GNU extensions are allowed, then print a specialized definition
223 * for isl_ast_op_min and isl_ast_op_max.
224 * Otherwise, use the default isl definition.
226 __isl_give isl_printer
*ppcg_print_macro(enum isl_ast_op_type type
,
227 __isl_take isl_printer
*p
)
230 struct ppcg_options
*options
;
235 ctx
= isl_printer_get_ctx(p
);
236 options
= isl_ctx_peek_options(ctx
, &ppcg_options_args
);
237 if (!options
|| !options
->allow_gnu_extensions
)
238 return isl_ast_op_type_print_macro(type
, p
);
246 return isl_ast_op_type_print_macro(type
, p
);
250 /* isl_ast_expr_foreach_ast_op_type or isl_ast_node_foreach_ast_op_type
251 * callback that prints a macro definition for "type".
253 static isl_stat
print_macro(enum isl_ast_op_type type
, void *user
)
255 isl_printer
**p
= user
;
257 *p
= ppcg_print_macro(type
, *p
);
259 return isl_stat_error
;
264 /* Print the required macros for "expr".
266 __isl_give isl_printer
*ppcg_ast_expr_print_macros(
267 __isl_keep isl_ast_expr
*expr
, __isl_take isl_printer
*p
)
269 if (isl_ast_expr_foreach_ast_op_type(expr
, &print_macro
, &p
) < 0)
270 return isl_printer_free(p
);
274 /* isl_id_to_ast_expr_foreach callback that prints the required
275 * macro definitions for "val".
277 static isl_stat
print_expr_macros(__isl_take isl_id
*key
,
278 __isl_take isl_ast_expr
*val
, void *user
)
280 isl_printer
**p
= user
;
282 *p
= ppcg_ast_expr_print_macros(val
, *p
);
284 isl_ast_expr_free(val
);
287 return isl_stat_error
;
291 /* Print the required macro definitions for the body of a statement in which
292 * the access expressions are replaced by the isl_ast_expr objects
295 __isl_give isl_printer
*ppcg_print_body_macros(__isl_take isl_printer
*p
,
296 __isl_keep isl_id_to_ast_expr
*ref2expr
)
298 if (isl_id_to_ast_expr_foreach(ref2expr
, &print_expr_macros
, &p
) < 0)
299 return isl_printer_free(p
);
303 /* Print the required macros for "node".
305 __isl_give isl_printer
*ppcg_print_macros(__isl_take isl_printer
*p
,
306 __isl_keep isl_ast_node
*node
)
308 if (isl_ast_node_foreach_ast_op_type(node
, &print_macro
, &p
) < 0)
309 return isl_printer_free(p
);
313 /* Names used for the macros that may appear in a printed isl AST.
315 const char *ppcg_min
= "ppcg_min";
316 const char *ppcg_max
= "ppcg_max";
317 const char *ppcg_fdiv_q
= "ppcg_fdiv_q";
319 /* Set the names of the macros that may appear in a printed isl AST.
321 __isl_give isl_printer
*ppcg_set_macro_names(__isl_take isl_printer
*p
)
323 p
= isl_ast_op_type_set_print_name(p
, isl_ast_op_min
, ppcg_min
);
324 p
= isl_ast_op_type_set_print_name(p
, isl_ast_op_max
, ppcg_max
);
325 p
= isl_ast_op_type_set_print_name(p
, isl_ast_op_fdiv_q
, ppcg_fdiv_q
);
330 /* Given a multi affine expression "mpa" without domain, modify it to have
331 * the schedule space of "build" as domain.
333 * If the schedule space of "build" is a parameter space, then nothing
335 * Otherwise, "mpa" is first given a 0D domain and then it is combined
336 * with a mapping from the schedule space of "build" to the same 0D domain.
338 __isl_give isl_multi_pw_aff
*ppcg_attach_multi_pw_aff(
339 __isl_take isl_multi_pw_aff
*mpa
, __isl_keep isl_ast_build
*build
)
345 space
= isl_ast_build_get_schedule_space(build
);
346 params
= isl_space_is_params(space
);
347 if (params
< 0 || params
) {
348 isl_space_free(space
);
350 return isl_multi_pw_aff_free(mpa
);
353 space
= isl_space_from_domain(space
);
354 ma
= isl_multi_aff_zero(space
);
355 mpa
= isl_multi_pw_aff_from_range(mpa
);
356 mpa
= isl_multi_pw_aff_pullback_multi_aff(mpa
, ma
);
361 /* Build an access AST expression from "size" using "build".
362 * "size" does not have a domain, but "build" may have a proper schedule space.
363 * First modify "size" to have that schedule space as domain.
365 __isl_give isl_ast_expr
*ppcg_build_size_expr(__isl_take isl_multi_pw_aff
*size
,
366 __isl_keep isl_ast_build
*build
)
368 size
= ppcg_attach_multi_pw_aff(size
, build
);
369 return isl_ast_build_access_from_multi_pw_aff(build
, size
);
372 /* Print a declaration for an array with element type "base_type" and
373 * size "size" to "p".
375 __isl_give isl_printer
*ppcg_print_declaration_with_size(
376 __isl_take isl_printer
*p
, const char *base_type
,
377 __isl_keep isl_ast_expr
*size
)
379 if (!base_type
|| !size
)
380 return isl_printer_free(p
);
382 p
= ppcg_ast_expr_print_macros(size
, p
);
383 p
= isl_printer_start_line(p
);
384 p
= isl_printer_print_str(p
, base_type
);
385 p
= isl_printer_print_str(p
, " ");
386 p
= isl_printer_print_ast_expr(p
, size
);
387 p
= isl_printer_print_str(p
, ";");
388 p
= isl_printer_end_line(p
);
393 /* Print a declaration for array "array" to "p", using "build"
394 * to simplify any size expressions.
396 * The size is computed from the extent of the array and is
397 * subsequently converted to an "access expression" by "build".
399 __isl_give isl_printer
*ppcg_print_declaration(__isl_take isl_printer
*p
,
400 struct pet_array
*array
, __isl_keep isl_ast_build
*build
)
402 isl_multi_pw_aff
*size
;
406 return isl_printer_free(p
);
408 size
= ppcg_size_from_extent(isl_set_copy(array
->extent
));
409 expr
= isl_ast_build_access_from_multi_pw_aff(build
, size
);
410 p
= ppcg_print_declaration_with_size(p
, array
->element_type
, expr
);
411 isl_ast_expr_free(expr
);
416 /* Print declarations for the arrays in "scop" that are declared
417 * and that are exposed (if exposed == 1) or not exposed (if exposed == 0).
419 static __isl_give isl_printer
*print_declarations(__isl_take isl_printer
*p
,
420 struct ppcg_scop
*scop
, int exposed
)
423 isl_ast_build
*build
;
426 return isl_printer_free(p
);
428 build
= isl_ast_build_from_context(isl_set_copy(scop
->context
));
429 for (i
= 0; i
< scop
->pet
->n_array
; ++i
) {
430 struct pet_array
*array
= scop
->pet
->arrays
[i
];
432 if (!array
->declared
)
434 if (array
->exposed
!= exposed
)
437 p
= ppcg_print_declaration(p
, array
, build
);
439 isl_ast_build_free(build
);
444 /* Print declarations for the arrays in "scop" that are declared
445 * and exposed to the code after the scop.
447 __isl_give isl_printer
*ppcg_print_exposed_declarations(
448 __isl_take isl_printer
*p
, struct ppcg_scop
*scop
)
450 return print_declarations(p
, scop
, 1);
453 /* Print declarations for the arrays in "scop" that are declared,
454 * but not exposed to the code after the scop.
456 __isl_give isl_printer
*ppcg_print_hidden_declarations(
457 __isl_take isl_printer
*p
, struct ppcg_scop
*scop
)
459 return print_declarations(p
, scop
, 0);