isl_scheduler.c: graph_find_compressed_node: look up node in correct graph
[isl.git] / isl_schedule_read.c
blobe3ea8c526c921ea82e4042c46707eb99e3759f79
1 #include <isl/schedule.h>
2 #include <isl/stream.h>
3 #include <isl_schedule_private.h>
4 #include <isl_schedule_tree.h>
6 /* An enumeration of the various keys that may appear in a YAML mapping
7 * of a schedule.
8 */
9 enum isl_schedule_key {
10 isl_schedule_key_error = -1,
11 isl_schedule_key_child,
12 isl_schedule_key_coincident,
13 isl_schedule_key_context,
14 isl_schedule_key_contraction,
15 isl_schedule_key_domain,
16 isl_schedule_key_expansion,
17 isl_schedule_key_extension,
18 isl_schedule_key_filter,
19 isl_schedule_key_guard,
20 isl_schedule_key_leaf,
21 isl_schedule_key_mark,
22 isl_schedule_key_options,
23 isl_schedule_key_permutable,
24 isl_schedule_key_schedule,
25 isl_schedule_key_sequence,
26 isl_schedule_key_set,
27 isl_schedule_key_end
30 /* Textual representations of the YAML keys for an isl_schedule object.
32 static char *key_str[] = {
33 [isl_schedule_key_child] = "child",
34 [isl_schedule_key_coincident] = "coincident",
35 [isl_schedule_key_context] = "context",
36 [isl_schedule_key_contraction] = "contraction",
37 [isl_schedule_key_domain] = "domain",
38 [isl_schedule_key_expansion] = "expansion",
39 [isl_schedule_key_extension] = "extension",
40 [isl_schedule_key_filter] = "filter",
41 [isl_schedule_key_guard] = "guard",
42 [isl_schedule_key_leaf] = "leaf",
43 [isl_schedule_key_mark] = "mark",
44 [isl_schedule_key_options] = "options",
45 [isl_schedule_key_permutable] = "permutable",
46 [isl_schedule_key_schedule] = "schedule",
47 [isl_schedule_key_sequence] = "sequence",
48 [isl_schedule_key_set] = "set",
51 #undef KEY
52 #define KEY enum isl_schedule_key
53 #undef KEY_ERROR
54 #define KEY_ERROR isl_schedule_key_error
55 #undef KEY_END
56 #define KEY_END isl_schedule_key_end
57 #include "extract_key.c"
59 static __isl_give isl_schedule_tree *isl_stream_read_schedule_tree(
60 __isl_keep isl_stream *s);
62 /* Read a subtree with context root node from "s".
64 static __isl_give isl_schedule_tree *read_context(__isl_keep isl_stream *s)
66 isl_set *context = NULL;
67 isl_schedule_tree *tree;
68 isl_ctx *ctx;
69 struct isl_token *tok;
70 enum isl_schedule_key key;
71 char *str;
72 int more;
74 ctx = isl_stream_get_ctx(s);
76 key = get_key(s);
78 if (isl_stream_yaml_next(s) < 0)
79 return NULL;
81 tok = isl_stream_next_token(s);
82 if (!tok) {
83 isl_stream_error(s, NULL, "unexpected EOF");
84 return NULL;
86 str = isl_token_get_str(ctx, tok);
87 context = isl_set_read_from_str(ctx, str);
88 free(str);
89 isl_token_free(tok);
91 more = isl_stream_yaml_next(s);
92 if (more < 0)
93 goto error;
94 if (!more) {
95 tree = isl_schedule_tree_from_context(context);
96 } else {
97 key = get_key(s);
98 if (key != isl_schedule_key_child)
99 isl_die(ctx, isl_error_invalid, "expecting child",
100 goto error);
101 if (isl_stream_yaml_next(s) < 0)
102 goto error;
103 tree = isl_stream_read_schedule_tree(s);
104 tree = isl_schedule_tree_insert_context(tree, context);
107 return tree;
108 error:
109 isl_set_free(context);
110 return NULL;
113 /* Read a subtree with domain root node from "s".
115 static __isl_give isl_schedule_tree *read_domain(__isl_keep isl_stream *s)
117 isl_union_set *domain = NULL;
118 isl_schedule_tree *tree;
119 isl_ctx *ctx;
120 struct isl_token *tok;
121 enum isl_schedule_key key;
122 char *str;
123 int more;
125 ctx = isl_stream_get_ctx(s);
127 key = get_key(s);
129 if (isl_stream_yaml_next(s) < 0)
130 return NULL;
132 tok = isl_stream_next_token(s);
133 if (!tok) {
134 isl_stream_error(s, NULL, "unexpected EOF");
135 return NULL;
137 str = isl_token_get_str(ctx, tok);
138 domain = isl_union_set_read_from_str(ctx, str);
139 free(str);
140 isl_token_free(tok);
142 more = isl_stream_yaml_next(s);
143 if (more < 0)
144 goto error;
145 if (!more) {
146 tree = isl_schedule_tree_from_domain(domain);
147 } else {
148 key = get_key(s);
149 if (key != isl_schedule_key_child)
150 isl_die(ctx, isl_error_invalid, "expecting child",
151 goto error);
152 if (isl_stream_yaml_next(s) < 0)
153 goto error;
154 tree = isl_stream_read_schedule_tree(s);
155 tree = isl_schedule_tree_insert_domain(tree, domain);
158 return tree;
159 error:
160 isl_union_set_free(domain);
161 return NULL;
164 /* Read a subtree with expansion root node from "s".
166 static __isl_give isl_schedule_tree *read_expansion(isl_stream *s)
168 isl_ctx *ctx;
169 isl_union_pw_multi_aff *contraction = NULL;
170 isl_union_map *expansion = NULL;
171 isl_schedule_tree *tree = NULL;
172 int more;
174 ctx = isl_stream_get_ctx(s);
176 do {
177 struct isl_token *tok;
178 enum isl_schedule_key key;
179 char *str;
181 key = get_key(s);
182 if (isl_stream_yaml_next(s) < 0)
183 goto error;
185 switch (key) {
186 case isl_schedule_key_contraction:
187 isl_union_pw_multi_aff_free(contraction);
188 tok = isl_stream_next_token(s);
189 str = isl_token_get_str(ctx, tok);
190 contraction = isl_union_pw_multi_aff_read_from_str(ctx,
191 str);
192 free(str);
193 isl_token_free(tok);
194 if (!contraction)
195 goto error;
196 break;
197 case isl_schedule_key_expansion:
198 isl_union_map_free(expansion);
199 tok = isl_stream_next_token(s);
200 str = isl_token_get_str(ctx, tok);
201 expansion = isl_union_map_read_from_str(ctx, str);
202 free(str);
203 isl_token_free(tok);
204 if (!expansion)
205 goto error;
206 break;
207 case isl_schedule_key_child:
208 isl_schedule_tree_free(tree);
209 tree = isl_stream_read_schedule_tree(s);
210 if (!tree)
211 goto error;
212 break;
213 default:
214 isl_die(ctx, isl_error_invalid, "unexpected key",
215 goto error);
217 } while ((more = isl_stream_yaml_next(s)) > 0);
219 if (more < 0)
220 goto error;
222 if (!contraction)
223 isl_die(ctx, isl_error_invalid, "missing contraction",
224 goto error);
225 if (!expansion)
226 isl_die(ctx, isl_error_invalid, "missing expansion",
227 goto error);
229 if (!tree)
230 return isl_schedule_tree_from_expansion(contraction, expansion);
231 return isl_schedule_tree_insert_expansion(tree, contraction, expansion);
232 error:
233 isl_schedule_tree_free(tree);
234 isl_union_pw_multi_aff_free(contraction);
235 isl_union_map_free(expansion);
236 return NULL;
239 /* Read a subtree with extension root node from "s".
241 static __isl_give isl_schedule_tree *read_extension(isl_stream *s)
243 isl_union_map *extension = NULL;
244 isl_schedule_tree *tree;
245 isl_ctx *ctx;
246 struct isl_token *tok;
247 enum isl_schedule_key key;
248 char *str;
249 int more;
251 ctx = isl_stream_get_ctx(s);
253 key = get_key(s);
255 if (isl_stream_yaml_next(s) < 0)
256 return NULL;
258 tok = isl_stream_next_token(s);
259 if (!tok) {
260 isl_stream_error(s, NULL, "unexpected EOF");
261 return NULL;
263 str = isl_token_get_str(ctx, tok);
264 extension = isl_union_map_read_from_str(ctx, str);
265 free(str);
266 isl_token_free(tok);
268 more = isl_stream_yaml_next(s);
269 if (more < 0)
270 goto error;
271 if (!more) {
272 tree = isl_schedule_tree_from_extension(extension);
273 } else {
274 key = get_key(s);
275 if (key != isl_schedule_key_child)
276 isl_die(ctx, isl_error_invalid, "expecting child",
277 goto error);
278 if (isl_stream_yaml_next(s) < 0)
279 goto error;
280 tree = isl_stream_read_schedule_tree(s);
281 tree = isl_schedule_tree_insert_extension(tree, extension);
284 return tree;
285 error:
286 isl_union_map_free(extension);
287 return NULL;
290 /* Read a subtree with filter root node from "s".
292 static __isl_give isl_schedule_tree *read_filter(__isl_keep isl_stream *s)
294 isl_union_set *filter = NULL;
295 isl_schedule_tree *tree;
296 isl_ctx *ctx;
297 struct isl_token *tok;
298 enum isl_schedule_key key;
299 char *str;
300 int more;
302 ctx = isl_stream_get_ctx(s);
304 key = get_key(s);
306 if (isl_stream_yaml_next(s) < 0)
307 return NULL;
309 tok = isl_stream_next_token(s);
310 if (!tok) {
311 isl_stream_error(s, NULL, "unexpected EOF");
312 return NULL;
314 str = isl_token_get_str(ctx, tok);
315 filter = isl_union_set_read_from_str(ctx, str);
316 free(str);
317 isl_token_free(tok);
319 more = isl_stream_yaml_next(s);
320 if (more < 0)
321 goto error;
322 if (!more) {
323 tree = isl_schedule_tree_from_filter(filter);
324 } else {
325 key = get_key(s);
326 if (key != isl_schedule_key_child)
327 isl_die(ctx, isl_error_invalid, "expecting child",
328 goto error);
329 if (isl_stream_yaml_next(s) < 0)
330 goto error;
331 tree = isl_stream_read_schedule_tree(s);
332 tree = isl_schedule_tree_insert_filter(tree, filter);
335 return tree;
336 error:
337 isl_union_set_free(filter);
338 return NULL;
341 /* Read a subtree with guard root node from "s".
343 static __isl_give isl_schedule_tree *read_guard(isl_stream *s)
345 isl_set *guard = NULL;
346 isl_schedule_tree *tree;
347 isl_ctx *ctx;
348 struct isl_token *tok;
349 enum isl_schedule_key key;
350 char *str;
351 int more;
353 ctx = isl_stream_get_ctx(s);
355 key = get_key(s);
357 if (isl_stream_yaml_next(s) < 0)
358 return NULL;
360 tok = isl_stream_next_token(s);
361 if (!tok) {
362 isl_stream_error(s, NULL, "unexpected EOF");
363 return NULL;
365 str = isl_token_get_str(ctx, tok);
366 guard = isl_set_read_from_str(ctx, str);
367 free(str);
368 isl_token_free(tok);
370 more = isl_stream_yaml_next(s);
371 if (more < 0)
372 goto error;
373 if (!more) {
374 tree = isl_schedule_tree_from_guard(guard);
375 } else {
376 key = get_key(s);
377 if (key != isl_schedule_key_child)
378 isl_die(ctx, isl_error_invalid, "expecting child",
379 goto error);
380 if (isl_stream_yaml_next(s) < 0)
381 goto error;
382 tree = isl_stream_read_schedule_tree(s);
383 tree = isl_schedule_tree_insert_guard(tree, guard);
386 return tree;
387 error:
388 isl_set_free(guard);
389 return NULL;
392 /* Read a subtree with mark root node from "s".
394 static __isl_give isl_schedule_tree *read_mark(isl_stream *s)
396 isl_id *mark;
397 isl_schedule_tree *tree;
398 isl_ctx *ctx;
399 struct isl_token *tok;
400 enum isl_schedule_key key;
401 char *str;
402 int more;
404 ctx = isl_stream_get_ctx(s);
406 key = get_key(s);
408 if (isl_stream_yaml_next(s) < 0)
409 return NULL;
411 tok = isl_stream_next_token(s);
412 if (!tok) {
413 isl_stream_error(s, NULL, "unexpected EOF");
414 return NULL;
416 str = isl_token_get_str(ctx, tok);
417 mark = isl_id_alloc(ctx, str, NULL);
418 free(str);
419 isl_token_free(tok);
421 more = isl_stream_yaml_next(s);
422 if (more < 0)
423 goto error;
424 if (!more) {
425 isl_die(ctx, isl_error_invalid, "expecting child",
426 goto error);
427 } else {
428 key = get_key(s);
429 if (key != isl_schedule_key_child)
430 isl_die(ctx, isl_error_invalid, "expecting child",
431 goto error);
432 if (isl_stream_yaml_next(s) < 0)
433 goto error;
434 tree = isl_stream_read_schedule_tree(s);
435 tree = isl_schedule_tree_insert_mark(tree, mark);
438 return tree;
439 error:
440 isl_id_free(mark);
441 return NULL;
444 /* Read a sequence of integers from "s" (representing the coincident
445 * property of a band node).
447 static __isl_give isl_val_list *read_coincident(__isl_keep isl_stream *s)
449 isl_ctx *ctx;
450 isl_val_list *list;
451 int more;
453 ctx = isl_stream_get_ctx(s);
455 if (isl_stream_yaml_read_start_sequence(s) < 0)
456 return NULL;
458 list = isl_val_list_alloc(ctx, 0);
459 while ((more = isl_stream_yaml_next(s)) > 0) {
460 isl_val *val;
462 val = isl_stream_read_val(s);
463 list = isl_val_list_add(list, val);
466 if (more < 0 || isl_stream_yaml_read_end_sequence(s))
467 list = isl_val_list_free(list);
469 return list;
472 /* Set the (initial) coincident properties of "band" according to
473 * the (initial) elements of "coincident".
475 static __isl_give isl_schedule_band *set_coincident(
476 __isl_take isl_schedule_band *band, __isl_take isl_val_list *coincident)
478 int i;
479 int n, m;
481 n = isl_schedule_band_n_member(band);
482 m = isl_val_list_n_val(coincident);
484 for (i = 0; i < n && i < m; ++i) {
485 isl_val *v;
487 v = isl_val_list_get_val(coincident, i);
488 if (!v)
489 band = isl_schedule_band_free(band);
490 band = isl_schedule_band_member_set_coincident(band, i,
491 !isl_val_is_zero(v));
492 isl_val_free(v);
494 isl_val_list_free(coincident);
495 return band;
498 /* Read a subtree with band root node from "s".
500 static __isl_give isl_schedule_tree *read_band(isl_stream *s)
502 isl_multi_union_pw_aff *schedule = NULL;
503 isl_schedule_tree *tree = NULL;
504 isl_val_list *coincident = NULL;
505 isl_union_set *options = NULL;
506 isl_ctx *ctx;
507 isl_schedule_band *band;
508 int permutable = 0;
509 int more;
511 ctx = isl_stream_get_ctx(s);
513 do {
514 struct isl_token *tok;
515 enum isl_schedule_key key;
516 char *str;
517 isl_val *v;
519 key = get_key(s);
520 if (isl_stream_yaml_next(s) < 0)
521 goto error;
523 switch (key) {
524 case isl_schedule_key_schedule:
525 schedule = isl_multi_union_pw_aff_free(schedule);
526 tok = isl_stream_next_token(s);
527 if (!tok) {
528 isl_stream_error(s, NULL, "unexpected EOF");
529 goto error;
531 str = isl_token_get_str(ctx, tok);
532 schedule = isl_multi_union_pw_aff_read_from_str(ctx,
533 str);
534 free(str);
535 isl_token_free(tok);
536 if (!schedule)
537 goto error;
538 break;
539 case isl_schedule_key_coincident:
540 coincident = read_coincident(s);
541 if (!coincident)
542 goto error;
543 break;
544 case isl_schedule_key_permutable:
545 v = isl_stream_read_val(s);
546 permutable = !isl_val_is_zero(v);
547 isl_val_free(v);
548 break;
549 case isl_schedule_key_options:
550 isl_union_set_free(options);
551 tok = isl_stream_next_token(s);
552 str = isl_token_get_str(ctx, tok);
553 options = isl_union_set_read_from_str(ctx, str);
554 free(str);
555 isl_token_free(tok);
556 if (!options)
557 goto error;
558 break;
559 case isl_schedule_key_child:
560 isl_schedule_tree_free(tree);
561 tree = isl_stream_read_schedule_tree(s);
562 if (!tree)
563 goto error;
564 break;
565 default:
566 isl_die(ctx, isl_error_invalid, "unexpected key",
567 goto error);
569 } while ((more = isl_stream_yaml_next(s)) > 0);
571 if (more < 0)
572 goto error;
574 if (!schedule)
575 isl_die(ctx, isl_error_invalid, "missing schedule", goto error);
577 band = isl_schedule_band_from_multi_union_pw_aff(schedule);
578 band = isl_schedule_band_set_permutable(band, permutable);
579 if (coincident)
580 band = set_coincident(band, coincident);
581 if (options)
582 band = isl_schedule_band_set_ast_build_options(band, options);
583 if (tree)
584 tree = isl_schedule_tree_insert_band(tree, band);
585 else
586 tree = isl_schedule_tree_from_band(band);
588 return tree;
589 error:
590 isl_val_list_free(coincident);
591 isl_union_set_free(options);
592 isl_schedule_tree_free(tree);
593 isl_multi_union_pw_aff_free(schedule);
594 return NULL;
597 /* Read a subtree with root node of type "type" from "s".
598 * The node is represented by a sequence of children.
600 static __isl_give isl_schedule_tree *read_children(isl_stream *s,
601 enum isl_schedule_node_type type)
603 isl_ctx *ctx;
604 isl_schedule_tree_list *list;
605 int more;
607 ctx = isl_stream_get_ctx(s);
609 isl_token_free(isl_stream_next_token(s));
611 if (isl_stream_yaml_next(s) < 0)
612 return NULL;
614 if (isl_stream_yaml_read_start_sequence(s))
615 return NULL;
617 list = isl_schedule_tree_list_alloc(ctx, 0);
618 while ((more = isl_stream_yaml_next(s)) > 0) {
619 isl_schedule_tree *tree;
621 tree = isl_stream_read_schedule_tree(s);
622 list = isl_schedule_tree_list_add(list, tree);
625 if (more < 0 || isl_stream_yaml_read_end_sequence(s))
626 list = isl_schedule_tree_list_free(list);
628 return isl_schedule_tree_from_children(type, list);
631 /* Read a subtree with sequence root node from "s".
633 static __isl_give isl_schedule_tree *read_sequence(isl_stream *s)
635 return read_children(s, isl_schedule_node_sequence);
638 /* Read a subtree with set root node from "s".
640 static __isl_give isl_schedule_tree *read_set(isl_stream *s)
642 return read_children(s, isl_schedule_node_set);
645 /* Read a schedule (sub)tree from "s".
647 * We first determine the type of the root node based on the first
648 * mapping key and then hand over to a function tailored to reading
649 * nodes of this type.
651 static __isl_give isl_schedule_tree *isl_stream_read_schedule_tree(
652 struct isl_stream *s)
654 enum isl_schedule_key key;
655 struct isl_token *tok;
656 isl_schedule_tree *tree = NULL;
657 int more;
659 if (isl_stream_yaml_read_start_mapping(s))
660 return NULL;
661 more = isl_stream_yaml_next(s);
662 if (more < 0)
663 return NULL;
664 if (!more) {
665 isl_stream_error(s, NULL, "missing key");
666 return NULL;
669 tok = isl_stream_next_token(s);
670 key = extract_key(s, tok);
671 isl_stream_push_token(s, tok);
672 if (key < 0)
673 return NULL;
674 switch (key) {
675 case isl_schedule_key_context:
676 tree = read_context(s);
677 break;
678 case isl_schedule_key_domain:
679 tree = read_domain(s);
680 break;
681 case isl_schedule_key_contraction:
682 case isl_schedule_key_expansion:
683 tree = read_expansion(s);
684 break;
685 case isl_schedule_key_extension:
686 tree = read_extension(s);
687 break;
688 case isl_schedule_key_filter:
689 tree = read_filter(s);
690 break;
691 case isl_schedule_key_guard:
692 tree = read_guard(s);
693 break;
694 case isl_schedule_key_leaf:
695 isl_token_free(isl_stream_next_token(s));
696 tree = isl_schedule_tree_leaf(isl_stream_get_ctx(s));
697 break;
698 case isl_schedule_key_mark:
699 tree = read_mark(s);
700 break;
701 case isl_schedule_key_sequence:
702 tree = read_sequence(s);
703 break;
704 case isl_schedule_key_set:
705 tree = read_set(s);
706 break;
707 case isl_schedule_key_schedule:
708 case isl_schedule_key_coincident:
709 case isl_schedule_key_options:
710 case isl_schedule_key_permutable:
711 tree = read_band(s);
712 break;
713 case isl_schedule_key_child:
714 isl_die(isl_stream_get_ctx(s), isl_error_unsupported,
715 "cannot identity node type", return NULL);
716 case isl_schedule_key_end:
717 case isl_schedule_key_error:
718 return NULL;
721 if (isl_stream_yaml_read_end_mapping(s) < 0) {
722 isl_stream_error(s, NULL, "unexpected extra elements");
723 return isl_schedule_tree_free(tree);
726 return tree;
729 /* Read an isl_schedule from "s".
731 __isl_give isl_schedule *isl_stream_read_schedule(isl_stream *s)
733 isl_ctx *ctx;
734 isl_schedule_tree *tree;
736 if (!s)
737 return NULL;
739 ctx = isl_stream_get_ctx(s);
740 tree = isl_stream_read_schedule_tree(s);
741 return isl_schedule_from_schedule_tree(ctx, tree);
744 /* Read an isl_schedule from "input".
746 __isl_give isl_schedule *isl_schedule_read_from_file(isl_ctx *ctx, FILE *input)
748 struct isl_stream *s;
749 isl_schedule *schedule;
751 s = isl_stream_new_file(ctx, input);
752 if (!s)
753 return NULL;
754 schedule = isl_stream_read_schedule(s);
755 isl_stream_free(s);
757 return schedule;
760 /* Read an isl_schedule from "str".
762 __isl_give isl_schedule *isl_schedule_read_from_str(isl_ctx *ctx,
763 const char *str)
765 struct isl_stream *s;
766 isl_schedule *schedule;
768 s = isl_stream_new_str(ctx, str);
769 if (!s)
770 return NULL;
771 schedule = isl_stream_read_schedule(s);
772 isl_stream_free(s);
774 return schedule;