add isl_basic_set_var_offset
[isl.git] / isl_schedule_read.c
blob9b81e391ef87100b09f7b9ed0df4750b9d08c814
1 #include <isl/id.h>
2 #include <isl/val.h>
3 #include <isl/schedule.h>
4 #include <isl/stream.h>
5 #include <isl_schedule_private.h>
6 #include <isl_schedule_tree.h>
8 /* An enumeration of the various keys that may appear in a YAML mapping
9 * of a schedule.
11 enum isl_schedule_key {
12 isl_schedule_key_error = -1,
13 isl_schedule_key_child,
14 isl_schedule_key_coincident,
15 isl_schedule_key_context,
16 isl_schedule_key_contraction,
17 isl_schedule_key_domain,
18 isl_schedule_key_expansion,
19 isl_schedule_key_extension,
20 isl_schedule_key_filter,
21 isl_schedule_key_guard,
22 isl_schedule_key_leaf,
23 isl_schedule_key_mark,
24 isl_schedule_key_options,
25 isl_schedule_key_permutable,
26 isl_schedule_key_schedule,
27 isl_schedule_key_sequence,
28 isl_schedule_key_set,
29 isl_schedule_key_end
32 /* Textual representations of the YAML keys for an isl_schedule object.
34 static char *key_str[] = {
35 [isl_schedule_key_child] = "child",
36 [isl_schedule_key_coincident] = "coincident",
37 [isl_schedule_key_context] = "context",
38 [isl_schedule_key_contraction] = "contraction",
39 [isl_schedule_key_domain] = "domain",
40 [isl_schedule_key_expansion] = "expansion",
41 [isl_schedule_key_extension] = "extension",
42 [isl_schedule_key_filter] = "filter",
43 [isl_schedule_key_guard] = "guard",
44 [isl_schedule_key_leaf] = "leaf",
45 [isl_schedule_key_mark] = "mark",
46 [isl_schedule_key_options] = "options",
47 [isl_schedule_key_permutable] = "permutable",
48 [isl_schedule_key_schedule] = "schedule",
49 [isl_schedule_key_sequence] = "sequence",
50 [isl_schedule_key_set] = "set",
53 #undef KEY
54 #define KEY enum isl_schedule_key
55 #undef KEY_ERROR
56 #define KEY_ERROR isl_schedule_key_error
57 #undef KEY_END
58 #define KEY_END isl_schedule_key_end
59 #include "extract_key.c"
61 static __isl_give isl_schedule_tree *isl_stream_read_schedule_tree(
62 __isl_keep isl_stream *s);
64 /* Read a subtree with context root node from "s".
66 static __isl_give isl_schedule_tree *read_context(__isl_keep isl_stream *s)
68 isl_set *context = NULL;
69 isl_schedule_tree *tree;
70 isl_ctx *ctx;
71 struct isl_token *tok;
72 enum isl_schedule_key key;
73 char *str;
74 int more;
76 ctx = isl_stream_get_ctx(s);
78 key = get_key(s);
80 if (isl_stream_yaml_next(s) < 0)
81 return NULL;
83 tok = isl_stream_next_token(s);
84 if (!tok) {
85 isl_stream_error(s, NULL, "unexpected EOF");
86 return NULL;
88 str = isl_token_get_str(ctx, tok);
89 context = isl_set_read_from_str(ctx, str);
90 free(str);
91 isl_token_free(tok);
93 more = isl_stream_yaml_next(s);
94 if (more < 0)
95 goto error;
96 if (!more) {
97 tree = isl_schedule_tree_from_context(context);
98 } else {
99 key = get_key(s);
100 if (key != isl_schedule_key_child)
101 isl_die(ctx, isl_error_invalid, "expecting child",
102 goto error);
103 if (isl_stream_yaml_next(s) < 0)
104 goto error;
105 tree = isl_stream_read_schedule_tree(s);
106 tree = isl_schedule_tree_insert_context(tree, context);
109 return tree;
110 error:
111 isl_set_free(context);
112 return NULL;
115 /* Read a subtree with domain root node from "s".
117 static __isl_give isl_schedule_tree *read_domain(__isl_keep isl_stream *s)
119 isl_union_set *domain = NULL;
120 isl_schedule_tree *tree;
121 isl_ctx *ctx;
122 struct isl_token *tok;
123 enum isl_schedule_key key;
124 char *str;
125 int more;
127 ctx = isl_stream_get_ctx(s);
129 key = get_key(s);
131 if (isl_stream_yaml_next(s) < 0)
132 return NULL;
134 tok = isl_stream_next_token(s);
135 if (!tok) {
136 isl_stream_error(s, NULL, "unexpected EOF");
137 return NULL;
139 str = isl_token_get_str(ctx, tok);
140 domain = isl_union_set_read_from_str(ctx, str);
141 free(str);
142 isl_token_free(tok);
144 more = isl_stream_yaml_next(s);
145 if (more < 0)
146 goto error;
147 if (!more) {
148 tree = isl_schedule_tree_from_domain(domain);
149 } else {
150 key = get_key(s);
151 if (key != isl_schedule_key_child)
152 isl_die(ctx, isl_error_invalid, "expecting child",
153 goto error);
154 if (isl_stream_yaml_next(s) < 0)
155 goto error;
156 tree = isl_stream_read_schedule_tree(s);
157 tree = isl_schedule_tree_insert_domain(tree, domain);
160 return tree;
161 error:
162 isl_union_set_free(domain);
163 return NULL;
166 /* Read a subtree with expansion root node from "s".
168 static __isl_give isl_schedule_tree *read_expansion(isl_stream *s)
170 isl_ctx *ctx;
171 isl_union_pw_multi_aff *contraction = NULL;
172 isl_union_map *expansion = NULL;
173 isl_schedule_tree *tree = NULL;
174 int more;
176 ctx = isl_stream_get_ctx(s);
178 do {
179 struct isl_token *tok;
180 enum isl_schedule_key key;
181 char *str;
183 key = get_key(s);
184 if (isl_stream_yaml_next(s) < 0)
185 goto error;
187 switch (key) {
188 case isl_schedule_key_contraction:
189 isl_union_pw_multi_aff_free(contraction);
190 tok = isl_stream_next_token(s);
191 str = isl_token_get_str(ctx, tok);
192 contraction = isl_union_pw_multi_aff_read_from_str(ctx,
193 str);
194 free(str);
195 isl_token_free(tok);
196 if (!contraction)
197 goto error;
198 break;
199 case isl_schedule_key_expansion:
200 isl_union_map_free(expansion);
201 tok = isl_stream_next_token(s);
202 str = isl_token_get_str(ctx, tok);
203 expansion = isl_union_map_read_from_str(ctx, str);
204 free(str);
205 isl_token_free(tok);
206 if (!expansion)
207 goto error;
208 break;
209 case isl_schedule_key_child:
210 isl_schedule_tree_free(tree);
211 tree = isl_stream_read_schedule_tree(s);
212 if (!tree)
213 goto error;
214 break;
215 default:
216 isl_die(ctx, isl_error_invalid, "unexpected key",
217 goto error);
219 } while ((more = isl_stream_yaml_next(s)) > 0);
221 if (more < 0)
222 goto error;
224 if (!contraction)
225 isl_die(ctx, isl_error_invalid, "missing contraction",
226 goto error);
227 if (!expansion)
228 isl_die(ctx, isl_error_invalid, "missing expansion",
229 goto error);
231 if (!tree)
232 return isl_schedule_tree_from_expansion(contraction, expansion);
233 return isl_schedule_tree_insert_expansion(tree, contraction, expansion);
234 error:
235 isl_schedule_tree_free(tree);
236 isl_union_pw_multi_aff_free(contraction);
237 isl_union_map_free(expansion);
238 return NULL;
241 /* Read a subtree with extension root node from "s".
243 static __isl_give isl_schedule_tree *read_extension(isl_stream *s)
245 isl_union_map *extension = NULL;
246 isl_schedule_tree *tree;
247 isl_ctx *ctx;
248 struct isl_token *tok;
249 enum isl_schedule_key key;
250 char *str;
251 int more;
253 ctx = isl_stream_get_ctx(s);
255 key = get_key(s);
257 if (isl_stream_yaml_next(s) < 0)
258 return NULL;
260 tok = isl_stream_next_token(s);
261 if (!tok) {
262 isl_stream_error(s, NULL, "unexpected EOF");
263 return NULL;
265 str = isl_token_get_str(ctx, tok);
266 extension = isl_union_map_read_from_str(ctx, str);
267 free(str);
268 isl_token_free(tok);
270 more = isl_stream_yaml_next(s);
271 if (more < 0)
272 goto error;
273 if (!more) {
274 tree = isl_schedule_tree_from_extension(extension);
275 } else {
276 key = get_key(s);
277 if (key != isl_schedule_key_child)
278 isl_die(ctx, isl_error_invalid, "expecting child",
279 goto error);
280 if (isl_stream_yaml_next(s) < 0)
281 goto error;
282 tree = isl_stream_read_schedule_tree(s);
283 tree = isl_schedule_tree_insert_extension(tree, extension);
286 return tree;
287 error:
288 isl_union_map_free(extension);
289 return NULL;
292 /* Read a subtree with filter root node from "s".
294 static __isl_give isl_schedule_tree *read_filter(__isl_keep isl_stream *s)
296 isl_union_set *filter = NULL;
297 isl_schedule_tree *tree;
298 isl_ctx *ctx;
299 struct isl_token *tok;
300 enum isl_schedule_key key;
301 char *str;
302 int more;
304 ctx = isl_stream_get_ctx(s);
306 key = get_key(s);
308 if (isl_stream_yaml_next(s) < 0)
309 return NULL;
311 tok = isl_stream_next_token(s);
312 if (!tok) {
313 isl_stream_error(s, NULL, "unexpected EOF");
314 return NULL;
316 str = isl_token_get_str(ctx, tok);
317 filter = isl_union_set_read_from_str(ctx, str);
318 free(str);
319 isl_token_free(tok);
321 more = isl_stream_yaml_next(s);
322 if (more < 0)
323 goto error;
324 if (!more) {
325 tree = isl_schedule_tree_from_filter(filter);
326 } else {
327 key = get_key(s);
328 if (key != isl_schedule_key_child)
329 isl_die(ctx, isl_error_invalid, "expecting child",
330 goto error);
331 if (isl_stream_yaml_next(s) < 0)
332 goto error;
333 tree = isl_stream_read_schedule_tree(s);
334 tree = isl_schedule_tree_insert_filter(tree, filter);
337 return tree;
338 error:
339 isl_union_set_free(filter);
340 return NULL;
343 /* Read a subtree with guard root node from "s".
345 static __isl_give isl_schedule_tree *read_guard(isl_stream *s)
347 isl_set *guard = NULL;
348 isl_schedule_tree *tree;
349 isl_ctx *ctx;
350 struct isl_token *tok;
351 enum isl_schedule_key key;
352 char *str;
353 int more;
355 ctx = isl_stream_get_ctx(s);
357 key = get_key(s);
359 if (isl_stream_yaml_next(s) < 0)
360 return NULL;
362 tok = isl_stream_next_token(s);
363 if (!tok) {
364 isl_stream_error(s, NULL, "unexpected EOF");
365 return NULL;
367 str = isl_token_get_str(ctx, tok);
368 guard = isl_set_read_from_str(ctx, str);
369 free(str);
370 isl_token_free(tok);
372 more = isl_stream_yaml_next(s);
373 if (more < 0)
374 goto error;
375 if (!more) {
376 tree = isl_schedule_tree_from_guard(guard);
377 } else {
378 key = get_key(s);
379 if (key != isl_schedule_key_child)
380 isl_die(ctx, isl_error_invalid, "expecting child",
381 goto error);
382 if (isl_stream_yaml_next(s) < 0)
383 goto error;
384 tree = isl_stream_read_schedule_tree(s);
385 tree = isl_schedule_tree_insert_guard(tree, guard);
388 return tree;
389 error:
390 isl_set_free(guard);
391 return NULL;
394 /* Read a subtree with mark root node from "s".
396 static __isl_give isl_schedule_tree *read_mark(isl_stream *s)
398 isl_id *mark;
399 isl_schedule_tree *tree;
400 isl_ctx *ctx;
401 struct isl_token *tok;
402 enum isl_schedule_key key;
403 char *str;
404 int more;
406 ctx = isl_stream_get_ctx(s);
408 key = get_key(s);
410 if (isl_stream_yaml_next(s) < 0)
411 return NULL;
413 tok = isl_stream_next_token(s);
414 if (!tok) {
415 isl_stream_error(s, NULL, "unexpected EOF");
416 return NULL;
418 str = isl_token_get_str(ctx, tok);
419 mark = isl_id_alloc(ctx, str, NULL);
420 free(str);
421 isl_token_free(tok);
423 more = isl_stream_yaml_next(s);
424 if (more < 0)
425 goto error;
426 if (!more) {
427 isl_die(ctx, isl_error_invalid, "expecting child",
428 goto error);
429 } else {
430 key = get_key(s);
431 if (key != isl_schedule_key_child)
432 isl_die(ctx, isl_error_invalid, "expecting child",
433 goto error);
434 if (isl_stream_yaml_next(s) < 0)
435 goto error;
436 tree = isl_stream_read_schedule_tree(s);
437 tree = isl_schedule_tree_insert_mark(tree, mark);
440 return tree;
441 error:
442 isl_id_free(mark);
443 return NULL;
446 /* Read a sequence of integers from "s" (representing the coincident
447 * property of a band node).
449 static __isl_give isl_val_list *read_coincident(__isl_keep isl_stream *s)
451 isl_ctx *ctx;
452 isl_val_list *list;
453 int more;
455 ctx = isl_stream_get_ctx(s);
457 if (isl_stream_yaml_read_start_sequence(s) < 0)
458 return NULL;
460 list = isl_val_list_alloc(ctx, 0);
461 while ((more = isl_stream_yaml_next(s)) > 0) {
462 isl_val *val;
464 val = isl_stream_read_val(s);
465 list = isl_val_list_add(list, val);
468 if (more < 0 || isl_stream_yaml_read_end_sequence(s))
469 list = isl_val_list_free(list);
471 return list;
474 /* Set the (initial) coincident properties of "band" according to
475 * the (initial) elements of "coincident".
477 static __isl_give isl_schedule_band *set_coincident(
478 __isl_take isl_schedule_band *band, __isl_take isl_val_list *coincident)
480 int i;
481 int n, m;
483 n = isl_schedule_band_n_member(band);
484 m = isl_val_list_n_val(coincident);
486 for (i = 0; i < n && i < m; ++i) {
487 isl_val *v;
489 v = isl_val_list_get_val(coincident, i);
490 if (!v)
491 band = isl_schedule_band_free(band);
492 band = isl_schedule_band_member_set_coincident(band, i,
493 !isl_val_is_zero(v));
494 isl_val_free(v);
496 isl_val_list_free(coincident);
497 return band;
500 /* Read a subtree with band root node from "s".
502 static __isl_give isl_schedule_tree *read_band(isl_stream *s)
504 isl_multi_union_pw_aff *schedule = NULL;
505 isl_schedule_tree *tree = NULL;
506 isl_val_list *coincident = NULL;
507 isl_union_set *options = NULL;
508 isl_ctx *ctx;
509 isl_schedule_band *band;
510 int permutable = 0;
511 int more;
513 ctx = isl_stream_get_ctx(s);
515 do {
516 struct isl_token *tok;
517 enum isl_schedule_key key;
518 char *str;
519 isl_val *v;
521 key = get_key(s);
522 if (isl_stream_yaml_next(s) < 0)
523 goto error;
525 switch (key) {
526 case isl_schedule_key_schedule:
527 schedule = isl_multi_union_pw_aff_free(schedule);
528 tok = isl_stream_next_token(s);
529 if (!tok) {
530 isl_stream_error(s, NULL, "unexpected EOF");
531 goto error;
533 str = isl_token_get_str(ctx, tok);
534 schedule = isl_multi_union_pw_aff_read_from_str(ctx,
535 str);
536 free(str);
537 isl_token_free(tok);
538 if (!schedule)
539 goto error;
540 break;
541 case isl_schedule_key_coincident:
542 coincident = read_coincident(s);
543 if (!coincident)
544 goto error;
545 break;
546 case isl_schedule_key_permutable:
547 v = isl_stream_read_val(s);
548 permutable = !isl_val_is_zero(v);
549 isl_val_free(v);
550 break;
551 case isl_schedule_key_options:
552 isl_union_set_free(options);
553 tok = isl_stream_next_token(s);
554 str = isl_token_get_str(ctx, tok);
555 options = isl_union_set_read_from_str(ctx, str);
556 free(str);
557 isl_token_free(tok);
558 if (!options)
559 goto error;
560 break;
561 case isl_schedule_key_child:
562 isl_schedule_tree_free(tree);
563 tree = isl_stream_read_schedule_tree(s);
564 if (!tree)
565 goto error;
566 break;
567 default:
568 isl_die(ctx, isl_error_invalid, "unexpected key",
569 goto error);
571 } while ((more = isl_stream_yaml_next(s)) > 0);
573 if (more < 0)
574 goto error;
576 if (!schedule)
577 isl_die(ctx, isl_error_invalid, "missing schedule", goto error);
579 band = isl_schedule_band_from_multi_union_pw_aff(schedule);
580 band = isl_schedule_band_set_permutable(band, permutable);
581 if (coincident)
582 band = set_coincident(band, coincident);
583 if (options)
584 band = isl_schedule_band_set_ast_build_options(band, options);
585 if (tree)
586 tree = isl_schedule_tree_insert_band(tree, band);
587 else
588 tree = isl_schedule_tree_from_band(band);
590 return tree;
591 error:
592 isl_val_list_free(coincident);
593 isl_union_set_free(options);
594 isl_schedule_tree_free(tree);
595 isl_multi_union_pw_aff_free(schedule);
596 return NULL;
599 /* Read a subtree with root node of type "type" from "s".
600 * The node is represented by a sequence of children.
602 static __isl_give isl_schedule_tree *read_children(isl_stream *s,
603 enum isl_schedule_node_type type)
605 isl_ctx *ctx;
606 isl_schedule_tree_list *list;
607 int more;
609 ctx = isl_stream_get_ctx(s);
611 isl_token_free(isl_stream_next_token(s));
613 if (isl_stream_yaml_next(s) < 0)
614 return NULL;
616 if (isl_stream_yaml_read_start_sequence(s))
617 return NULL;
619 list = isl_schedule_tree_list_alloc(ctx, 0);
620 while ((more = isl_stream_yaml_next(s)) > 0) {
621 isl_schedule_tree *tree;
623 tree = isl_stream_read_schedule_tree(s);
624 list = isl_schedule_tree_list_add(list, tree);
627 if (more < 0 || isl_stream_yaml_read_end_sequence(s))
628 list = isl_schedule_tree_list_free(list);
630 return isl_schedule_tree_from_children(type, list);
633 /* Read a subtree with sequence root node from "s".
635 static __isl_give isl_schedule_tree *read_sequence(isl_stream *s)
637 return read_children(s, isl_schedule_node_sequence);
640 /* Read a subtree with set root node from "s".
642 static __isl_give isl_schedule_tree *read_set(isl_stream *s)
644 return read_children(s, isl_schedule_node_set);
647 /* Read a schedule (sub)tree from "s".
649 * We first determine the type of the root node based on the first
650 * mapping key and then hand over to a function tailored to reading
651 * nodes of this type.
653 static __isl_give isl_schedule_tree *isl_stream_read_schedule_tree(
654 struct isl_stream *s)
656 enum isl_schedule_key key;
657 struct isl_token *tok;
658 isl_schedule_tree *tree = NULL;
659 int more;
661 if (isl_stream_yaml_read_start_mapping(s))
662 return NULL;
663 more = isl_stream_yaml_next(s);
664 if (more < 0)
665 return NULL;
666 if (!more) {
667 isl_stream_error(s, NULL, "missing key");
668 return NULL;
671 tok = isl_stream_next_token(s);
672 key = extract_key(s, tok);
673 isl_stream_push_token(s, tok);
674 if (key < 0)
675 return NULL;
676 switch (key) {
677 case isl_schedule_key_context:
678 tree = read_context(s);
679 break;
680 case isl_schedule_key_domain:
681 tree = read_domain(s);
682 break;
683 case isl_schedule_key_contraction:
684 case isl_schedule_key_expansion:
685 tree = read_expansion(s);
686 break;
687 case isl_schedule_key_extension:
688 tree = read_extension(s);
689 break;
690 case isl_schedule_key_filter:
691 tree = read_filter(s);
692 break;
693 case isl_schedule_key_guard:
694 tree = read_guard(s);
695 break;
696 case isl_schedule_key_leaf:
697 isl_token_free(isl_stream_next_token(s));
698 tree = isl_schedule_tree_leaf(isl_stream_get_ctx(s));
699 break;
700 case isl_schedule_key_mark:
701 tree = read_mark(s);
702 break;
703 case isl_schedule_key_sequence:
704 tree = read_sequence(s);
705 break;
706 case isl_schedule_key_set:
707 tree = read_set(s);
708 break;
709 case isl_schedule_key_schedule:
710 case isl_schedule_key_coincident:
711 case isl_schedule_key_options:
712 case isl_schedule_key_permutable:
713 tree = read_band(s);
714 break;
715 case isl_schedule_key_child:
716 isl_die(isl_stream_get_ctx(s), isl_error_unsupported,
717 "cannot identify node type", return NULL);
718 case isl_schedule_key_end:
719 case isl_schedule_key_error:
720 return NULL;
723 if (isl_stream_yaml_read_end_mapping(s) < 0) {
724 isl_stream_error(s, NULL, "unexpected extra elements");
725 return isl_schedule_tree_free(tree);
728 return tree;
731 /* Read an isl_schedule from "s".
733 __isl_give isl_schedule *isl_stream_read_schedule(isl_stream *s)
735 isl_ctx *ctx;
736 isl_schedule_tree *tree;
738 if (!s)
739 return NULL;
741 ctx = isl_stream_get_ctx(s);
742 tree = isl_stream_read_schedule_tree(s);
743 return isl_schedule_from_schedule_tree(ctx, tree);
746 /* Read an isl_schedule from "input".
748 __isl_give isl_schedule *isl_schedule_read_from_file(isl_ctx *ctx, FILE *input)
750 struct isl_stream *s;
751 isl_schedule *schedule;
753 s = isl_stream_new_file(ctx, input);
754 if (!s)
755 return NULL;
756 schedule = isl_stream_read_schedule(s);
757 isl_stream_free(s);
759 return schedule;
762 /* Read an isl_schedule from "str".
764 __isl_give isl_schedule *isl_schedule_read_from_str(isl_ctx *ctx,
765 const char *str)
767 struct isl_stream *s;
768 isl_schedule *schedule;
770 s = isl_stream_new_str(ctx, str);
771 if (!s)
772 return NULL;
773 schedule = isl_stream_read_schedule(s);
774 isl_stream_free(s);
776 return schedule;