iscc: drop schedule_forest
[barvinok.git] / iscc.c
blob299236d3e716fee13a33b56daedb793635356400
1 #include <assert.h>
2 #include <ctype.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include <unistd.h>
6 #include <isl/aff.h>
7 #include <isl/obj.h>
8 #include <isl/stream.h>
9 #include <isl/set.h>
10 #include <isl/map.h>
11 #include <isl/vertices.h>
12 #include <isl/flow.h>
13 #include <isl/schedule.h>
14 #include <isl/ast_build.h>
15 #include <isl_obj_list.h>
16 #include <isl_obj_str.h>
17 #include <barvinok/isl.h>
18 #include <barvinok/options.h>
19 #include "lattice_width.h"
21 #include "config.h"
23 #ifdef HAVE_SIGACTION
24 #include <signal.h>
26 static isl_ctx *main_ctx;
28 static void handler(int signum)
30 if (isl_ctx_aborted(main_ctx))
31 exit(EXIT_FAILURE);
32 isl_ctx_abort(main_ctx);
35 static struct sigaction sa_old;
37 static void install_signal_handler(isl_ctx *ctx)
39 struct sigaction sa;
41 main_ctx = ctx;
43 memset(&sa, 0, sizeof(struct sigaction));
44 sa.sa_handler = &handler;
45 sa.sa_flags = SA_RESTART;
46 sigaction(SIGINT, &sa, &sa_old);
49 static void remove_signal_handler(isl_ctx *ctx)
51 sigaction(SIGINT, &sa_old, NULL);
54 #else
56 static void install_signal_handler(isl_ctx *ctx)
60 static void remove_signal_handler(isl_ctx *ctx)
64 #endif
66 #ifdef HAVE_PET
67 #include <pet.h>
68 #else
69 struct pet_options;
70 int pet_options_set_autodetect(isl_ctx *ctx, int val)
72 return -1;
74 #endif
76 static int iscc_bool_false = 0;
77 static int iscc_bool_true = 1;
78 static int iscc_bool_error = -1;
80 enum iscc_op { ISCC_READ, ISCC_WRITE, ISCC_SOURCE, ISCC_VERTICES,
81 ISCC_LAST, ISCC_ANY, ISCC_BEFORE, ISCC_UNDER,
82 ISCC_SCHEDULE,
83 ISCC_MINIMIZING, ISCC_RESPECTING,
84 ISCC_CODEGEN, ISCC_USING,
85 ISCC_TYPEOF, ISCC_PRINT, ISCC_ASSERT,
86 ISCC_N_OP };
87 static const char *op_name[ISCC_N_OP] = {
88 [ISCC_ASSERT] = "assert",
89 [ISCC_READ] = "read",
90 [ISCC_WRITE] = "write",
91 [ISCC_PRINT] = "print",
92 [ISCC_SOURCE] = "source",
93 [ISCC_VERTICES] = "vertices",
94 [ISCC_LAST] = "last",
95 [ISCC_ANY] = "any",
96 [ISCC_BEFORE] = "before",
97 [ISCC_UNDER] = "under",
98 [ISCC_SCHEDULE] = "schedule",
99 [ISCC_MINIMIZING] = "minimizing",
100 [ISCC_RESPECTING] = "respecting",
101 [ISCC_CODEGEN] = "codegen",
102 [ISCC_USING] = "using",
103 [ISCC_TYPEOF] = "typeof"
105 static enum isl_token_type iscc_op[ISCC_N_OP];
107 struct isl_arg_choice iscc_format[] = {
108 {"isl", ISL_FORMAT_ISL},
109 {"omega", ISL_FORMAT_OMEGA},
110 {"polylib", ISL_FORMAT_POLYLIB},
111 {"ext-polylib", ISL_FORMAT_EXT_POLYLIB},
112 {"latex", ISL_FORMAT_LATEX},
113 {"C", ISL_FORMAT_C},
117 struct iscc_options {
118 struct barvinok_options *barvinok;
119 struct pet_options *pet;
120 unsigned format;
121 int io;
124 ISL_ARGS_START(struct iscc_options, iscc_options_args)
125 ISL_ARG_CHILD(struct iscc_options, barvinok, "barvinok", &barvinok_options_args,
126 "barvinok options")
127 #ifdef HAVE_PET
128 ISL_ARG_CHILD(struct iscc_options, pet, "pet", &pet_options_args, "pet options")
129 #endif
130 ISL_ARG_CHOICE(struct iscc_options, format, 0, "format", \
131 iscc_format, ISL_FORMAT_ISL, "output format")
132 ISL_ARG_BOOL(struct iscc_options, io, 0, "io", 1,
133 "allow read and write operations")
134 ISL_ARGS_END
136 ISL_ARG_DEF(iscc_options, struct iscc_options, iscc_options_args)
137 ISL_ARG_CTX_DEF(iscc_options, struct iscc_options, iscc_options_args)
139 static void *isl_obj_bool_copy(void *v)
141 return v;
144 static void isl_obj_bool_free(void *v)
148 static __isl_give isl_printer *isl_obj_bool_print(__isl_take isl_printer *p,
149 void *v)
151 if (v == &iscc_bool_true)
152 return isl_printer_print_str(p, "True");
153 else if (v == &iscc_bool_false)
154 return isl_printer_print_str(p, "False");
155 else
156 return isl_printer_print_str(p, "Error");
159 static void *isl_obj_bool_add(void *v1, void *v2)
161 return v1;
164 struct isl_obj_vtable isl_obj_bool_vtable = {
165 isl_obj_bool_copy,
166 isl_obj_bool_add,
167 isl_obj_bool_print,
168 isl_obj_bool_free
170 #define isl_obj_bool (&isl_obj_bool_vtable)
172 int *iscc_bool_from_int(int res)
174 return res < 0 ? &iscc_bool_error :
175 res ? &iscc_bool_true : &iscc_bool_false;
178 static int isl_union_map_is_superset(__isl_take isl_union_map *map1,
179 __isl_take isl_union_map *map2)
181 return isl_union_map_is_subset(map2, map1);
183 static int isl_union_set_is_superset(__isl_take isl_union_set *set1,
184 __isl_take isl_union_set *set2)
186 return isl_union_set_is_subset(set2, set1);
189 static int isl_union_map_is_strict_superset(__isl_take isl_union_map *map1,
190 __isl_take isl_union_map *map2)
192 return isl_union_map_is_strict_subset(map2, map1);
194 static int isl_union_set_is_strict_superset(__isl_take isl_union_set *set1,
195 __isl_take isl_union_set *set2)
197 return isl_union_set_is_strict_subset(set2, set1);
200 extern struct isl_obj_vtable isl_obj_list_vtable;
201 #define isl_obj_list (&isl_obj_list_vtable)
203 typedef void *(*isc_bin_op_fn)(void *lhs, void *rhs);
204 typedef int (*isc_bin_test_fn)(void *lhs, void *rhs);
205 struct isc_bin_op {
206 enum isl_token_type op;
207 isl_obj_type lhs;
208 isl_obj_type rhs;
209 isl_obj_type res;
210 union {
211 isc_bin_op_fn fn;
212 isc_bin_test_fn test;
213 } o;
215 struct isc_named_bin_op {
216 char *name;
217 struct isc_bin_op op;
220 struct iscc_at {
221 isl_union_pw_qpolynomial *upwqp;
222 isl_union_pw_qpolynomial *res;
225 static isl_stat eval_at(__isl_take isl_point *pnt, void *user)
227 struct iscc_at *at = (struct iscc_at *) user;
228 isl_val *v;
229 isl_qpolynomial *qp;
230 isl_set *set;
232 set = isl_set_from_point(isl_point_copy(pnt));
233 v = isl_union_pw_qpolynomial_eval(
234 isl_union_pw_qpolynomial_copy(at->upwqp), pnt);
235 qp = isl_qpolynomial_val_on_domain(isl_set_get_space(set), v);
237 at->res = isl_union_pw_qpolynomial_add(at->res,
238 isl_union_pw_qpolynomial_from_pw_qpolynomial(
239 isl_pw_qpolynomial_alloc(set, qp)));
241 return isl_stat_ok;
244 __isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_at(
245 __isl_take isl_union_pw_qpolynomial *upwqp,
246 __isl_take isl_union_set *uset)
248 struct iscc_at at;
250 at.upwqp = upwqp;
251 at.res = isl_union_pw_qpolynomial_zero(isl_union_set_get_space(uset));
253 isl_union_set_foreach_point(uset, eval_at, &at);
255 isl_union_pw_qpolynomial_free(upwqp);
256 isl_union_set_free(uset);
258 return at.res;
261 struct iscc_fold_at {
262 isl_union_pw_qpolynomial_fold *upwf;
263 isl_union_pw_qpolynomial *res;
266 static isl_stat eval_fold_at(__isl_take isl_point *pnt, void *user)
268 struct iscc_fold_at *at = (struct iscc_fold_at *) user;
269 isl_val *v;
270 isl_qpolynomial *qp;
271 isl_set *set;
273 set = isl_set_from_point(isl_point_copy(pnt));
274 v = isl_union_pw_qpolynomial_fold_eval(
275 isl_union_pw_qpolynomial_fold_copy(at->upwf), pnt);
276 qp = isl_qpolynomial_val_on_domain(isl_set_get_space(set), v);
278 at->res = isl_union_pw_qpolynomial_add(at->res,
279 isl_union_pw_qpolynomial_from_pw_qpolynomial(
280 isl_pw_qpolynomial_alloc(set, qp)));
282 return isl_stat_ok;
285 __isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_fold_at(
286 __isl_take isl_union_pw_qpolynomial_fold *upwf,
287 __isl_take isl_union_set *uset)
289 struct iscc_fold_at at;
291 at.upwf = upwf;
292 at.res = isl_union_pw_qpolynomial_zero(isl_union_set_get_space(uset));
294 isl_union_set_foreach_point(uset, eval_fold_at, &at);
296 isl_union_pw_qpolynomial_fold_free(upwf);
297 isl_union_set_free(uset);
299 return at.res;
302 static __isl_give isl_union_pw_qpolynomial_fold *union_pw_qpolynomial_add_union_pw_qpolynomial_fold(
303 __isl_take isl_union_pw_qpolynomial *upwqp,
304 __isl_take isl_union_pw_qpolynomial_fold *upwf)
306 return isl_union_pw_qpolynomial_fold_add_union_pw_qpolynomial(upwf,
307 upwqp);
310 static __isl_give struct isl_list *union_map_apply_union_pw_qpolynomial_fold(
311 __isl_take isl_union_map *umap,
312 __isl_take isl_union_pw_qpolynomial_fold *upwf)
314 isl_ctx *ctx;
315 struct isl_list *list;
316 int tight;
318 ctx = isl_union_map_get_ctx(umap);
319 list = isl_list_alloc(ctx, 2);
320 if (!list)
321 goto error2;
323 list->obj[0].type = isl_obj_union_pw_qpolynomial_fold;
324 list->obj[0].v = isl_union_map_apply_union_pw_qpolynomial_fold(umap,
325 upwf, &tight);
326 list->obj[1].type = isl_obj_bool;
327 list->obj[1].v = tight ? &iscc_bool_true : &iscc_bool_false;
328 if (tight < 0 || !list->obj[0].v)
329 goto error;
331 return list;
332 error2:
333 isl_union_map_free(umap);
334 isl_union_pw_qpolynomial_fold_free(upwf);
335 error:
336 isl_list_free(list);
337 return NULL;
340 static __isl_give struct isl_list *union_set_apply_union_pw_qpolynomial_fold(
341 __isl_take isl_union_set *uset,
342 __isl_take isl_union_pw_qpolynomial_fold *upwf)
344 isl_ctx *ctx;
345 struct isl_list *list;
346 int tight;
348 ctx = isl_union_set_get_ctx(uset);
349 list = isl_list_alloc(ctx, 2);
350 if (!list)
351 goto error2;
353 list->obj[0].type = isl_obj_union_pw_qpolynomial_fold;
354 list->obj[0].v = isl_union_set_apply_union_pw_qpolynomial_fold(uset,
355 upwf, &tight);
356 list->obj[1].type = isl_obj_bool;
357 list->obj[1].v = tight ? &iscc_bool_true : &iscc_bool_false;
358 if (tight < 0 || !list->obj[0].v)
359 goto error;
361 return list;
362 error2:
363 isl_union_set_free(uset);
364 isl_union_pw_qpolynomial_fold_free(upwf);
365 error:
366 isl_list_free(list);
367 return NULL;
370 static __isl_give isl_union_pw_qpolynomial *isl_val_mul_union_pw_qpolynomial(
371 __isl_take isl_val *v, __isl_take isl_union_pw_qpolynomial *upwqp)
373 return isl_union_pw_qpolynomial_scale_val(upwqp, v);
376 static __isl_give isl_union_pw_qpolynomial_fold *
377 int_val_mul_union_pw_qpolynomial_fold(__isl_take isl_val *v,
378 __isl_take isl_union_pw_qpolynomial_fold *upwf)
380 return isl_union_pw_qpolynomial_fold_scale_val(upwf, v);
383 /* Are the two strings "str1" and "str2" equal to each other?
385 static int str_eq(__isl_keep isl_str *str1, __isl_keep isl_str *str2)
387 if (!str1 || !str2)
388 return -1;
390 return !strcmp(str1->s, str2->s);
393 struct isc_bin_op bin_ops[] = {
394 { '+', isl_obj_val, isl_obj_val, isl_obj_val,
395 (isc_bin_op_fn) &isl_val_add },
396 { '-', isl_obj_val, isl_obj_val, isl_obj_val,
397 (isc_bin_op_fn) &isl_val_sub },
398 { '*', isl_obj_val, isl_obj_val, isl_obj_val,
399 (isc_bin_op_fn) &isl_val_mul },
400 { '+', isl_obj_pw_multi_aff, isl_obj_pw_multi_aff,
401 isl_obj_pw_multi_aff,
402 (isc_bin_op_fn) &isl_pw_multi_aff_add },
403 { '+', isl_obj_union_set, isl_obj_union_set,
404 isl_obj_union_set,
405 (isc_bin_op_fn) &isl_union_set_union },
406 { '+', isl_obj_union_map, isl_obj_union_map,
407 isl_obj_union_map,
408 (isc_bin_op_fn) &isl_union_map_union },
409 { '-', isl_obj_union_set, isl_obj_union_set,
410 isl_obj_union_set,
411 (isc_bin_op_fn) &isl_union_set_subtract },
412 { '-', isl_obj_union_map, isl_obj_union_map,
413 isl_obj_union_map,
414 (isc_bin_op_fn) &isl_union_map_subtract },
415 { '*', isl_obj_union_set, isl_obj_union_set,
416 isl_obj_union_set,
417 (isc_bin_op_fn) &isl_union_set_intersect },
418 { '*', isl_obj_union_map, isl_obj_union_map,
419 isl_obj_union_map,
420 (isc_bin_op_fn) &isl_union_map_intersect },
421 { '*', isl_obj_union_map, isl_obj_union_set,
422 isl_obj_union_map,
423 (isc_bin_op_fn) &isl_union_map_intersect_domain },
424 { '.', isl_obj_union_map, isl_obj_union_map,
425 isl_obj_union_map,
426 (isc_bin_op_fn) &isl_union_map_apply_range },
427 { '.', isl_obj_union_map, isl_obj_union_pw_qpolynomial,
428 isl_obj_union_pw_qpolynomial,
429 (isc_bin_op_fn) &isl_union_map_apply_union_pw_qpolynomial },
430 { '.', isl_obj_union_map, isl_obj_union_pw_qpolynomial_fold,
431 isl_obj_list,
432 (isc_bin_op_fn) &union_map_apply_union_pw_qpolynomial_fold },
433 { ISL_TOKEN_TO, isl_obj_union_set, isl_obj_union_set,
434 isl_obj_union_map,
435 (isc_bin_op_fn) &isl_union_map_from_domain_and_range },
436 { '=', isl_obj_union_set, isl_obj_union_set, isl_obj_bool,
437 { .test = (isc_bin_test_fn) &isl_union_set_is_equal } },
438 { '=', isl_obj_union_map, isl_obj_union_map, isl_obj_bool,
439 { .test = (isc_bin_test_fn) &isl_union_map_is_equal } },
440 { ISL_TOKEN_LE, isl_obj_union_set, isl_obj_union_set,
441 isl_obj_bool,
442 { .test = (isc_bin_test_fn) &isl_union_set_is_subset } },
443 { ISL_TOKEN_LE, isl_obj_union_map, isl_obj_union_map,
444 isl_obj_bool,
445 { .test = (isc_bin_test_fn) &isl_union_map_is_subset } },
446 { ISL_TOKEN_LT, isl_obj_union_set, isl_obj_union_set,
447 isl_obj_bool,
448 { .test = (isc_bin_test_fn) &isl_union_set_is_strict_subset } },
449 { ISL_TOKEN_LT, isl_obj_union_map, isl_obj_union_map,
450 isl_obj_bool,
451 { .test = (isc_bin_test_fn) &isl_union_map_is_strict_subset } },
452 { ISL_TOKEN_GE, isl_obj_union_set, isl_obj_union_set,
453 isl_obj_bool,
454 { .test = (isc_bin_test_fn) &isl_union_set_is_superset } },
455 { ISL_TOKEN_GE, isl_obj_union_map, isl_obj_union_map,
456 isl_obj_bool,
457 { .test = (isc_bin_test_fn) &isl_union_map_is_superset } },
458 { ISL_TOKEN_GT, isl_obj_union_set, isl_obj_union_set,
459 isl_obj_bool,
460 { .test =
461 (isc_bin_test_fn) &isl_union_set_is_strict_superset } },
462 { ISL_TOKEN_GT, isl_obj_union_map, isl_obj_union_map,
463 isl_obj_bool,
464 { .test =
465 (isc_bin_test_fn) &isl_union_map_is_strict_superset } },
466 { ISL_TOKEN_LEX_LE, isl_obj_union_set, isl_obj_union_set,
467 isl_obj_union_map,
468 (isc_bin_op_fn) &isl_union_set_lex_le_union_set },
469 { ISL_TOKEN_LEX_LT, isl_obj_union_set, isl_obj_union_set,
470 isl_obj_union_map,
471 (isc_bin_op_fn) &isl_union_set_lex_lt_union_set },
472 { ISL_TOKEN_LEX_GE, isl_obj_union_set, isl_obj_union_set,
473 isl_obj_union_map,
474 (isc_bin_op_fn) &isl_union_set_lex_ge_union_set },
475 { ISL_TOKEN_LEX_GT, isl_obj_union_set, isl_obj_union_set,
476 isl_obj_union_map,
477 (isc_bin_op_fn) &isl_union_set_lex_gt_union_set },
478 { ISL_TOKEN_LEX_LE, isl_obj_union_map, isl_obj_union_map,
479 isl_obj_union_map,
480 (isc_bin_op_fn) &isl_union_map_lex_le_union_map },
481 { ISL_TOKEN_LEX_LT, isl_obj_union_map, isl_obj_union_map,
482 isl_obj_union_map,
483 (isc_bin_op_fn) &isl_union_map_lex_lt_union_map },
484 { ISL_TOKEN_LEX_GE, isl_obj_union_map, isl_obj_union_map,
485 isl_obj_union_map,
486 (isc_bin_op_fn) &isl_union_map_lex_ge_union_map },
487 { ISL_TOKEN_LEX_GT, isl_obj_union_map, isl_obj_union_map,
488 isl_obj_union_map,
489 (isc_bin_op_fn) &isl_union_map_lex_gt_union_map },
490 { '.', isl_obj_union_pw_qpolynomial_fold,
491 isl_obj_union_pw_qpolynomial_fold,
492 isl_obj_union_pw_qpolynomial_fold,
493 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_fold },
494 { '+', isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
495 isl_obj_union_pw_qpolynomial,
496 (isc_bin_op_fn) &isl_union_pw_qpolynomial_add },
497 { '+', isl_obj_union_pw_qpolynomial,
498 isl_obj_union_pw_qpolynomial_fold,
499 isl_obj_union_pw_qpolynomial_fold,
500 (isc_bin_op_fn) &union_pw_qpolynomial_add_union_pw_qpolynomial_fold },
501 { '+', isl_obj_union_pw_qpolynomial_fold,
502 isl_obj_union_pw_qpolynomial,
503 isl_obj_union_pw_qpolynomial_fold,
504 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_add_union_pw_qpolynomial },
505 { '-', isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
506 isl_obj_union_pw_qpolynomial,
507 (isc_bin_op_fn) &isl_union_pw_qpolynomial_sub },
508 { '*', isl_obj_val, isl_obj_union_pw_qpolynomial,
509 isl_obj_union_pw_qpolynomial,
510 (isc_bin_op_fn) &isl_val_mul_union_pw_qpolynomial },
511 { '*', isl_obj_union_pw_qpolynomial, isl_obj_val,
512 isl_obj_union_pw_qpolynomial,
513 (isc_bin_op_fn) &isl_union_pw_qpolynomial_scale_val },
514 { '*', isl_obj_val, isl_obj_union_pw_qpolynomial_fold,
515 isl_obj_union_pw_qpolynomial_fold,
516 (isc_bin_op_fn) &int_val_mul_union_pw_qpolynomial_fold },
517 { '*', isl_obj_union_pw_qpolynomial_fold, isl_obj_val,
518 isl_obj_union_pw_qpolynomial_fold,
519 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_scale_val },
520 { '*', isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
521 isl_obj_union_pw_qpolynomial,
522 (isc_bin_op_fn) &isl_union_pw_qpolynomial_mul },
523 { '*', isl_obj_union_pw_qpolynomial, isl_obj_union_set,
524 isl_obj_union_pw_qpolynomial,
525 (isc_bin_op_fn) &isl_union_pw_qpolynomial_intersect_domain },
526 { '*', isl_obj_union_pw_qpolynomial_fold, isl_obj_union_set,
527 isl_obj_union_pw_qpolynomial_fold,
528 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_intersect_domain },
529 { '@', isl_obj_union_pw_qpolynomial, isl_obj_union_set,
530 isl_obj_union_pw_qpolynomial,
531 (isc_bin_op_fn) &isl_union_pw_qpolynomial_at },
532 { '@', isl_obj_union_pw_qpolynomial_fold, isl_obj_union_set,
533 isl_obj_union_pw_qpolynomial,
534 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_at },
535 { '%', isl_obj_union_set, isl_obj_union_set,
536 isl_obj_union_set,
537 (isc_bin_op_fn) &isl_union_set_gist },
538 { '%', isl_obj_union_map, isl_obj_union_map,
539 isl_obj_union_map,
540 (isc_bin_op_fn) &isl_union_map_gist },
541 { '%', isl_obj_union_map, isl_obj_union_set,
542 isl_obj_union_map,
543 (isc_bin_op_fn) &isl_union_map_gist_domain },
544 { '%', isl_obj_union_pw_qpolynomial, isl_obj_union_set,
545 isl_obj_union_pw_qpolynomial,
546 (isc_bin_op_fn) &isl_union_pw_qpolynomial_gist },
547 { '%', isl_obj_union_pw_qpolynomial_fold, isl_obj_union_set,
548 isl_obj_union_pw_qpolynomial_fold,
549 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_gist },
550 { ISL_TOKEN_EQ_EQ, isl_obj_union_pw_qpolynomial,
551 isl_obj_union_pw_qpolynomial, isl_obj_bool,
552 { .test = (isc_bin_test_fn)
553 &isl_union_pw_qpolynomial_plain_is_equal } },
554 { ISL_TOKEN_EQ_EQ, isl_obj_union_pw_qpolynomial_fold,
555 isl_obj_union_pw_qpolynomial_fold, isl_obj_bool,
556 { .test = (isc_bin_test_fn)
557 &isl_union_pw_qpolynomial_fold_plain_is_equal } },
558 { '+', isl_obj_str, isl_obj_str, isl_obj_str,
559 (isc_bin_op_fn) &isl_str_concat },
560 { '=', isl_obj_str, isl_obj_str, isl_obj_bool,
561 { .test = (isc_bin_test_fn) &str_eq } },
565 static __isl_give isl_union_map *map_after_map(__isl_take isl_union_map *umap1,
566 __isl_take isl_union_map *umap2)
568 return isl_union_map_apply_range(umap2, umap1);
571 static __isl_give isl_union_pw_qpolynomial *qpolynomial_after_map(
572 __isl_take isl_union_pw_qpolynomial *upwqp,
573 __isl_take isl_union_map *umap)
575 return isl_union_map_apply_union_pw_qpolynomial(umap, upwqp);
578 static __isl_give struct isl_list *qpolynomial_fold_after_map(
579 __isl_take isl_union_pw_qpolynomial_fold *upwf,
580 __isl_take isl_union_map *umap)
582 return union_map_apply_union_pw_qpolynomial_fold(umap, upwf);
585 struct isc_named_bin_op named_bin_ops[] = {
586 { "after", { -1, isl_obj_union_map, isl_obj_union_map,
587 isl_obj_union_map,
588 (isc_bin_op_fn) &map_after_map } },
589 { "after", { -1, isl_obj_union_pw_qpolynomial,
590 isl_obj_union_map, isl_obj_union_pw_qpolynomial,
591 (isc_bin_op_fn) &qpolynomial_after_map } },
592 { "after", { -1, isl_obj_union_pw_qpolynomial_fold,
593 isl_obj_union_map, isl_obj_list,
594 (isc_bin_op_fn) &qpolynomial_fold_after_map } },
595 { "before", { -1, isl_obj_union_map, isl_obj_union_map,
596 isl_obj_union_map,
597 (isc_bin_op_fn) &isl_union_map_apply_range } },
598 { "before", { -1, isl_obj_union_map,
599 isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
600 (isc_bin_op_fn) &isl_union_map_apply_union_pw_qpolynomial } },
601 { "before", { -1, isl_obj_union_map,
602 isl_obj_union_pw_qpolynomial_fold, isl_obj_list,
603 (isc_bin_op_fn) &union_map_apply_union_pw_qpolynomial_fold } },
604 { "cross", { -1, isl_obj_union_set, isl_obj_union_set,
605 isl_obj_union_set,
606 (isc_bin_op_fn) &isl_union_set_product } },
607 { "cross", { -1, isl_obj_union_map, isl_obj_union_map,
608 isl_obj_union_map,
609 (isc_bin_op_fn) &isl_union_map_product } },
610 NULL
613 __isl_give isl_set *union_set_sample(__isl_take isl_union_set *uset)
615 return isl_set_from_basic_set(isl_union_set_sample(uset));
618 __isl_give isl_map *union_map_sample(__isl_take isl_union_map *umap)
620 return isl_map_from_basic_map(isl_union_map_sample(umap));
623 static __isl_give struct isl_list *union_map_power(
624 __isl_take isl_union_map *umap)
626 isl_ctx *ctx;
627 struct isl_list *list;
628 int exact;
630 ctx = isl_union_map_get_ctx(umap);
631 list = isl_list_alloc(ctx, 2);
632 if (!list)
633 goto error2;
635 list->obj[0].type = isl_obj_union_map;
636 list->obj[0].v = isl_union_map_power(umap, &exact);
637 list->obj[1].type = isl_obj_bool;
638 list->obj[1].v = exact ? &iscc_bool_true : &iscc_bool_false;
639 if (exact < 0 || !list->obj[0].v)
640 goto error;
642 return list;
643 error2:
644 isl_union_map_free(umap);
645 error:
646 isl_list_free(list);
647 return NULL;
650 /* Compute a lower or upper bound on "upwqp" depending on "type" and
651 * return a list containing two elements, the bound and a boolean
652 * indicating whether the result is tight.
654 static __isl_give struct isl_list *union_pw_qpolynomial_bound(
655 __isl_take isl_union_pw_qpolynomial *upwqp, enum isl_fold type)
657 isl_ctx *ctx;
658 struct isl_list *list;
659 int tight;
661 ctx = isl_union_pw_qpolynomial_get_ctx(upwqp);
662 list = isl_list_alloc(ctx, 2);
663 if (!list)
664 goto error2;
666 list->obj[0].type = isl_obj_union_pw_qpolynomial_fold;
667 list->obj[0].v = isl_union_pw_qpolynomial_bound(upwqp, type, &tight);
668 list->obj[1].type = isl_obj_bool;
669 list->obj[1].v = tight ? &iscc_bool_true : &iscc_bool_false;
670 if (tight < 0 || !list->obj[0].v)
671 goto error;
673 return list;
674 error2:
675 isl_union_pw_qpolynomial_free(upwqp);
676 error:
677 isl_list_free(list);
678 return NULL;
681 /* Compute a lower bound on "upwqp" and return a list containing
682 * two elements, the bound and a booleanindicating whether
683 * the result is tight.
685 static __isl_give struct isl_list *union_pw_qpolynomial_lower_bound(
686 __isl_take isl_union_pw_qpolynomial *upwqp)
688 return union_pw_qpolynomial_bound(upwqp, isl_fold_min);
691 /* Compute a upper bound on "upwqp" and return a list containing
692 * two elements, the bound and a booleanindicating whether
693 * the result is tight.
695 static __isl_give struct isl_list *union_pw_qpolynomial_upper_bound(
696 __isl_take isl_union_pw_qpolynomial *upwqp)
698 return union_pw_qpolynomial_bound(upwqp, isl_fold_max);
701 #ifdef HAVE_PET
702 static __isl_give isl_list *parse(__isl_take isl_str *str)
704 isl_ctx *ctx;
705 struct isl_list *list;
706 struct pet_scop *scop;
707 isl_union_map *sched, *may_reads, *must_writes, *may_writes;
708 isl_union_set *domain;
709 struct iscc_options *options;
711 if (!str)
712 return NULL;
713 ctx = str->ctx;
715 options = isl_ctx_peek_iscc_options(ctx);
716 if (!options || !options->io) {
717 isl_str_free(str);
718 isl_die(ctx, isl_error_invalid,
719 "parse_file operation not allowed", return NULL);
722 list = isl_list_alloc(ctx, 5);
723 if (!list)
724 goto error;
726 scop = pet_scop_extract_from_C_source(ctx, str->s, NULL);
727 domain = pet_scop_collect_domains(scop);
728 sched = scop ? isl_schedule_get_map(scop->schedule) : NULL;
729 may_reads = pet_scop_collect_may_reads(scop);
730 may_writes = pet_scop_collect_may_writes(scop);
731 must_writes = pet_scop_collect_must_writes(scop);
732 pet_scop_free(scop);
734 list->obj[0].type = isl_obj_union_set;
735 list->obj[0].v = domain;
736 list->obj[1].type = isl_obj_union_map;
737 list->obj[1].v = must_writes;
738 list->obj[2].type = isl_obj_union_map;
739 list->obj[2].v = may_writes;
740 list->obj[3].type = isl_obj_union_map;
741 list->obj[3].v = may_reads;
742 list->obj[4].type = isl_obj_union_map;
743 list->obj[4].v = sched;
745 if (!list->obj[0].v || !list->obj[1].v ||
746 !list->obj[2].v || !list->obj[3].v || !list->obj[4].v)
747 goto error;
749 isl_str_free(str);
750 return list;
751 error:
752 isl_list_free(list);
753 isl_str_free(str);
754 return NULL;
756 #endif
758 static isl_stat add_point(__isl_take isl_point *pnt, void *user)
760 isl_union_set **scan = (isl_union_set **) user;
762 *scan = isl_union_set_add_set(*scan, isl_set_from_point(pnt));
764 return isl_stat_ok;
767 static __isl_give isl_union_set *union_set_scan(__isl_take isl_union_set *uset)
769 isl_union_set *scan;
771 scan = isl_union_set_empty(isl_union_set_get_space(uset));
773 if (isl_union_set_foreach_point(uset, add_point, &scan) < 0) {
774 isl_union_set_free(scan);
775 return uset;
778 isl_union_set_free(uset);
779 return scan;
782 static __isl_give isl_union_map *union_map_scan(__isl_take isl_union_map *umap)
784 return isl_union_set_unwrap(union_set_scan(isl_union_map_wrap(umap)));
787 static __isl_give isl_union_pw_qpolynomial *union_pw_qpolynomial_poly(
788 __isl_take isl_union_pw_qpolynomial *upwqp)
790 return isl_union_pw_qpolynomial_to_polynomial(upwqp, 0);
793 static __isl_give isl_union_pw_qpolynomial *union_pw_qpolynomial_lpoly(
794 __isl_take isl_union_pw_qpolynomial *upwqp)
796 return isl_union_pw_qpolynomial_to_polynomial(upwqp, -1);
799 static __isl_give isl_union_pw_qpolynomial *union_pw_qpolynomial_upoly(
800 __isl_take isl_union_pw_qpolynomial *upwqp)
802 return isl_union_pw_qpolynomial_to_polynomial(upwqp, 1);
805 /* Return the domain of "schedule".
807 static __isl_give isl_union_set *schedule_domain(
808 __isl_take isl_schedule *schedule)
810 isl_union_set *domain;
812 domain = isl_schedule_get_domain(schedule);
813 isl_schedule_free(schedule);
815 return domain;
818 /* Convert "schedule" to a union map representation.
820 static __isl_give isl_union_map *schedule_map(__isl_take isl_schedule *schedule)
822 isl_union_map *map;
824 map = isl_schedule_get_map(schedule);
825 isl_schedule_free(schedule);
827 return map;
830 typedef void *(*isc_un_op_fn)(void *arg);
831 struct isc_un_op {
832 enum isl_token_type op;
833 isl_obj_type arg;
834 isl_obj_type res;
835 isc_un_op_fn fn;
837 struct isc_named_un_op {
838 char *name;
839 struct isc_un_op op;
841 struct isc_named_un_op named_un_ops[] = {
842 {"aff", { -1, isl_obj_union_map, isl_obj_union_map,
843 (isc_un_op_fn) &isl_union_map_affine_hull } },
844 {"aff", { -1, isl_obj_union_set, isl_obj_union_set,
845 (isc_un_op_fn) &isl_union_set_affine_hull } },
846 {"card", { -1, isl_obj_union_set,
847 isl_obj_union_pw_qpolynomial,
848 (isc_un_op_fn) &isl_union_set_card } },
849 {"card", { -1, isl_obj_union_map,
850 isl_obj_union_pw_qpolynomial,
851 (isc_un_op_fn) &isl_union_map_card } },
852 {"coalesce", { -1, isl_obj_union_set, isl_obj_union_set,
853 (isc_un_op_fn) &isl_union_set_coalesce } },
854 {"coalesce", { -1, isl_obj_union_map, isl_obj_union_map,
855 (isc_un_op_fn) &isl_union_map_coalesce } },
856 {"coalesce", { -1, isl_obj_union_pw_qpolynomial,
857 isl_obj_union_pw_qpolynomial,
858 (isc_un_op_fn) &isl_union_pw_qpolynomial_coalesce } },
859 {"coalesce", { -1, isl_obj_union_pw_qpolynomial_fold,
860 isl_obj_union_pw_qpolynomial_fold,
861 (isc_un_op_fn) &isl_union_pw_qpolynomial_fold_coalesce } },
862 {"coefficients", { -1, isl_obj_union_set,
863 isl_obj_union_set,
864 (isc_un_op_fn) &isl_union_set_coefficients } },
865 {"solutions", { -1, isl_obj_union_set, isl_obj_union_set,
866 (isc_un_op_fn) &isl_union_set_solutions } },
867 {"deltas", { -1, isl_obj_union_map, isl_obj_union_set,
868 (isc_un_op_fn) &isl_union_map_deltas } },
869 {"deltas_map", { -1, isl_obj_union_map, isl_obj_union_map,
870 (isc_un_op_fn) &isl_union_map_deltas_map } },
871 {"dom", { -1, isl_obj_schedule, isl_obj_union_set,
872 (isc_un_op_fn) &schedule_domain } },
873 {"dom", { -1, isl_obj_union_map, isl_obj_union_set,
874 (isc_un_op_fn) &isl_union_map_domain } },
875 {"dom", { -1, isl_obj_union_pw_qpolynomial, isl_obj_union_set,
876 (isc_un_op_fn) &isl_union_pw_qpolynomial_domain } },
877 {"dom", { -1, isl_obj_union_pw_qpolynomial_fold,
878 isl_obj_union_set,
879 (isc_un_op_fn) &isl_union_pw_qpolynomial_fold_domain } },
880 {"domain", { -1, isl_obj_schedule, isl_obj_union_set,
881 (isc_un_op_fn) &schedule_domain } },
882 {"domain", { -1, isl_obj_union_map, isl_obj_union_set,
883 (isc_un_op_fn) &isl_union_map_domain } },
884 {"domain", { -1, isl_obj_union_pw_qpolynomial,
885 isl_obj_union_set,
886 (isc_un_op_fn) &isl_union_pw_qpolynomial_domain } },
887 {"domain", { -1, isl_obj_union_pw_qpolynomial_fold,
888 isl_obj_union_set,
889 (isc_un_op_fn) &isl_union_pw_qpolynomial_fold_domain } },
890 {"domain_map", { -1, isl_obj_union_map, isl_obj_union_map,
891 (isc_un_op_fn) &isl_union_map_domain_map } },
892 {"ran", { -1, isl_obj_union_map, isl_obj_union_set,
893 (isc_un_op_fn) &isl_union_map_range } },
894 {"range", { -1, isl_obj_union_map, isl_obj_union_set,
895 (isc_un_op_fn) &isl_union_map_range } },
896 {"range_map", { -1, isl_obj_union_map, isl_obj_union_map,
897 (isc_un_op_fn) &isl_union_map_range_map } },
898 {"identity", { -1, isl_obj_union_set, isl_obj_union_map,
899 (isc_un_op_fn) &isl_union_set_identity } },
900 {"lattice_width", { -1, isl_obj_union_set,
901 isl_obj_union_pw_qpolynomial,
902 (isc_un_op_fn) &isl_union_set_lattice_width } },
903 {"lb", { -1, isl_obj_union_pw_qpolynomial, isl_obj_list,
904 (isc_un_op_fn) &union_pw_qpolynomial_lower_bound } },
905 {"lexmin", { -1, isl_obj_union_map, isl_obj_union_map,
906 (isc_un_op_fn) &isl_union_map_lexmin } },
907 {"lexmax", { -1, isl_obj_union_map, isl_obj_union_map,
908 (isc_un_op_fn) &isl_union_map_lexmax } },
909 {"lexmin", { -1, isl_obj_union_set, isl_obj_union_set,
910 (isc_un_op_fn) &isl_union_set_lexmin } },
911 {"lexmax", { -1, isl_obj_union_set, isl_obj_union_set,
912 (isc_un_op_fn) &isl_union_set_lexmax } },
913 {"lift", { -1, isl_obj_union_set, isl_obj_union_set,
914 (isc_un_op_fn) &isl_union_set_lift } },
915 {"map", { -1, isl_obj_schedule, isl_obj_union_map,
916 (isc_un_op_fn) &schedule_map } },
917 {"params", { -1, isl_obj_union_map, isl_obj_set,
918 (isc_un_op_fn) &isl_union_map_params } },
919 {"params", { -1, isl_obj_union_set, isl_obj_set,
920 (isc_un_op_fn) &isl_union_set_params } },
921 {"poly", { -1, isl_obj_union_map, isl_obj_union_map,
922 (isc_un_op_fn) &isl_union_map_polyhedral_hull } },
923 {"poly", { -1, isl_obj_union_set, isl_obj_union_set,
924 (isc_un_op_fn) &isl_union_set_polyhedral_hull } },
925 {"poly", { -1, isl_obj_union_pw_qpolynomial,
926 isl_obj_union_pw_qpolynomial,
927 (isc_un_op_fn) &union_pw_qpolynomial_poly } },
928 {"lpoly", { -1, isl_obj_union_pw_qpolynomial,
929 isl_obj_union_pw_qpolynomial,
930 (isc_un_op_fn) &union_pw_qpolynomial_lpoly } },
931 {"upoly", { -1, isl_obj_union_pw_qpolynomial,
932 isl_obj_union_pw_qpolynomial,
933 (isc_un_op_fn) &union_pw_qpolynomial_upoly } },
934 #ifdef HAVE_PET
935 {"parse_file", { -1, isl_obj_str, isl_obj_list,
936 (isc_un_op_fn) &parse } },
937 #endif
938 {"pow", { -1, isl_obj_union_map, isl_obj_list,
939 (isc_un_op_fn) &union_map_power } },
940 {"sample", { -1, isl_obj_union_set, isl_obj_set,
941 (isc_un_op_fn) &union_set_sample } },
942 {"sample", { -1, isl_obj_union_map, isl_obj_map,
943 (isc_un_op_fn) &union_map_sample } },
944 {"scan", { -1, isl_obj_union_set, isl_obj_union_set,
945 (isc_un_op_fn) &union_set_scan } },
946 {"scan", { -1, isl_obj_union_map, isl_obj_union_map,
947 (isc_un_op_fn) &union_map_scan } },
948 {"sum", { -1, isl_obj_union_pw_qpolynomial,
949 isl_obj_union_pw_qpolynomial,
950 (isc_un_op_fn) &isl_union_pw_qpolynomial_sum } },
951 {"ub", { -1, isl_obj_union_pw_qpolynomial, isl_obj_list,
952 (isc_un_op_fn) &union_pw_qpolynomial_upper_bound } },
953 {"unwrap", { -1, isl_obj_union_set, isl_obj_union_map,
954 (isc_un_op_fn) &isl_union_set_unwrap } },
955 {"wrap", { -1, isl_obj_union_map, isl_obj_union_set,
956 (isc_un_op_fn) &isl_union_map_wrap } },
957 {"zip", { -1, isl_obj_union_map, isl_obj_union_map,
958 (isc_un_op_fn) &isl_union_map_zip } },
959 NULL
962 struct isl_named_obj {
963 char *name;
964 struct isl_obj obj;
967 static void free_obj(struct isl_obj obj)
969 obj.type->free(obj.v);
972 static int same_name(const void *entry, const void *val)
974 const struct isl_named_obj *named = (const struct isl_named_obj *)entry;
976 return !strcmp(named->name, val);
979 static int do_assign(struct isl_ctx *ctx, struct isl_hash_table *table,
980 char *name, struct isl_obj obj)
982 struct isl_hash_table_entry *entry;
983 uint32_t name_hash;
984 struct isl_named_obj *named;
986 name_hash = isl_hash_string(isl_hash_init(), name);
987 entry = isl_hash_table_find(ctx, table, name_hash, same_name, name, 1);
988 if (!entry)
989 goto error;
990 if (entry->data) {
991 named = entry->data;
992 free_obj(named->obj);
993 free(name);
994 } else {
995 named = isl_alloc_type(ctx, struct isl_named_obj);
996 if (!named)
997 goto error;
998 named->name = name;
999 entry->data = named;
1001 named->obj = obj;
1003 return 0;
1004 error:
1005 free_obj(obj);
1006 free(name);
1007 return -1;
1010 static struct isl_obj stored_obj(struct isl_ctx *ctx,
1011 struct isl_hash_table *table, char *name)
1013 struct isl_obj obj = { isl_obj_none, NULL };
1014 struct isl_hash_table_entry *entry;
1015 uint32_t name_hash;
1017 name_hash = isl_hash_string(isl_hash_init(), name);
1018 entry = isl_hash_table_find(ctx, table, name_hash, same_name, name, 0);
1019 if (entry) {
1020 struct isl_named_obj *named;
1021 named = entry->data;
1022 obj = named->obj;
1023 } else if (isdigit(name[0]))
1024 fprintf(stderr, "unknown identifier '$%s'\n", name);
1025 else
1026 fprintf(stderr, "unknown identifier '%s'\n", name);
1028 free(name);
1029 obj.v = obj.type->copy(obj.v);
1030 return obj;
1033 static int is_subtype(struct isl_obj obj, isl_obj_type super)
1035 if (obj.type == super)
1036 return 1;
1037 if (obj.type == isl_obj_map && super == isl_obj_union_map)
1038 return 1;
1039 if (obj.type == isl_obj_set && super == isl_obj_union_set)
1040 return 1;
1041 if (obj.type == isl_obj_schedule && super == isl_obj_union_map)
1042 return 1;
1043 if (obj.type == isl_obj_pw_multi_aff && super == isl_obj_union_set) {
1044 isl_space *space = isl_pw_multi_aff_get_space(obj.v);
1045 int is_set = isl_space_is_set(space);
1046 isl_space_free(space);
1047 return is_set;
1049 if (obj.type == isl_obj_pw_qpolynomial &&
1050 super == isl_obj_union_pw_qpolynomial)
1051 return 1;
1052 if (obj.type == isl_obj_pw_qpolynomial_fold &&
1053 super == isl_obj_union_pw_qpolynomial_fold)
1054 return 1;
1055 if (obj.type == isl_obj_union_set && isl_union_set_is_empty(obj.v))
1056 return 1;
1057 if (obj.type == isl_obj_list) {
1058 struct isl_list *list = obj.v;
1059 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
1060 return is_subtype(list->obj[0], super);
1062 if (super == isl_obj_str)
1063 return 1;
1064 return 0;
1067 static struct isl_obj obj_at(struct isl_obj obj, int i)
1069 struct isl_list *list = obj.v;
1071 obj = list->obj[i];
1072 obj.v = obj.type->copy(obj.v);
1074 isl_list_free(list);
1076 return obj;
1079 static struct isl_obj convert(isl_ctx *ctx, struct isl_obj obj,
1080 isl_obj_type type)
1082 if (obj.type == type)
1083 return obj;
1084 if (obj.type == isl_obj_pw_multi_aff && type == isl_obj_union_set) {
1085 isl_set *set = isl_set_from_pw_multi_aff(obj.v);
1086 obj.type = isl_obj_union_set;
1087 obj.v = isl_union_set_from_set(set);
1088 return obj;
1090 if (obj.type == isl_obj_map && type == isl_obj_union_map) {
1091 obj.type = isl_obj_union_map;
1092 obj.v = isl_union_map_from_map(obj.v);
1093 return obj;
1095 if (obj.type == isl_obj_schedule && type == isl_obj_union_map) {
1096 obj.type = isl_obj_union_map;
1097 obj.v = schedule_map(obj.v);
1098 return obj;
1100 if (obj.type == isl_obj_set && type == isl_obj_union_set) {
1101 obj.type = isl_obj_union_set;
1102 obj.v = isl_union_set_from_set(obj.v);
1103 return obj;
1105 if (obj.type == isl_obj_pw_qpolynomial &&
1106 type == isl_obj_union_pw_qpolynomial) {
1107 obj.type = isl_obj_union_pw_qpolynomial;
1108 obj.v = isl_union_pw_qpolynomial_from_pw_qpolynomial(obj.v);
1109 return obj;
1111 if (obj.type == isl_obj_pw_qpolynomial_fold &&
1112 type == isl_obj_union_pw_qpolynomial_fold) {
1113 obj.type = isl_obj_union_pw_qpolynomial_fold;
1114 obj.v = isl_union_pw_qpolynomial_fold_from_pw_qpolynomial_fold(obj.v);
1115 return obj;
1117 if (obj.type == isl_obj_union_set && isl_union_set_is_empty(obj.v)) {
1118 if (type == isl_obj_union_map) {
1119 obj.type = isl_obj_union_map;
1120 return obj;
1122 if (type == isl_obj_union_pw_qpolynomial) {
1123 isl_space *dim = isl_union_set_get_space(obj.v);
1124 isl_union_set_free(obj.v);
1125 obj.v = isl_union_pw_qpolynomial_zero(dim);
1126 obj.type = isl_obj_union_pw_qpolynomial;
1127 return obj;
1129 if (type == isl_obj_union_pw_qpolynomial_fold) {
1130 isl_space *dim = isl_union_set_get_space(obj.v);
1131 isl_union_set_free(obj.v);
1132 obj.v = isl_union_pw_qpolynomial_fold_zero(dim,
1133 isl_fold_list);
1134 obj.type = isl_obj_union_pw_qpolynomial_fold;
1135 return obj;
1138 if (obj.type == isl_obj_list) {
1139 struct isl_list *list = obj.v;
1140 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
1141 return convert(ctx, obj_at(obj, 0), type);
1143 if (type == isl_obj_str) {
1144 isl_str *str;
1145 isl_printer *p;
1146 char *s;
1148 p = isl_printer_to_str(ctx);
1149 if (!p)
1150 goto error;
1151 p = obj.type->print(p, obj.v);
1152 s = isl_printer_get_str(p);
1153 isl_printer_free(p);
1155 str = isl_str_from_string(ctx, s);
1156 if (!str)
1157 goto error;
1158 free_obj(obj);
1159 obj.v = str;
1160 obj.type = isl_obj_str;
1161 return obj;
1164 error:
1165 free_obj(obj);
1166 obj.type = isl_obj_none;
1167 obj.v = NULL;
1168 return obj;
1171 static struct isc_bin_op *read_bin_op_if_available(struct isl_stream *s,
1172 struct isl_obj lhs)
1174 int i;
1175 struct isl_token *tok;
1177 tok = isl_stream_next_token(s);
1178 if (!tok)
1179 return NULL;
1181 for (i = 0; ; ++i) {
1182 if (!bin_ops[i].op)
1183 break;
1184 if (bin_ops[i].op != isl_token_get_type(tok))
1185 continue;
1186 if (!is_subtype(lhs, bin_ops[i].lhs))
1187 continue;
1189 isl_token_free(tok);
1190 return &bin_ops[i];
1193 for (i = 0; ; ++i) {
1194 if (!named_bin_ops[i].name)
1195 break;
1196 if (named_bin_ops[i].op.op != isl_token_get_type(tok))
1197 continue;
1198 if (!is_subtype(lhs, named_bin_ops[i].op.lhs))
1199 continue;
1201 isl_token_free(tok);
1202 return &named_bin_ops[i].op;
1205 isl_stream_push_token(s, tok);
1207 return NULL;
1210 static struct isc_un_op *read_prefix_un_op_if_available(struct isl_stream *s)
1212 int i;
1213 struct isl_token *tok;
1215 tok = isl_stream_next_token(s);
1216 if (!tok)
1217 return NULL;
1219 for (i = 0; ; ++i) {
1220 if (!named_un_ops[i].name)
1221 break;
1222 if (named_un_ops[i].op.op != isl_token_get_type(tok))
1223 continue;
1225 isl_token_free(tok);
1226 return &named_un_ops[i].op;
1229 isl_stream_push_token(s, tok);
1231 return NULL;
1234 static struct isc_un_op *find_matching_un_op(struct isc_un_op *like,
1235 struct isl_obj arg)
1237 int i;
1239 for (i = 0; ; ++i) {
1240 if (!named_un_ops[i].name)
1241 break;
1242 if (named_un_ops[i].op.op != like->op)
1243 continue;
1244 if (!is_subtype(arg, named_un_ops[i].op.arg))
1245 continue;
1247 return &named_un_ops[i].op;
1250 return NULL;
1253 static int is_assign(struct isl_stream *s)
1255 struct isl_token *tok;
1256 struct isl_token *tok2;
1257 int assign;
1259 tok = isl_stream_next_token(s);
1260 if (!tok)
1261 return 0;
1262 if (isl_token_get_type(tok) != ISL_TOKEN_IDENT) {
1263 isl_stream_push_token(s, tok);
1264 return 0;
1267 tok2 = isl_stream_next_token(s);
1268 if (!tok2) {
1269 isl_stream_push_token(s, tok);
1270 return 0;
1272 assign = isl_token_get_type(tok2) == ISL_TOKEN_DEF;
1273 isl_stream_push_token(s, tok2);
1274 isl_stream_push_token(s, tok);
1276 return assign;
1279 static struct isl_obj read_obj(struct isl_stream *s,
1280 struct isl_hash_table *table);
1281 static struct isl_obj read_expr(struct isl_stream *s,
1282 struct isl_hash_table *table);
1284 static struct isl_obj read_un_op_expr(struct isl_stream *s,
1285 struct isl_hash_table *table, struct isc_un_op *op)
1287 isl_ctx *ctx;
1288 struct isl_obj obj = { isl_obj_none, NULL };
1290 obj = read_obj(s, table);
1291 if (!obj.v)
1292 goto error;
1294 op = find_matching_un_op(op, obj);
1296 ctx = isl_stream_get_ctx(s);
1297 if (!op)
1298 isl_die(ctx, isl_error_invalid,
1299 "no such unary operator defined on given operand",
1300 goto error);
1302 obj = convert(ctx, obj, op->arg);
1303 obj.v = op->fn(obj.v);
1304 obj.type = op->res;
1306 return obj;
1307 error:
1308 free_obj(obj);
1309 obj.type = isl_obj_none;
1310 obj.v = NULL;
1311 return obj;
1314 static struct isl_obj transitive_closure(struct isl_ctx *ctx, struct isl_obj obj)
1316 struct isl_list *list;
1317 int exact;
1319 if (obj.type != isl_obj_union_map)
1320 obj = convert(ctx, obj, isl_obj_union_map);
1321 isl_assert(ctx, obj.type == isl_obj_union_map, goto error);
1322 list = isl_list_alloc(ctx, 2);
1323 if (!list)
1324 goto error;
1326 list->obj[0].type = isl_obj_union_map;
1327 list->obj[0].v = isl_union_map_transitive_closure(obj.v, &exact);
1328 list->obj[1].type = isl_obj_bool;
1329 list->obj[1].v = exact ? &iscc_bool_true : &iscc_bool_false;
1330 obj.v = list;
1331 obj.type = isl_obj_list;
1332 if (exact < 0 || !list->obj[0].v)
1333 goto error;
1335 return obj;
1336 error:
1337 free_obj(obj);
1338 obj.type = isl_obj_none;
1339 obj.v = NULL;
1340 return obj;
1343 static struct isl_obj obj_at_index(struct isl_stream *s, struct isl_obj obj)
1345 struct isl_list *list = obj.v;
1346 struct isl_token *tok;
1347 isl_ctx *ctx;
1348 isl_val *v;
1349 int i;
1351 tok = isl_stream_next_token(s);
1352 if (!tok || isl_token_get_type(tok) != ISL_TOKEN_VALUE) {
1353 isl_stream_error(s, tok, "expecting index");
1354 if (tok)
1355 isl_stream_push_token(s, tok);
1356 goto error;
1358 ctx = isl_stream_get_ctx(s);
1359 v = isl_token_get_val(ctx, tok);
1360 i = isl_val_get_num_si(v);
1361 isl_val_free(v);
1362 isl_token_free(tok);
1363 isl_assert(ctx, i < list->n, goto error);
1364 if (isl_stream_eat(s, ']'))
1365 goto error;
1367 return obj_at(obj, i);
1368 error:
1369 free_obj(obj);
1370 obj.type = isl_obj_none;
1371 obj.v = NULL;
1372 return obj;
1375 static struct isl_obj apply(struct isl_stream *s, __isl_take isl_union_map *umap,
1376 struct isl_hash_table *table)
1378 isl_ctx *ctx;
1379 struct isl_obj obj;
1381 obj = read_expr(s, table);
1382 ctx = isl_stream_get_ctx(s);
1383 isl_assert(ctx, is_subtype(obj, isl_obj_union_set) ||
1384 is_subtype(obj, isl_obj_union_map), goto error);
1386 if (obj.type == isl_obj_list) {
1387 struct isl_list *list = obj.v;
1388 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
1389 obj = obj_at(obj, 0);
1391 if (obj.type == isl_obj_set)
1392 obj = convert(ctx, obj, isl_obj_union_set);
1393 else if (obj.type == isl_obj_map)
1394 obj = convert(ctx, obj, isl_obj_union_map);
1395 if (obj.type == isl_obj_union_set) {
1396 obj.v = isl_union_set_apply(obj.v, umap);
1397 } else
1398 obj.v = isl_union_map_apply_range(obj.v, umap);
1399 if (!obj.v)
1400 goto error2;
1402 if (isl_stream_eat(s, ')'))
1403 goto error2;
1405 return obj;
1406 error:
1407 isl_union_map_free(umap);
1408 error2:
1409 free_obj(obj);
1410 obj.type = isl_obj_none;
1411 obj.v = NULL;
1412 return obj;
1415 static struct isl_obj apply_fun_set(struct isl_obj obj,
1416 __isl_take isl_union_set *uset)
1418 if (obj.type == isl_obj_union_pw_qpolynomial) {
1419 obj.v = isl_union_set_apply_union_pw_qpolynomial(uset, obj.v);
1420 } else {
1421 obj.type = isl_obj_list;
1422 obj.v = union_set_apply_union_pw_qpolynomial_fold(uset, obj.v);
1424 return obj;
1427 static struct isl_obj apply_fun_map(struct isl_obj obj,
1428 __isl_take isl_union_map *umap)
1430 if (obj.type == isl_obj_union_pw_qpolynomial) {
1431 obj.v = isl_union_map_apply_union_pw_qpolynomial(umap, obj.v);
1432 } else {
1433 obj.type = isl_obj_list;
1434 obj.v = union_map_apply_union_pw_qpolynomial_fold(umap, obj.v);
1436 return obj;
1439 static struct isl_obj apply_fun(struct isl_stream *s,
1440 struct isl_obj obj, struct isl_hash_table *table)
1442 struct isl_obj arg;
1443 isl_ctx *ctx;
1445 arg = read_expr(s, table);
1446 ctx = isl_stream_get_ctx(s);
1447 if (!is_subtype(arg, isl_obj_union_map) &&
1448 !is_subtype(arg, isl_obj_union_set))
1449 isl_die(ctx, isl_error_invalid,
1450 "expecting set of map argument", goto error);
1452 if (arg.type == isl_obj_list) {
1453 struct isl_list *list = arg.v;
1454 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
1455 arg = obj_at(arg, 0);
1457 if (arg.type == isl_obj_set)
1458 arg = convert(ctx, arg, isl_obj_union_set);
1459 else if (arg.type == isl_obj_map)
1460 arg = convert(ctx, arg, isl_obj_union_map);
1461 if (arg.type == isl_obj_union_set)
1462 obj = apply_fun_set(obj, arg.v);
1463 else
1464 obj = apply_fun_map(obj, arg.v);
1465 if (!obj.v)
1466 goto error2;
1468 if (isl_stream_eat(s, ')'))
1469 goto error2;
1471 return obj;
1472 error:
1473 free_obj(arg);
1474 error2:
1475 free_obj(obj);
1476 obj.type = isl_obj_none;
1477 obj.v = NULL;
1478 return obj;
1481 struct add_vertex_data {
1482 struct isl_list *list;
1483 int i;
1486 static isl_stat add_vertex(__isl_take isl_vertex *vertex, void *user)
1488 struct add_vertex_data *data = (struct add_vertex_data *)user;
1489 isl_multi_aff *ma;
1490 isl_set *dom;
1492 ma = isl_vertex_get_expr(vertex);
1493 dom = isl_set_from_basic_set(isl_vertex_get_domain(vertex));
1495 data->list->obj[data->i].type = isl_obj_pw_multi_aff;
1496 data->list->obj[data->i].v = isl_pw_multi_aff_alloc(dom, ma);
1497 data->i++;
1499 isl_vertex_free(vertex);
1501 return isl_stat_ok;
1504 static isl_stat set_vertices(__isl_take isl_set *set, void *user)
1506 isl_ctx *ctx;
1507 isl_basic_set *hull;
1508 isl_vertices *vertices = NULL;
1509 struct isl_list *list = NULL;
1510 isl_stat r;
1511 struct add_vertex_data *data = (struct add_vertex_data *)user;
1513 set = isl_set_remove_divs(set);
1514 hull = isl_set_convex_hull(set);
1515 vertices = isl_basic_set_compute_vertices(hull);
1516 isl_basic_set_free(hull);
1518 list = data->list;
1520 ctx = isl_vertices_get_ctx(vertices);
1521 data->list = isl_list_alloc(ctx, isl_vertices_get_n_vertices(vertices));
1522 if (!data->list)
1523 goto error;
1525 data->i = 0;
1526 r = isl_vertices_foreach_vertex(vertices, &add_vertex, user);
1528 data->list = isl_list_concat(list, data->list);
1530 isl_vertices_free(vertices);
1532 return r;
1533 error:
1534 data->list = list;
1535 isl_vertices_free(vertices);
1536 return isl_stat_error;
1539 static struct isl_obj vertices(struct isl_stream *s,
1540 struct isl_hash_table *table)
1542 isl_ctx *ctx;
1543 struct isl_obj obj;
1544 struct isl_list *list = NULL;
1545 isl_union_set *uset = NULL;
1546 struct add_vertex_data data = { NULL };
1548 obj = read_expr(s, table);
1549 ctx = isl_stream_get_ctx(s);
1550 obj = convert(ctx, obj, isl_obj_union_set);
1551 isl_assert(ctx, obj.type == isl_obj_union_set, goto error);
1552 uset = obj.v;
1553 obj.v = NULL;
1555 list = isl_list_alloc(ctx, 0);
1556 if (!list)
1557 goto error;
1559 data.list = list;
1561 if (isl_union_set_foreach_set(uset, &set_vertices, &data) < 0)
1562 goto error;
1564 isl_union_set_free(uset);
1566 obj.type = isl_obj_list;
1567 obj.v = data.list;
1569 return obj;
1570 error:
1571 isl_union_set_free(uset);
1572 isl_list_free(data.list);
1573 free_obj(obj);
1574 obj.type = isl_obj_none;
1575 obj.v = NULL;
1576 return obj;
1579 static struct isl_obj type_of(struct isl_stream *s,
1580 struct isl_hash_table *table)
1582 isl_ctx *ctx;
1583 struct isl_obj obj;
1584 const char *type = "unknown";
1586 obj = read_expr(s, table);
1588 if (obj.type == isl_obj_map ||
1589 obj.type == isl_obj_union_map)
1590 type = "map";
1591 if (obj.type == isl_obj_set ||
1592 obj.type == isl_obj_union_set)
1593 type = "set";
1594 if (obj.type == isl_obj_pw_multi_aff)
1595 type = "piecewise multi-quasiaffine expression";
1596 if (obj.type == isl_obj_pw_qpolynomial ||
1597 obj.type == isl_obj_union_pw_qpolynomial)
1598 type = "piecewise quasipolynomial";
1599 if (obj.type == isl_obj_pw_qpolynomial_fold ||
1600 obj.type == isl_obj_union_pw_qpolynomial_fold)
1601 type = "piecewise quasipolynomial fold";
1602 if (obj.type == isl_obj_list)
1603 type = "list";
1604 if (obj.type == isl_obj_bool)
1605 type = "boolean";
1606 if (obj.type == isl_obj_str)
1607 type = "string";
1608 if (obj.type == isl_obj_val)
1609 type = "value";
1610 if (obj.type == isl_obj_schedule)
1611 type = "schedule";
1613 free_obj(obj);
1614 obj.type = isl_obj_str;
1615 obj.v = isl_str_from_string(isl_stream_get_ctx(s), strdup(type));
1617 return obj;
1620 static __isl_give isl_union_set *read_set(struct isl_stream *s,
1621 struct isl_hash_table *table)
1623 struct isl_obj obj;
1624 isl_ctx *ctx;
1626 obj = read_obj(s, table);
1627 ctx = isl_stream_get_ctx(s);
1628 obj = convert(ctx, obj, isl_obj_union_set);
1629 isl_assert(ctx, obj.type == isl_obj_union_set, goto error);
1630 return obj.v;
1631 error:
1632 free_obj(obj);
1633 return NULL;
1636 static __isl_give isl_union_map *read_map(struct isl_stream *s,
1637 struct isl_hash_table *table)
1639 struct isl_obj obj;
1640 isl_ctx *ctx;
1642 obj = read_obj(s, table);
1643 ctx = isl_stream_get_ctx(s);
1644 obj = convert(ctx, obj, isl_obj_union_map);
1645 isl_assert(ctx, obj.type == isl_obj_union_map, goto error);
1646 return obj.v;
1647 error:
1648 free_obj(obj);
1649 return NULL;
1652 /* Read a schedule in the form of either a schedule (tree) or a union map
1653 * from "s" and store the schedule in "access".
1655 static __isl_give isl_union_access_info *access_info_set_schedule(
1656 __isl_take isl_union_access_info *access, struct isl_stream *s,
1657 struct isl_hash_table *table)
1659 struct isl_obj obj;
1660 isl_ctx *ctx;
1662 obj = read_obj(s, table);
1663 if (obj.type == isl_obj_schedule)
1664 return isl_union_access_info_set_schedule(access, obj.v);
1665 ctx = isl_stream_get_ctx(s);
1666 obj = convert(ctx, obj, isl_obj_union_map);
1668 return isl_union_access_info_set_schedule_map(access, obj.v);
1671 static struct isl_obj last_any(struct isl_stream *s,
1672 struct isl_hash_table *table, __isl_take isl_union_map *must_source,
1673 __isl_take isl_union_map *may_source)
1675 struct isl_obj obj = { isl_obj_none, NULL };
1676 isl_union_access_info *access;
1677 isl_union_flow *flow;
1678 isl_union_map *sink = NULL;
1679 isl_union_map *may_dep;
1681 if (isl_stream_eat(s, iscc_op[ISCC_BEFORE]))
1682 goto error;
1684 sink = read_map(s, table);
1685 if (!sink)
1686 goto error;
1688 if (isl_stream_eat(s, iscc_op[ISCC_UNDER]))
1689 goto error;
1691 access = isl_union_access_info_from_sink(sink);
1692 access = isl_union_access_info_set_must_source(access, must_source);
1693 access = isl_union_access_info_set_may_source(access, may_source);
1694 access = access_info_set_schedule(access, s, table);
1695 flow = isl_union_access_info_compute_flow(access);
1696 may_dep = isl_union_flow_get_may_dependence(flow);
1697 isl_union_flow_free(flow);
1699 if (!may_dep)
1700 return obj;
1702 obj.type = isl_obj_union_map;
1703 obj.v = may_dep;
1705 return obj;
1706 error:
1707 isl_union_map_free(may_source);
1708 isl_union_map_free(must_source);
1709 isl_union_map_free(sink);
1710 free_obj(obj);
1711 obj.type = isl_obj_none;
1712 obj.v = NULL;
1713 return obj;
1716 static struct isl_obj any(struct isl_stream *s, struct isl_hash_table *table)
1718 struct isl_obj obj = { isl_obj_none, NULL };
1719 isl_union_access_info *access;
1720 isl_union_flow *flow;
1721 isl_union_map *may_source = NULL;
1722 isl_union_map *sink = NULL;
1723 isl_union_map *may_dep;
1725 may_source = read_map(s, table);
1726 if (!may_source)
1727 goto error;
1729 if (isl_stream_eat_if_available(s, iscc_op[ISCC_LAST])) {
1730 isl_union_map *must_source;
1731 must_source = read_map(s, table);
1732 if (!must_source)
1733 goto error;
1734 return last_any(s, table, must_source, may_source);
1737 if (isl_stream_eat(s, iscc_op[ISCC_BEFORE]))
1738 goto error;
1740 sink = read_map(s, table);
1741 if (!sink)
1742 goto error;
1744 if (isl_stream_eat(s, iscc_op[ISCC_UNDER]))
1745 goto error;
1747 access = isl_union_access_info_from_sink(sink);
1748 access = isl_union_access_info_set_may_source(access, may_source);
1749 access = access_info_set_schedule(access, s, table);
1750 flow = isl_union_access_info_compute_flow(access);
1751 may_dep = isl_union_flow_get_may_dependence(flow);
1752 isl_union_flow_free(flow);
1754 if (!may_dep)
1755 return obj;
1757 obj.type = isl_obj_union_map;
1758 obj.v = may_dep;
1760 return obj;
1761 error:
1762 isl_union_map_free(may_source);
1763 isl_union_map_free(sink);
1764 free_obj(obj);
1765 obj.type = isl_obj_none;
1766 obj.v = NULL;
1767 return obj;
1770 static struct isl_obj last(struct isl_stream *s, struct isl_hash_table *table)
1772 struct isl_obj obj = { isl_obj_none, NULL };
1773 struct isl_list *list = NULL;
1774 isl_union_access_info *access;
1775 isl_union_flow *flow;
1776 isl_union_map *must_source = NULL;
1777 isl_union_map *sink = NULL;
1778 isl_union_map *must_dep;
1779 isl_union_map *must_no_source;
1781 must_source = read_map(s, table);
1782 if (!must_source)
1783 goto error;
1785 if (isl_stream_eat_if_available(s, iscc_op[ISCC_ANY])) {
1786 isl_union_map *may_source;
1787 may_source = read_map(s, table);
1788 if (!may_source)
1789 goto error;
1790 return last_any(s, table, must_source, may_source);
1793 list = isl_list_alloc(isl_stream_get_ctx(s), 2);
1794 if (!list)
1795 goto error;
1797 if (isl_stream_eat(s, iscc_op[ISCC_BEFORE]))
1798 goto error;
1800 sink = read_map(s, table);
1801 if (!sink)
1802 goto error;
1804 if (isl_stream_eat(s, iscc_op[ISCC_UNDER]))
1805 goto error;
1807 access = isl_union_access_info_from_sink(sink);
1808 access = isl_union_access_info_set_must_source(access, must_source);
1809 access = access_info_set_schedule(access, s, table);
1810 flow = isl_union_access_info_compute_flow(access);
1811 must_dep = isl_union_flow_get_must_dependence(flow);
1812 must_no_source = isl_union_flow_get_must_no_source(flow);
1813 isl_union_flow_free(flow);
1815 list->obj[0].type = isl_obj_union_map;
1816 list->obj[0].v = must_dep;
1817 list->obj[1].type = isl_obj_union_map;
1818 list->obj[1].v = must_no_source;
1820 if (!must_dep || !must_no_source) {
1821 isl_list_free(list);
1822 return obj;
1825 obj.v = list;
1826 obj.type = isl_obj_list;
1828 return obj;
1829 error:
1830 isl_list_free(list);
1831 isl_union_map_free(must_source);
1832 isl_union_map_free(sink);
1833 free_obj(obj);
1834 obj.type = isl_obj_none;
1835 obj.v = NULL;
1836 return obj;
1839 static __isl_give isl_schedule *get_schedule(struct isl_stream *s,
1840 struct isl_hash_table *table)
1842 isl_union_set *domain;
1843 isl_union_map *validity;
1844 isl_union_map *proximity;
1846 domain = read_set(s, table);
1847 if (!domain)
1848 return NULL;
1850 validity = isl_union_map_empty(isl_union_set_get_space(domain));
1851 proximity = isl_union_map_empty(isl_union_set_get_space(domain));
1853 for (;;) {
1854 isl_union_map *umap;
1855 if (isl_stream_eat_if_available(s, iscc_op[ISCC_RESPECTING])) {
1856 umap = read_map(s, table);
1857 validity = isl_union_map_union(validity, umap);
1858 } else if (isl_stream_eat_if_available(s, iscc_op[ISCC_MINIMIZING])) {
1859 umap = read_map(s, table);
1860 proximity = isl_union_map_union(proximity, umap);
1861 } else
1862 break;
1865 return isl_union_set_compute_schedule(domain, validity, proximity);
1868 static struct isl_obj schedule(struct isl_stream *s,
1869 struct isl_hash_table *table)
1871 struct isl_obj obj = { isl_obj_none, NULL };
1872 isl_schedule *schedule;
1874 schedule = get_schedule(s, table);
1876 obj.v = schedule;
1877 obj.type = isl_obj_schedule;
1879 return obj;
1882 /* Read a schedule for code generation in the form of either
1883 * a schedule tree or a union map.
1884 * If the input is a set rather than a map, then we construct
1885 * an identity union map schedule on the given set.
1887 static struct isl_obj get_codegen_schedule(struct isl_stream *s,
1888 struct isl_hash_table *table)
1890 struct isl_obj obj;
1891 isl_ctx *ctx;
1893 obj = read_obj(s, table);
1894 ctx = isl_stream_get_ctx(s);
1896 if (obj.type == isl_obj_schedule)
1897 return obj;
1898 if (is_subtype(obj, isl_obj_union_set)) {
1899 obj = convert(ctx, obj, isl_obj_union_set);
1900 obj.v = isl_union_set_identity(obj.v);
1901 obj.type = isl_obj_union_map;
1903 if (is_subtype(obj, isl_obj_union_map))
1904 return convert(ctx, obj, isl_obj_union_map);
1906 free_obj(obj);
1907 obj.v = NULL;
1908 obj.type = isl_obj_none;
1909 isl_die(ctx, isl_error_invalid, "expecting schedule, set or map",
1910 return obj);
1913 /* Generate an AST for the given schedule and options and return the AST.
1915 static __isl_give isl_ast_node *get_ast_from_union_map(
1916 __isl_take isl_union_map *schedule, __isl_take isl_union_map *options)
1918 isl_space *space;
1919 isl_set *context;
1920 isl_ast_build *build;
1921 isl_ast_node *tree;
1923 space = isl_union_map_get_space(schedule);
1924 context = isl_set_universe(isl_space_params(space));
1926 build = isl_ast_build_from_context(context);
1927 build = isl_ast_build_set_options(build, options);
1928 tree = isl_ast_build_ast_from_schedule(build, schedule);
1929 isl_ast_build_free(build);
1931 return tree;
1934 /* Generate an AST for the given schedule and return the AST.
1936 static __isl_give isl_ast_node *get_ast_from_schedule(
1937 __isl_take isl_schedule *schedule)
1939 isl_ast_build *build;
1940 isl_ast_node *tree;
1942 build = isl_ast_build_alloc(isl_schedule_get_ctx(schedule));
1943 tree = isl_ast_build_node_from_schedule(build, schedule);
1944 isl_ast_build_free(build);
1946 return tree;
1949 /* Print the AST "tree" on the printer "p".
1951 static __isl_give isl_printer *print_ast(__isl_take isl_printer *p,
1952 __isl_take isl_ast_node *tree)
1954 int format;
1956 format = isl_printer_get_output_format(p);
1957 p = isl_printer_set_output_format(p, ISL_FORMAT_C);
1958 p = isl_printer_print_ast_node(p, tree);
1959 p = isl_printer_set_output_format(p, format);
1961 isl_ast_node_free(tree);
1963 return p;
1966 /* Perform the codegen operation.
1967 * In particular, read a schedule, check if the user has specified any options
1968 * and then generate an AST from the schedule (and options) and print it.
1969 * In case the schedule is specified as a schedule tree, the AST generation
1970 * options are embedded in the schedule, so they are not read in separately.
1972 static __isl_give isl_printer *codegen(struct isl_stream *s,
1973 struct isl_hash_table *table, __isl_take isl_printer *p)
1975 struct isl_obj obj;
1976 isl_ast_node *tree;
1978 obj = get_codegen_schedule(s, table);
1979 if (!obj.v)
1980 return p;
1982 if (obj.type == isl_obj_schedule) {
1983 isl_schedule *schedule = obj.v;
1985 tree = get_ast_from_schedule(schedule);
1986 } else {
1987 isl_union_map *schedule = obj.v;
1988 isl_union_map *options;
1990 if (isl_stream_eat_if_available(s, iscc_op[ISCC_USING]))
1991 options = read_map(s, table);
1992 else
1993 options = isl_union_map_empty(
1994 isl_union_map_get_space(schedule));
1996 tree = get_ast_from_union_map(schedule, options);
1999 p = print_ast(p, tree);
2001 isl_stream_eat(s, ';');
2003 return p;
2006 static struct isl_obj power(struct isl_stream *s, struct isl_obj obj)
2008 struct isl_token *tok;
2009 isl_ctx *ctx;
2010 isl_val *v;
2012 ctx = isl_stream_get_ctx(s);
2013 if (isl_stream_eat_if_available(s, '+'))
2014 return transitive_closure(ctx, obj);
2016 isl_assert(ctx, is_subtype(obj, isl_obj_union_map), goto error);
2017 if (obj.type != isl_obj_union_map)
2018 obj = convert(ctx, obj, isl_obj_union_map);
2020 tok = isl_stream_next_token(s);
2021 if (!tok || isl_token_get_type(tok) != ISL_TOKEN_VALUE) {
2022 isl_stream_error(s, tok, "expecting integer exponent");
2023 if (tok)
2024 isl_stream_push_token(s, tok);
2025 goto error;
2028 v = isl_token_get_val(ctx, tok);
2029 if (isl_val_is_zero(v)) {
2030 isl_stream_error(s, tok, "expecting non-zero exponent");
2031 isl_val_free(v);
2032 if (tok)
2033 isl_stream_push_token(s, tok);
2034 goto error;
2037 obj.v = isl_union_map_fixed_power_val(obj.v, v);
2038 isl_token_free(tok);
2039 if (!obj.v)
2040 goto error;
2042 return obj;
2043 error:
2044 free_obj(obj);
2045 obj.type = isl_obj_none;
2046 obj.v = NULL;
2047 return obj;
2050 static struct isl_obj check_assert(struct isl_stream *s,
2051 struct isl_hash_table *table)
2053 struct isl_obj obj;
2054 isl_ctx *ctx;
2056 obj = read_expr(s, table);
2057 ctx = isl_stream_get_ctx(s);
2058 if (obj.type != isl_obj_bool)
2059 isl_die(ctx, isl_error_invalid,
2060 "expecting boolean expression", goto error);
2061 if (obj.v != &iscc_bool_true)
2062 isl_die(ctx, isl_error_unknown,
2063 "assertion failed", abort());
2064 error:
2065 free_obj(obj);
2066 obj.type = isl_obj_none;
2067 obj.v = NULL;
2068 return obj;
2071 static struct isl_obj read_from_file(struct isl_stream *s)
2073 isl_ctx *ctx;
2074 struct isl_obj obj;
2075 struct isl_token *tok;
2076 struct isl_stream *s_file;
2077 struct iscc_options *options;
2078 char *name;
2079 FILE *file;
2081 tok = isl_stream_next_token(s);
2082 if (!tok || isl_token_get_type(tok) != ISL_TOKEN_STRING) {
2083 isl_stream_error(s, tok, "expecting filename");
2084 isl_token_free(tok);
2085 goto error;
2088 ctx = isl_stream_get_ctx(s);
2089 options = isl_ctx_peek_iscc_options(ctx);
2090 if (!options || !options->io) {
2091 isl_token_free(tok);
2092 isl_die(ctx, isl_error_invalid,
2093 "read operation not allowed", goto error);
2096 name = isl_token_get_str(ctx, tok);
2097 isl_token_free(tok);
2098 file = fopen(name, "r");
2099 free(name);
2100 isl_assert(ctx, file, goto error);
2102 s_file = isl_stream_new_file(ctx, file);
2103 if (!s_file) {
2104 fclose(file);
2105 goto error;
2108 obj = isl_stream_read_obj(s_file);
2110 isl_stream_free(s_file);
2111 fclose(file);
2113 return obj;
2114 error:
2115 obj.type = isl_obj_none;
2116 obj.v = NULL;
2117 return obj;
2120 static struct isl_obj write_to_file(struct isl_stream *s,
2121 struct isl_hash_table *table)
2123 struct isl_obj obj;
2124 struct isl_token *tok;
2125 struct isl_stream *s_file;
2126 struct iscc_options *options;
2127 char *name;
2128 FILE *file;
2129 isl_ctx *ctx;
2130 isl_printer *p;
2132 tok = isl_stream_next_token(s);
2133 if (!tok || isl_token_get_type(tok) != ISL_TOKEN_STRING) {
2134 isl_stream_error(s, tok, "expecting filename");
2135 isl_token_free(tok);
2136 goto error;
2139 obj = read_expr(s, table);
2141 ctx = isl_stream_get_ctx(s);
2142 options = isl_ctx_peek_iscc_options(ctx);
2143 if (!options || !options->io) {
2144 isl_token_free(tok);
2145 isl_die(ctx, isl_error_invalid,
2146 "write operation not allowed", goto error);
2149 name = isl_token_get_str(ctx, tok);
2150 isl_token_free(tok);
2151 file = fopen(name, "w");
2152 free(name);
2153 if (!file)
2154 isl_die(ctx, isl_error_unknown,
2155 "could not open file for writing", goto error);
2157 p = isl_printer_to_file(ctx, file);
2158 p = isl_printer_set_output_format(p, options->format);
2159 p = obj.type->print(p, obj.v);
2160 p = isl_printer_end_line(p);
2161 isl_printer_free(p);
2163 fclose(file);
2164 error:
2165 free_obj(obj);
2166 obj.type = isl_obj_none;
2167 obj.v = NULL;
2168 return obj;
2171 static struct isl_obj read_string_if_available(struct isl_stream *s)
2173 struct isl_token *tok;
2174 struct isl_obj obj = { isl_obj_none, NULL };
2176 tok = isl_stream_next_token(s);
2177 if (!tok)
2178 return obj;
2179 if (isl_token_get_type(tok) == ISL_TOKEN_STRING) {
2180 isl_str *str;
2181 str = isl_str_alloc(isl_stream_get_ctx(s));
2182 if (!str)
2183 goto error;
2184 str->s = isl_token_get_str(isl_stream_get_ctx(s), tok);
2185 isl_token_free(tok);
2186 obj.v = str;
2187 obj.type = isl_obj_str;
2188 } else
2189 isl_stream_push_token(s, tok);
2190 return obj;
2191 error:
2192 isl_token_free(tok);
2193 return obj;
2196 static struct isl_obj read_bool_if_available(struct isl_stream *s)
2198 struct isl_token *tok;
2199 struct isl_obj obj = { isl_obj_none, NULL };
2200 int type;
2202 tok = isl_stream_next_token(s);
2203 if (!tok)
2204 return obj;
2205 type = isl_token_get_type(tok);
2206 if (type == ISL_TOKEN_FALSE || type == ISL_TOKEN_TRUE) {
2207 int is_true = type == ISL_TOKEN_TRUE;
2208 isl_token_free(tok);
2209 obj.v = is_true ? &iscc_bool_true : &iscc_bool_false;
2210 obj.type = isl_obj_bool;
2211 } else
2212 isl_stream_push_token(s, tok);
2213 return obj;
2216 static __isl_give char *read_ident(struct isl_stream *s)
2218 char *name;
2219 isl_val *v;
2220 struct isl_token *tok, *tok2;
2222 name = isl_stream_read_ident_if_available(s);
2223 if (name)
2224 return name;
2226 tok = isl_stream_next_token(s);
2227 if (!tok)
2228 return NULL;
2229 if (isl_token_get_type(tok) != '$') {
2230 isl_stream_push_token(s, tok);
2231 return NULL;
2233 tok2 = isl_stream_next_token(s);
2234 if (!tok2 || isl_token_get_type(tok2) != ISL_TOKEN_VALUE) {
2235 if (tok2)
2236 isl_stream_push_token(s, tok2);
2237 isl_stream_push_token(s, tok);
2238 return NULL;
2241 v = isl_token_get_val(isl_stream_get_ctx(s), tok2);
2242 name = isl_val_to_str(v);
2243 isl_val_free(v);
2244 isl_token_free(tok);
2245 isl_token_free(tok2);
2247 return name;
2250 static struct isl_obj read_list(struct isl_stream *s,
2251 struct isl_hash_table *table, struct isl_obj obj)
2253 struct isl_list *list;
2255 list = isl_list_alloc(isl_stream_get_ctx(s), 2);
2256 if (!list)
2257 goto error;
2258 list->obj[0] = obj;
2259 list->obj[1] = read_obj(s, table);
2260 obj.v = list;
2261 obj.type = isl_obj_list;
2263 if (!list->obj[1].v)
2264 goto error;
2266 while (isl_stream_eat_if_available(s, ',')) {
2267 obj.v = list = isl_list_add_obj(list, read_obj(s, table));
2268 if (!obj.v)
2269 goto error;
2272 return obj;
2273 error:
2274 free_obj(obj);
2275 obj.type = isl_obj_none;
2276 obj.v = NULL;
2277 return obj;
2280 static struct isl_obj read_obj(struct isl_stream *s,
2281 struct isl_hash_table *table)
2283 isl_ctx *ctx;
2284 struct isl_obj obj = { isl_obj_none, NULL };
2285 char *name = NULL;
2286 struct isc_un_op *op = NULL;
2288 obj = read_string_if_available(s);
2289 if (obj.v)
2290 return obj;
2291 obj = read_bool_if_available(s);
2292 if (obj.v)
2293 return obj;
2294 ctx = isl_stream_get_ctx(s);
2295 if (isl_stream_eat_if_available(s, '(')) {
2296 if (isl_stream_next_token_is(s, ')')) {
2297 obj.type = isl_obj_list;
2298 obj.v = isl_list_alloc(ctx, 0);
2299 } else {
2300 obj = read_expr(s, table);
2301 if (obj.v && isl_stream_eat_if_available(s, ','))
2302 obj = read_list(s, table, obj);
2304 if (!obj.v || isl_stream_eat(s, ')'))
2305 goto error;
2306 } else {
2307 op = read_prefix_un_op_if_available(s);
2308 if (op)
2309 return read_un_op_expr(s, table, op);
2311 if (isl_stream_eat_if_available(s, iscc_op[ISCC_ASSERT]))
2312 return check_assert(s, table);
2313 if (isl_stream_eat_if_available(s, iscc_op[ISCC_READ]))
2314 return read_from_file(s);
2315 if (isl_stream_eat_if_available(s, iscc_op[ISCC_WRITE]))
2316 return write_to_file(s, table);
2317 if (isl_stream_eat_if_available(s, iscc_op[ISCC_VERTICES]))
2318 return vertices(s, table);
2319 if (isl_stream_eat_if_available(s, iscc_op[ISCC_ANY]))
2320 return any(s, table);
2321 if (isl_stream_eat_if_available(s, iscc_op[ISCC_LAST]))
2322 return last(s, table);
2323 if (isl_stream_eat_if_available(s, iscc_op[ISCC_SCHEDULE]))
2324 return schedule(s, table);
2325 if (isl_stream_eat_if_available(s, iscc_op[ISCC_TYPEOF]))
2326 return type_of(s, table);
2328 name = read_ident(s);
2329 if (name)
2330 obj = stored_obj(ctx, table, name);
2331 else
2332 obj = isl_stream_read_obj(s);
2333 if (!obj.v)
2334 goto error;
2337 if (isl_stream_eat_if_available(s, '^'))
2338 obj = power(s, obj);
2339 else if (obj.type == isl_obj_list && isl_stream_eat_if_available(s, '['))
2340 obj = obj_at_index(s, obj);
2341 else if (is_subtype(obj, isl_obj_union_map) &&
2342 isl_stream_eat_if_available(s, '(')) {
2343 obj = convert(ctx, obj, isl_obj_union_map);
2344 obj = apply(s, obj.v, table);
2345 } else if (is_subtype(obj, isl_obj_union_pw_qpolynomial) &&
2346 isl_stream_eat_if_available(s, '(')) {
2347 obj = convert(ctx, obj, isl_obj_union_pw_qpolynomial);
2348 obj = apply_fun(s, obj, table);
2349 } else if (is_subtype(obj, isl_obj_union_pw_qpolynomial_fold) &&
2350 isl_stream_eat_if_available(s, '(')) {
2351 obj = convert(ctx, obj, isl_obj_union_pw_qpolynomial_fold);
2352 obj = apply_fun(s, obj, table);
2355 return obj;
2356 error:
2357 free_obj(obj);
2358 obj.type = isl_obj_none;
2359 obj.v = NULL;
2360 return obj;
2363 static struct isc_bin_op *find_matching_bin_op(struct isc_bin_op *like,
2364 struct isl_obj lhs, struct isl_obj rhs)
2366 int i;
2368 for (i = 0; ; ++i) {
2369 if (!bin_ops[i].op)
2370 break;
2371 if (bin_ops[i].op != like->op)
2372 continue;
2373 if (!is_subtype(lhs, bin_ops[i].lhs))
2374 continue;
2375 if (!is_subtype(rhs, bin_ops[i].rhs))
2376 continue;
2378 return &bin_ops[i];
2381 for (i = 0; ; ++i) {
2382 if (!named_bin_ops[i].name)
2383 break;
2384 if (named_bin_ops[i].op.op != like->op)
2385 continue;
2386 if (!is_subtype(lhs, named_bin_ops[i].op.lhs))
2387 continue;
2388 if (!is_subtype(rhs, named_bin_ops[i].op.rhs))
2389 continue;
2391 return &named_bin_ops[i].op;
2394 return NULL;
2397 static int next_is_neg_int(struct isl_stream *s)
2399 struct isl_token *tok;
2400 int ret;
2402 tok = isl_stream_next_token(s);
2403 if (tok && isl_token_get_type(tok) == ISL_TOKEN_VALUE) {
2404 isl_val *v;
2405 v = isl_token_get_val(isl_stream_get_ctx(s), tok);
2406 ret = isl_val_is_neg(v);
2407 isl_val_free(v);
2408 } else
2409 ret = 0;
2410 isl_stream_push_token(s, tok);
2412 return ret;
2415 static struct isl_obj call_bin_op(isl_ctx *ctx, struct isc_bin_op *op,
2416 struct isl_obj lhs, struct isl_obj rhs)
2418 struct isl_obj obj;
2420 lhs = convert(ctx, lhs, op->lhs);
2421 rhs = convert(ctx, rhs, op->rhs);
2422 if (op->res != isl_obj_bool)
2423 obj.v = op->o.fn(lhs.v, rhs.v);
2424 else {
2425 int res = op->o.test(lhs.v, rhs.v);
2426 free_obj(lhs);
2427 free_obj(rhs);
2428 obj.v = iscc_bool_from_int(res);
2430 obj.type = op->res;
2432 return obj;
2435 static struct isl_obj read_expr(struct isl_stream *s,
2436 struct isl_hash_table *table)
2438 isl_ctx *ctx;
2439 struct isl_obj obj = { isl_obj_none, NULL };
2440 struct isl_obj right_obj = { isl_obj_none, NULL };
2442 obj = read_obj(s, table);
2443 ctx = isl_stream_get_ctx(s);
2444 for (; obj.v;) {
2445 struct isc_bin_op *op = NULL;
2447 op = read_bin_op_if_available(s, obj);
2448 if (!op)
2449 break;
2451 right_obj = read_obj(s, table);
2453 op = find_matching_bin_op(op, obj, right_obj);
2455 if (!op)
2456 isl_die(ctx, isl_error_invalid,
2457 "no such binary operator defined on given operands",
2458 goto error);
2460 obj = call_bin_op(ctx, op, obj, right_obj);
2463 if (obj.type == isl_obj_val && next_is_neg_int(s)) {
2464 right_obj = read_obj(s, table);
2465 obj.v = isl_val_add(obj.v, right_obj.v);
2468 return obj;
2469 error:
2470 free_obj(right_obj);
2471 free_obj(obj);
2472 obj.type = isl_obj_none;
2473 obj.v = NULL;
2474 return obj;
2477 static __isl_give isl_printer *source_file(struct isl_stream *s,
2478 struct isl_hash_table *table, __isl_take isl_printer *p);
2480 /* Print "obj" to the printer "p".
2481 * If the object is a schedule, then print it in block format.
2483 static __isl_give isl_printer *print_obj(__isl_take isl_printer *p,
2484 struct isl_obj obj)
2486 if (obj.type != isl_obj_schedule)
2487 return obj.type->print(p, obj.v);
2489 p = isl_printer_set_yaml_style(p, ISL_YAML_STYLE_BLOCK);
2490 p = obj.type->print(p, obj.v);
2491 p = isl_printer_set_yaml_style(p, ISL_YAML_STYLE_FLOW);
2493 return p;
2496 static __isl_give isl_printer *read_line(struct isl_stream *s,
2497 struct isl_hash_table *table, __isl_take isl_printer *p, int tty)
2499 isl_ctx *ctx;
2500 struct isl_obj obj = { isl_obj_none, NULL };
2501 char *lhs = NULL;
2502 int assign = 0;
2503 int only_print = 0;
2504 struct isc_bin_op *op = NULL;
2505 char buf[30];
2507 if (!p)
2508 return NULL;
2509 if (isl_stream_is_empty(s))
2510 return p;
2512 if (isl_stream_eat_if_available(s, iscc_op[ISCC_SOURCE]))
2513 return source_file(s, table, p);
2514 if (isl_stream_eat_if_available(s, iscc_op[ISCC_CODEGEN]))
2515 return codegen(s, table, p);
2517 assign = is_assign(s);
2518 if (assign) {
2519 lhs = isl_stream_read_ident_if_available(s);
2520 if (isl_stream_eat(s, ISL_TOKEN_DEF))
2521 goto error;
2522 } else if (isl_stream_eat_if_available(s, iscc_op[ISCC_PRINT]))
2523 only_print = 1;
2524 else if (!tty)
2525 only_print = 1;
2527 obj = read_expr(s, table);
2528 ctx = isl_stream_get_ctx(s);
2529 if (isl_ctx_last_error(ctx) == isl_error_abort) {
2530 fprintf(stderr, "Interrupted\n");
2531 isl_ctx_reset_error(ctx);
2533 if (isl_stream_eat(s, ';'))
2534 goto error;
2536 if (only_print) {
2537 if (obj.type != isl_obj_none && obj.v != NULL) {
2538 p = print_obj(p, obj);
2539 p = isl_printer_end_line(p);
2541 free_obj(obj);
2542 return p;
2544 if (!assign && obj.type != isl_obj_none && obj.v != NULL) {
2545 static int count = 0;
2546 snprintf(buf, sizeof(buf), "$%d", count++);
2547 lhs = strdup(buf + 1);
2549 p = isl_printer_print_str(p, buf);
2550 p = isl_printer_print_str(p, " := ");
2551 p = obj.type->print(p, obj.v);
2552 p = isl_printer_end_line(p);
2554 if (lhs && do_assign(ctx, table, lhs, obj))
2555 return p;
2557 return p;
2558 error:
2559 isl_stream_flush_tokens(s);
2560 isl_stream_skip_line(s);
2561 free(lhs);
2562 free_obj(obj);
2563 return p;
2566 static isl_stat free_cb(void **entry, void *user)
2568 struct isl_named_obj *named = *entry;
2570 free_obj(named->obj);
2571 free(named->name);
2572 free(named);
2574 return isl_stat_ok;
2577 static void register_named_ops(struct isl_stream *s)
2579 int i;
2581 for (i = 0; i < ISCC_N_OP; ++i) {
2582 iscc_op[i] = isl_stream_register_keyword(s, op_name[i]);
2583 assert(iscc_op[i] != ISL_TOKEN_ERROR);
2586 for (i = 0; ; ++i) {
2587 if (!named_un_ops[i].name)
2588 break;
2589 named_un_ops[i].op.op = isl_stream_register_keyword(s,
2590 named_un_ops[i].name);
2591 assert(named_un_ops[i].op.op != ISL_TOKEN_ERROR);
2594 for (i = 0; ; ++i) {
2595 if (!named_bin_ops[i].name)
2596 break;
2597 named_bin_ops[i].op.op = isl_stream_register_keyword(s,
2598 named_bin_ops[i].name);
2599 assert(named_bin_ops[i].op.op != ISL_TOKEN_ERROR);
2603 static __isl_give isl_printer *source_file(struct isl_stream *s,
2604 struct isl_hash_table *table, __isl_take isl_printer *p)
2606 isl_ctx *ctx;
2607 struct isl_token *tok;
2608 struct isl_stream *s_file;
2609 struct iscc_options *options;
2610 char *name;
2611 FILE *file;
2613 tok = isl_stream_next_token(s);
2614 if (!tok || isl_token_get_type(tok) != ISL_TOKEN_STRING) {
2615 isl_stream_error(s, tok, "expecting filename");
2616 isl_token_free(tok);
2617 return p;
2620 isl_stream_eat(s, ';');
2622 ctx = isl_stream_get_ctx(s);
2623 options = isl_ctx_peek_iscc_options(ctx);
2624 if (!options || !options->io) {
2625 isl_token_free(tok);
2626 isl_die(ctx, isl_error_invalid,
2627 "source operation not allowed", return p);
2630 name = isl_token_get_str(ctx, tok);
2631 isl_token_free(tok);
2632 file = fopen(name, "r");
2633 free(name);
2634 isl_assert(ctx, file, return p);
2636 s_file = isl_stream_new_file(ctx, file);
2637 if (!s_file) {
2638 fclose(file);
2639 return p;
2642 register_named_ops(s_file);
2644 while (!isl_stream_is_empty(s_file))
2645 p = read_line(s_file, table, p, 0);
2647 isl_stream_free(s_file);
2648 fclose(file);
2650 return p;
2653 int main(int argc, char **argv)
2655 struct isl_ctx *ctx;
2656 struct isl_stream *s;
2657 struct isl_hash_table *table;
2658 struct iscc_options *options;
2659 isl_printer *p;
2660 int tty = isatty(0);
2662 options = iscc_options_new_with_defaults();
2663 assert(options);
2665 ctx = isl_ctx_alloc_with_options(&iscc_options_args, options);
2666 pet_options_set_autodetect(ctx, 1);
2667 argc = isl_ctx_parse_options(ctx, argc, argv, ISL_ARG_ALL);
2668 s = isl_stream_new_file(ctx, stdin);
2669 assert(s);
2670 table = isl_hash_table_alloc(ctx, 10);
2671 assert(table);
2672 p = isl_printer_to_file(ctx, stdout);
2673 p = isl_printer_set_output_format(p, options->format);
2674 assert(p);
2676 register_named_ops(s);
2678 install_signal_handler(ctx);
2680 while (p && !isl_stream_is_empty(s)) {
2681 isl_ctx_resume(ctx);
2682 p = read_line(s, table, p, tty);
2685 remove_signal_handler(ctx);
2687 isl_printer_free(p);
2688 isl_hash_table_foreach(ctx, table, free_cb, NULL);
2689 isl_hash_table_free(ctx, table);
2690 isl_stream_free(s);
2691 isl_ctx_free(ctx);
2693 return 0;