expr.c: extract_affine_mul: abort on error rather than treating it as non-affine
[pet.git] / pet_codegen.c
blob30f58ab195f63a0dd086cf29b1e71ff31da5c436
1 /*
2 * Copyright 2012 Ecole Normale Superieure. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following
13 * disclaimer in the documentation and/or other materials provided
14 * with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY ECOLE NORMALE SUPERIEURE ''AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECOLE NORMALE SUPERIEURE OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
23 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 * The views and conclusions contained in the software and documentation
29 * are those of the authors and should not be interpreted as
30 * representing official policies, either expressed or implied, of
31 * Ecole Normale Superieure.
34 #include <assert.h>
35 #include <isl/aff.h>
36 #include <isl/ast_build.h>
37 #include <isl/options.h>
38 #include <isl/set.h>
39 #include <isl/map.h>
41 struct options {
42 struct isl_options *isl;
43 unsigned atomic;
44 unsigned separate;
45 unsigned read_options;
48 ISL_ARGS_START(struct options, options_args)
49 ISL_ARG_CHILD(struct options, isl, "isl", &isl_options_args, "isl options")
50 ISL_ARG_BOOL(struct options, atomic, 0, "atomic", 0,
51 "globally set the atomic option")
52 ISL_ARG_BOOL(struct options, separate, 0, "separate", 0,
53 "globally set the separate option")
54 ISL_ARG_BOOL(struct options, read_options, 0, "read-options", 0,
55 "read options from standard input")
56 ISL_ARGS_END
58 ISL_ARG_DEF(options, struct options, options_args)
60 /* Return a universal, 1-dimensional set with the given name.
62 static __isl_give isl_union_set *universe(isl_ctx *ctx, const char *name)
64 isl_space *space;
66 space = isl_space_set_alloc(ctx, 0, 1);
67 space = isl_space_set_tuple_name(space, isl_dim_set, name);
68 return isl_union_set_from_set(isl_set_universe(space));
71 /* Set the "name" option for the entire schedule domain.
73 static __isl_give isl_union_map *set_universe(__isl_take isl_union_map *opt,
74 __isl_keep isl_union_map *schedule, const char *name)
76 isl_ctx *ctx;
77 isl_union_set *domain, *target;
78 isl_union_map *option;
80 ctx = isl_union_map_get_ctx(opt);
82 domain = isl_union_map_range(isl_union_map_copy(schedule));
83 domain = isl_union_set_universe(domain);
84 target = universe(ctx, name);
85 option = isl_union_map_from_domain_and_range(domain, target);
86 opt = isl_union_map_union(opt, option);
88 return opt;
91 /* Set the build options based on the command line options.
93 * If no command line options are specified, we use default build options.
94 * If --read-options is specified, we read the build options from standard
95 * input.
96 * If --separate or --atomic is specified, we turn on the corresponding
97 * build option over the entire schedule domain.
99 static __isl_give isl_ast_build *set_options(__isl_take isl_ast_build *build,
100 struct options *options, __isl_keep isl_union_map *schedule)
102 isl_ctx *ctx;
103 isl_space *space;
104 isl_union_set *domain, *separate;
105 isl_union_map *opt, *opt_s, *opt_a;
107 if (!options->separate && !options->atomic && !options->read_options)
108 return build;
110 ctx = isl_union_map_get_ctx(schedule);
112 if (options->read_options)
113 opt = isl_union_map_read_from_file(ctx, stdin);
114 else
115 opt = isl_union_map_empty(isl_union_map_get_space(schedule));
117 if (options->separate)
118 opt = set_universe(opt, schedule, "separate");
119 if (options->atomic)
120 opt = set_universe(opt, schedule, "atomic");
122 build = isl_ast_build_set_options(build, opt);
124 return build;
127 /* Print a function declaration for the domain "set".
129 * In particular, print a declaration of the form
131 * void S(int, ..., int);
133 * where S is the name of the domain and the number of arguments
134 * is equal to the dimension of "set".
136 static int print_declaration(__isl_take isl_set *set, void *user)
138 isl_printer **p = user;
139 int i, n;
141 n = isl_set_dim(set, isl_dim_set);
143 *p = isl_printer_start_line(*p);
144 *p = isl_printer_print_str(*p, "void ");
145 *p = isl_printer_print_str(*p, isl_set_get_tuple_name(set));
146 *p = isl_printer_print_str(*p, "(");
147 for (i = 0; i < n; ++i) {
148 if (i)
149 *p = isl_printer_print_str(*p, ", ");
150 *p = isl_printer_print_str(*p, "int");
152 *p = isl_printer_print_str(*p, ");");
153 *p = isl_printer_end_line(*p);
155 isl_set_free(set);
157 return 0;
160 /* Print a function declaration for each domain in "uset".
162 static __isl_give isl_printer *print_declarations(__isl_take isl_printer *p,
163 __isl_keep isl_union_set *uset)
165 if (isl_union_set_foreach_set(uset, &print_declaration, &p) >= 0)
166 return p;
167 isl_printer_free(p);
168 return NULL;
171 /* Check that the domain of "map" is named.
173 static int check_name(__isl_take isl_map *map, void *user)
175 int named;
176 isl_ctx *ctx;
178 ctx = isl_map_get_ctx(map);
179 named = isl_map_has_tuple_name(map, isl_dim_in);
180 isl_map_free(map);
182 if (named < 0)
183 return -1;
184 if (!named)
185 isl_die(ctx, isl_error_invalid,
186 "all domains should be named", return -1);
187 return 0;
190 /* Read a schedule, a context and (optionally) build options,
191 * generate an AST and print the result in a form that is readable
192 * by pet.
194 * In particular, print out the following code
196 * void foo(<parameters>/)
198 * void S1(int,...,int);
199 * #pragma scop
200 * AST
201 * #pragma endscop
204 int main(int argc, char **argv)
206 int i, n;
207 isl_ctx *ctx;
208 isl_set *context;
209 isl_union_set *domain;
210 isl_union_map *schedule;
211 isl_ast_build *build;
212 isl_ast_node *tree;
213 struct options *options;
214 isl_ast_print_options *print_options;
215 isl_printer *p;
217 options = options_new_with_defaults();
218 assert(options);
219 argc = options_parse(options, argc, argv, ISL_ARG_ALL);
221 ctx = isl_ctx_alloc_with_options(&options_args, options);
223 schedule = isl_union_map_read_from_file(ctx, stdin);
224 if (isl_union_map_foreach_map(schedule, &check_name, NULL) < 0) {
225 isl_union_map_free(schedule);
226 isl_ctx_free(ctx);
227 return 1;
229 context = isl_set_read_from_file(ctx, stdin);
230 context = isl_set_align_params(context,
231 isl_union_map_get_space(schedule));
233 domain = isl_union_map_domain(isl_union_map_copy(schedule));
235 p = isl_printer_to_file(ctx, stdout);
236 p = isl_printer_set_output_format(p, ISL_FORMAT_C);
237 p = isl_printer_start_line(p);
238 p = isl_printer_print_str(p, "void foo(");
240 n = isl_set_dim(context, isl_dim_param);
241 for (i = 0; i < n; ++i) {
242 const char *name;
243 if (i)
244 p = isl_printer_print_str(p, ", ");
245 name = isl_set_get_dim_name(context, isl_dim_param, i);
246 p = isl_printer_print_str(p, "int ");
247 p = isl_printer_print_str(p, name);
250 p = isl_printer_print_str(p, ")");
251 p = isl_printer_end_line(p);
252 p = isl_printer_start_line(p);
253 p = isl_printer_print_str(p, "{");
254 p = isl_printer_end_line(p);
255 p = isl_printer_start_line(p);
256 p = isl_printer_indent(p, 2);
257 p = print_declarations(p, domain);
258 p = isl_printer_indent(p, -2);
259 p = isl_printer_print_str(p, "#pragma scop");
260 p = isl_printer_end_line(p);
262 build = isl_ast_build_from_context(context);
263 build = set_options(build, options, schedule);
264 tree = isl_ast_build_ast_from_schedule(build, schedule);
265 isl_ast_build_free(build);
267 p = isl_printer_indent(p, 2);
268 print_options = isl_ast_print_options_alloc(ctx);
269 p = isl_ast_node_print(tree, p, print_options);
270 p = isl_printer_indent(p, -2);
271 p = isl_printer_start_line(p);
272 p = isl_printer_print_str(p, "#pragma endscop");
273 p = isl_printer_end_line(p);
274 p = isl_printer_start_line(p);
275 p = isl_printer_print_str(p, "}");
276 p = isl_printer_end_line(p);
277 isl_printer_free(p);
279 isl_ast_node_free(tree);
280 isl_union_set_free(domain);
281 isl_ctx_free(ctx);
282 return 0;