update isl to version 0.17.1
[ppcg.git] / print.c
blob79aaf2b00d237f3abf52afe8127591163abb1970
1 /*
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
8 */
10 #include <isl/aff.h>
11 #include <isl/ast_build.h>
13 #include "print.h"
14 #include "util.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);
22 return p;
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);
31 return 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
41 * to "p" before?
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)
46 isl_ctx *ctx;
47 isl_id *id;
48 isl_bool printed;
50 if (!p)
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);
56 isl_id_free(id);
58 return printed;
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
65 * as the note.
67 static __isl_give isl_printer *mark_printed(__isl_take isl_printer *p,
68 const char *note_name)
70 isl_ctx *ctx;
71 isl_id *id;
73 if (!p)
74 return NULL;
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)
89 isl_bool printed;
91 printed = printed_before(p, note_name);
92 if (printed < 0)
93 return isl_printer_free(p);
94 if (printed)
95 return 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);
105 return p;
108 /* Structure for keeping track of definitions of some macros.
110 struct ppcg_macros {
111 const char *min;
112 const char *max;
115 /* Free the memory allocated by a struct ppcg_macros.
117 static void ppcg_macros_free(void *user)
119 free(user);
122 /* Default macro definitions (when GNU extensions are allowed).
124 struct ppcg_macros ppcg_macros_default = {
125 .min = "(x,y) "
126 "({ __typeof__(x) _x = (x); __typeof__(y) _y = (y); "
127 "_x < _y ? _x : _y; })",
128 .max = "(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)
146 isl_ctx *ctx;
147 isl_id *id, *macros_id;
148 struct ppcg_macros *macros;
150 if (!p)
151 return NULL;
153 ctx = isl_printer_get_ctx(p);
154 macros = isl_alloc_type(ctx, struct ppcg_macros);
155 if (!macros)
156 return isl_printer_free(p);
157 macros->min = min;
158 macros->max = max;
159 id = isl_id_alloc(ctx, ppcg_macros, NULL);
160 macros_id = isl_id_alloc(ctx, NULL, macros);
161 if (!macros_id)
162 ppcg_macros_free(macros);
163 else
164 macros_id = isl_id_set_free_user(macros_id, &ppcg_macros_free);
166 p = isl_printer_set_note(p, id, macros_id);
168 return p;
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)
178 isl_id *id;
179 isl_bool has_macros;
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) {
185 isl_id_free(id);
186 if (has_macros < 0)
187 return NULL;
188 return &ppcg_macros_default;
190 id = isl_printer_get_note(p, id);
191 macros = isl_id_get_user(id);
192 isl_id_free(id);
194 return macros;
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);
204 if (!macros)
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);
216 if (!macros)
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)
229 isl_ctx *ctx;
230 struct ppcg_options *options;
232 if (!p)
233 return NULL;
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);
240 switch (type) {
241 case isl_ast_op_max:
242 return print_max(p);
243 case isl_ast_op_min:
244 return print_min(p);
245 default:
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);
258 if (!*p)
259 return isl_stat_error;
261 return isl_stat_ok;
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);
271 return 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);
283 isl_id_free(key);
284 isl_ast_expr_free(val);
286 if (!*p)
287 return isl_stat_error;
288 return isl_stat_ok;
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
293 * in "ref2expr".
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);
300 return 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);
310 return 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);
327 return p;
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
334 * needs to be done.
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)
341 isl_bool params;
342 isl_space *space;
343 isl_multi_aff *ma;
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);
349 if (params < 0)
350 return isl_multi_pw_aff_free(mpa);
351 return 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);
358 return mpa;
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);
390 return 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;
403 isl_ast_expr *expr;
405 if (!array)
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);
413 return p;
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)
422 int i;
423 isl_ast_build *build;
425 if (!scop)
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)
433 continue;
434 if (array->exposed != exposed)
435 continue;
437 p = ppcg_print_declaration(p, array, build);
439 isl_ast_build_free(build);
441 return p;
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);