gpu_array_is_scalar: also consider a single struct as a scalar
[ppcg.git] / print.c
blob688153722ec0ce6bab8a418517fbf39431685f69
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"
15 __isl_give isl_printer *ppcg_start_block(__isl_take isl_printer *p)
17 p = isl_printer_start_line(p);
18 p = isl_printer_print_str(p, "{");
19 p = isl_printer_end_line(p);
20 p = isl_printer_indent(p, 2);
21 return p;
24 __isl_give isl_printer *ppcg_end_block(__isl_take isl_printer *p)
26 p = isl_printer_indent(p, -2);
27 p = isl_printer_start_line(p);
28 p = isl_printer_print_str(p, "}");
29 p = isl_printer_end_line(p);
30 return p;
33 /* Print "extent" as a sequence of
35 * [1 + maximal_value]
37 * one for each dimension.
39 static __isl_give isl_printer *print_extent(__isl_take isl_printer *p,
40 __isl_keep isl_set *extent)
42 int i, n;
44 n = isl_set_dim(extent, isl_dim_set);
45 if (n == 0)
46 return p;
48 for (i = 0; i < n; ++i) {
49 isl_set *dom;
50 isl_local_space *ls;
51 isl_aff *one;
52 isl_pw_aff *bound;
54 bound = isl_set_dim_max(isl_set_copy(extent), i);
55 dom = isl_pw_aff_domain(isl_pw_aff_copy(bound));
56 ls = isl_local_space_from_space(isl_set_get_space(dom));
57 one = isl_aff_zero_on_domain(ls);
58 one = isl_aff_add_constant_si(one, 1);
59 bound = isl_pw_aff_add(bound, isl_pw_aff_alloc(dom, one));
61 p = isl_printer_print_str(p, "[");
62 p = isl_printer_print_pw_aff(p, bound);
63 p = isl_printer_print_str(p, "]");
65 isl_pw_aff_free(bound);
68 return p;
71 /* Print declarations for the arrays in "scop" that are declared
72 * and that are exposed (if exposed == 1) or not exposed (if exposed == 0).
74 static __isl_give isl_printer *print_declarations(__isl_take isl_printer *p,
75 struct ppcg_scop *scop, int exposed)
77 int i;
79 if (!scop)
80 return isl_printer_free(p);
82 for (i = 0; i < scop->pet->n_array; ++i) {
83 struct pet_array *array = scop->pet->arrays[i];
84 const char *name;
86 if (!array->declared)
87 continue;
88 if (array->exposed != exposed)
89 continue;
91 name = isl_set_get_tuple_name(array->extent);
93 p = isl_printer_start_line(p);
94 p = isl_printer_print_str(p, array->element_type);
95 p = isl_printer_print_str(p, " ");
96 p = isl_printer_print_str(p, name);
97 p = print_extent(p, array->extent);
98 p = isl_printer_print_str(p, ";");
99 p = isl_printer_end_line(p);
102 return p;
105 /* Print declarations for the arrays in "scop" that are declared
106 * and exposed to the code after the scop.
108 __isl_give isl_printer *ppcg_print_exposed_declarations(
109 __isl_take isl_printer *p, struct ppcg_scop *scop)
111 return print_declarations(p, scop, 1);
114 /* Print declarations for the arrays in "scop" that are declared,
115 * but not exposed to the code after the scop.
117 __isl_give isl_printer *ppcg_print_hidden_declarations(
118 __isl_take isl_printer *p, struct ppcg_scop *scop)
120 return print_declarations(p, scop, 0);
123 /* Internal data structure for print_guarded_user.
125 * fn is the function that should be called to print the body.
126 * user is the argument that should be passed to this function.
128 struct ppcg_print_guarded_data {
129 __isl_give isl_printer *(*fn)(__isl_take isl_printer *p, void *user);
130 void *user;
133 /* Print the body of the if statement expressing the guard passed
134 * to "ppcg_print_guarded" by calling data->fn.
136 static __isl_give isl_printer *print_guarded_user(__isl_take isl_printer *p,
137 __isl_take isl_ast_print_options *options,
138 __isl_keep isl_ast_node *node, void *user)
140 struct ppcg_print_guarded_data *data = user;
142 p = data->fn(p, data->user);
144 isl_ast_print_options_free(options);
145 return p;
148 /* Print a condition for the given "guard" within the given "context"
149 * on "p", calling "fn" with "user" to print the body of the if statement.
150 * If the guard is implied by the context, then no if statement is printed
151 * and the body is printed directly to "p".
153 * Both "guard" and "context" are assumed to be parameter sets.
155 * We slightly abuse the AST generator to print this guard.
156 * In particular, we create a trivial schedule for an iteration
157 * domain with a single instance, restriced by the guard.
159 __isl_give isl_printer *ppcg_print_guarded(__isl_take isl_printer *p,
160 __isl_take isl_set *guard, __isl_take isl_set *context,
161 __isl_give isl_printer *(*fn)(__isl_take isl_printer *p, void *user),
162 void *user)
164 struct ppcg_print_guarded_data data = { fn, user };
165 isl_ctx *ctx;
166 isl_union_map *schedule;
167 isl_ast_build *build;
168 isl_ast_node *tree;
169 isl_ast_print_options *options;
171 ctx = isl_printer_get_ctx(p);
172 guard = isl_set_from_params(guard);
173 schedule = isl_union_map_from_map(isl_map_from_domain(guard));
174 build = isl_ast_build_from_context(context);
175 tree = isl_ast_build_ast_from_schedule(build, schedule);
176 isl_ast_build_free(build);
178 options = isl_ast_print_options_alloc(ctx);
179 options = isl_ast_print_options_set_print_user(options,
180 &print_guarded_user, &data);
181 p = isl_ast_node_print(tree, p, options);
182 isl_ast_node_free(tree);
184 return p;