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>
7
8/* An enumeration of the various keys that may appear in a YAML mapping
9 * of a schedule.
10 */
11enum 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
30};
31
32/* Textual representations of the YAML keys for an isl_schedule object.
33 */
34static 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",
51};
52
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#undef KEY_STR
60#define KEY_STR key_str
61#undef KEY_EXTRACT
62#define KEY_EXTRACT extract_key
63#undef KEY_GET
64#define KEY_GET get_key
65#include "extract_key.c"
66
67static __isl_give isl_schedule_tree *isl_stream_read_schedule_tree(
68 __isl_keep isl_stream *s);
69
70/* Read a subtree with context root node from "s".
71 */
72static __isl_give isl_schedule_tree *read_context(__isl_keep isl_stream *s)
73{
74 isl_set *context = NULL;
75 isl_schedule_tree *tree;
76 isl_ctx *ctx;
77 struct isl_token *tok;
78 enum isl_schedule_key key;
79 char *str;
80 isl_bool more;
81
82 ctx = isl_stream_get_ctx(s);
83
84 key = get_key(s);
85
86 if (isl_stream_yaml_next(s) < 0)
87 return NULL;
88
89 tok = isl_stream_next_token(s);
90 if (!tok) {
91 isl_stream_error(s, NULL, msg: "unexpected EOF");
92 return NULL;
93 }
94 str = isl_token_get_str(ctx, tok);
95 context = isl_set_read_from_str(ctx, str);
96 free(ptr: str);
97 isl_token_free(tok);
98
99 more = isl_stream_yaml_next(s);
100 if (more < 0)
101 goto error;
102 if (!more) {
103 tree = isl_schedule_tree_from_context(context);
104 } else {
105 key = get_key(s);
106 if (key != isl_schedule_key_child)
107 isl_die(ctx, isl_error_invalid, "expecting child",
108 goto error);
109 if (isl_stream_yaml_next(s) < 0)
110 goto error;
111 tree = isl_stream_read_schedule_tree(s);
112 tree = isl_schedule_tree_insert_context(tree, context);
113 }
114
115 return tree;
116error:
117 isl_set_free(set: context);
118 return NULL;
119}
120
121/* Read a subtree with domain root node from "s".
122 */
123static __isl_give isl_schedule_tree *read_domain(__isl_keep isl_stream *s)
124{
125 isl_union_set *domain = NULL;
126 isl_schedule_tree *tree;
127 isl_ctx *ctx;
128 struct isl_token *tok;
129 enum isl_schedule_key key;
130 char *str;
131 isl_bool more;
132
133 ctx = isl_stream_get_ctx(s);
134
135 key = get_key(s);
136
137 if (isl_stream_yaml_next(s) < 0)
138 return NULL;
139
140 tok = isl_stream_next_token(s);
141 if (!tok) {
142 isl_stream_error(s, NULL, msg: "unexpected EOF");
143 return NULL;
144 }
145 str = isl_token_get_str(ctx, tok);
146 domain = isl_union_set_read_from_str(ctx, str);
147 free(ptr: str);
148 isl_token_free(tok);
149
150 more = isl_stream_yaml_next(s);
151 if (more < 0)
152 goto error;
153 if (!more) {
154 tree = isl_schedule_tree_from_domain(domain);
155 } else {
156 key = get_key(s);
157 if (key != isl_schedule_key_child)
158 isl_die(ctx, isl_error_invalid, "expecting child",
159 goto error);
160 if (isl_stream_yaml_next(s) < 0)
161 goto error;
162 tree = isl_stream_read_schedule_tree(s);
163 tree = isl_schedule_tree_insert_domain(tree, domain);
164 }
165
166 return tree;
167error:
168 isl_union_set_free(uset: domain);
169 return NULL;
170}
171
172/* Read a subtree with expansion root node from "s".
173 */
174static __isl_give isl_schedule_tree *read_expansion(isl_stream *s)
175{
176 isl_ctx *ctx;
177 isl_union_pw_multi_aff *contraction = NULL;
178 isl_union_map *expansion = NULL;
179 isl_schedule_tree *tree = NULL;
180 isl_bool more;
181
182 ctx = isl_stream_get_ctx(s);
183
184 do {
185 struct isl_token *tok;
186 enum isl_schedule_key key;
187 char *str;
188
189 key = get_key(s);
190 if (isl_stream_yaml_next(s) < 0)
191 goto error;
192
193 switch (key) {
194 case isl_schedule_key_contraction:
195 isl_union_pw_multi_aff_free(upma: contraction);
196 tok = isl_stream_next_token(s);
197 str = isl_token_get_str(ctx, tok);
198 contraction = isl_union_pw_multi_aff_read_from_str(ctx,
199 str);
200 free(ptr: str);
201 isl_token_free(tok);
202 if (!contraction)
203 goto error;
204 break;
205 case isl_schedule_key_expansion:
206 isl_union_map_free(umap: expansion);
207 tok = isl_stream_next_token(s);
208 str = isl_token_get_str(ctx, tok);
209 expansion = isl_union_map_read_from_str(ctx, str);
210 free(ptr: str);
211 isl_token_free(tok);
212 if (!expansion)
213 goto error;
214 break;
215 case isl_schedule_key_child:
216 isl_schedule_tree_free(tree);
217 tree = isl_stream_read_schedule_tree(s);
218 if (!tree)
219 goto error;
220 break;
221 default:
222 isl_die(ctx, isl_error_invalid, "unexpected key",
223 goto error);
224 }
225 } while ((more = isl_stream_yaml_next(s)) == isl_bool_true);
226
227 if (more < 0)
228 goto error;
229
230 if (!contraction)
231 isl_die(ctx, isl_error_invalid, "missing contraction",
232 goto error);
233 if (!expansion)
234 isl_die(ctx, isl_error_invalid, "missing expansion",
235 goto error);
236
237 if (!tree)
238 return isl_schedule_tree_from_expansion(contraction, expansion);
239 return isl_schedule_tree_insert_expansion(tree, contraction, expansion);
240error:
241 isl_schedule_tree_free(tree);
242 isl_union_pw_multi_aff_free(upma: contraction);
243 isl_union_map_free(umap: expansion);
244 return NULL;
245}
246
247/* Read a subtree with extension root node from "s".
248 */
249static __isl_give isl_schedule_tree *read_extension(isl_stream *s)
250{
251 isl_union_map *extension = NULL;
252 isl_schedule_tree *tree;
253 isl_ctx *ctx;
254 struct isl_token *tok;
255 enum isl_schedule_key key;
256 char *str;
257 isl_bool more;
258
259 ctx = isl_stream_get_ctx(s);
260
261 key = get_key(s);
262
263 if (isl_stream_yaml_next(s) < 0)
264 return NULL;
265
266 tok = isl_stream_next_token(s);
267 if (!tok) {
268 isl_stream_error(s, NULL, msg: "unexpected EOF");
269 return NULL;
270 }
271 str = isl_token_get_str(ctx, tok);
272 extension = isl_union_map_read_from_str(ctx, str);
273 free(ptr: str);
274 isl_token_free(tok);
275
276 more = isl_stream_yaml_next(s);
277 if (more < 0)
278 goto error;
279 if (!more) {
280 tree = isl_schedule_tree_from_extension(extension);
281 } else {
282 key = get_key(s);
283 if (key != isl_schedule_key_child)
284 isl_die(ctx, isl_error_invalid, "expecting child",
285 goto error);
286 if (isl_stream_yaml_next(s) < 0)
287 goto error;
288 tree = isl_stream_read_schedule_tree(s);
289 tree = isl_schedule_tree_insert_extension(tree, extension);
290 }
291
292 return tree;
293error:
294 isl_union_map_free(umap: extension);
295 return NULL;
296}
297
298/* Read a subtree with filter root node from "s".
299 */
300static __isl_give isl_schedule_tree *read_filter(__isl_keep isl_stream *s)
301{
302 isl_union_set *filter = NULL;
303 isl_schedule_tree *tree;
304 isl_ctx *ctx;
305 struct isl_token *tok;
306 enum isl_schedule_key key;
307 char *str;
308 isl_bool more;
309
310 ctx = isl_stream_get_ctx(s);
311
312 key = get_key(s);
313
314 if (isl_stream_yaml_next(s) < 0)
315 return NULL;
316
317 tok = isl_stream_next_token(s);
318 if (!tok) {
319 isl_stream_error(s, NULL, msg: "unexpected EOF");
320 return NULL;
321 }
322 str = isl_token_get_str(ctx, tok);
323 filter = isl_union_set_read_from_str(ctx, str);
324 free(ptr: str);
325 isl_token_free(tok);
326
327 more = isl_stream_yaml_next(s);
328 if (more < 0)
329 goto error;
330 if (!more) {
331 tree = isl_schedule_tree_from_filter(filter);
332 } else {
333 key = get_key(s);
334 if (key != isl_schedule_key_child)
335 isl_die(ctx, isl_error_invalid, "expecting child",
336 goto error);
337 if (isl_stream_yaml_next(s) < 0)
338 goto error;
339 tree = isl_stream_read_schedule_tree(s);
340 tree = isl_schedule_tree_insert_filter(tree, filter);
341 }
342
343 return tree;
344error:
345 isl_union_set_free(uset: filter);
346 return NULL;
347}
348
349/* Read a subtree with guard root node from "s".
350 */
351static __isl_give isl_schedule_tree *read_guard(isl_stream *s)
352{
353 isl_set *guard = NULL;
354 isl_schedule_tree *tree;
355 isl_ctx *ctx;
356 struct isl_token *tok;
357 enum isl_schedule_key key;
358 char *str;
359 isl_bool more;
360
361 ctx = isl_stream_get_ctx(s);
362
363 key = get_key(s);
364
365 if (isl_stream_yaml_next(s) < 0)
366 return NULL;
367
368 tok = isl_stream_next_token(s);
369 if (!tok) {
370 isl_stream_error(s, NULL, msg: "unexpected EOF");
371 return NULL;
372 }
373 str = isl_token_get_str(ctx, tok);
374 guard = isl_set_read_from_str(ctx, str);
375 free(ptr: str);
376 isl_token_free(tok);
377
378 more = isl_stream_yaml_next(s);
379 if (more < 0)
380 goto error;
381 if (!more) {
382 tree = isl_schedule_tree_from_guard(guard);
383 } else {
384 key = get_key(s);
385 if (key != isl_schedule_key_child)
386 isl_die(ctx, isl_error_invalid, "expecting child",
387 goto error);
388 if (isl_stream_yaml_next(s) < 0)
389 goto error;
390 tree = isl_stream_read_schedule_tree(s);
391 tree = isl_schedule_tree_insert_guard(tree, guard);
392 }
393
394 return tree;
395error:
396 isl_set_free(set: guard);
397 return NULL;
398}
399
400/* Read a subtree with mark root node from "s".
401 */
402static __isl_give isl_schedule_tree *read_mark(isl_stream *s)
403{
404 isl_id *mark;
405 isl_schedule_tree *tree;
406 isl_ctx *ctx;
407 struct isl_token *tok;
408 enum isl_schedule_key key;
409 char *str;
410 isl_bool more;
411
412 ctx = isl_stream_get_ctx(s);
413
414 key = get_key(s);
415
416 if (isl_stream_yaml_next(s) < 0)
417 return NULL;
418
419 tok = isl_stream_next_token(s);
420 if (!tok) {
421 isl_stream_error(s, NULL, msg: "unexpected EOF");
422 return NULL;
423 }
424 str = isl_token_get_str(ctx, tok);
425 mark = isl_id_alloc(ctx, name: str, NULL);
426 free(ptr: str);
427 isl_token_free(tok);
428
429 more = isl_stream_yaml_next(s);
430 if (more < 0)
431 goto error;
432 if (!more) {
433 isl_die(ctx, isl_error_invalid, "expecting child",
434 goto error);
435 } else {
436 key = get_key(s);
437 if (key != isl_schedule_key_child)
438 isl_die(ctx, isl_error_invalid, "expecting child",
439 goto error);
440 if (isl_stream_yaml_next(s) < 0)
441 goto error;
442 tree = isl_stream_read_schedule_tree(s);
443 tree = isl_schedule_tree_insert_mark(tree, mark);
444 }
445
446 return tree;
447error:
448 isl_id_free(id: mark);
449 return NULL;
450}
451
452#undef EL_BASE
453#define EL_BASE val
454
455#include <isl_list_read_yaml_templ.c>
456
457/* Read a sequence of integers from "s" (representing the coincident
458 * property of a band node).
459 */
460static __isl_give isl_val_list *read_coincident(__isl_keep isl_stream *s)
461{
462 return isl_stream_yaml_read_val_list(s);
463}
464
465/* Set the (initial) coincident properties of "band" according to
466 * the (initial) elements of "coincident".
467 */
468static __isl_give isl_schedule_band *set_coincident(
469 __isl_take isl_schedule_band *band, __isl_take isl_val_list *coincident)
470{
471 int i;
472 isl_size n, m;
473
474 n = isl_schedule_band_n_member(band);
475 m = isl_val_list_n_val(list: coincident);
476 if (n < 0 || m < 0)
477 band = isl_schedule_band_free(band);
478
479 for (i = 0; i < n && i < m; ++i) {
480 isl_val *v;
481
482 v = isl_val_list_get_val(list: coincident, index: i);
483 if (!v)
484 band = isl_schedule_band_free(band);
485 band = isl_schedule_band_member_set_coincident(band, pos: i,
486 coincident: !isl_val_is_zero(v));
487 isl_val_free(v);
488 }
489 isl_val_list_free(list: coincident);
490 return band;
491}
492
493/* Read a subtree with band root node from "s".
494 */
495static __isl_give isl_schedule_tree *read_band(isl_stream *s)
496{
497 isl_multi_union_pw_aff *schedule = NULL;
498 isl_schedule_tree *tree = NULL;
499 isl_val_list *coincident = NULL;
500 isl_union_set *options = NULL;
501 isl_ctx *ctx;
502 isl_schedule_band *band;
503 int permutable = 0;
504 isl_bool more;
505
506 ctx = isl_stream_get_ctx(s);
507
508 do {
509 struct isl_token *tok;
510 enum isl_schedule_key key;
511 char *str;
512 isl_val *v;
513
514 key = get_key(s);
515 if (isl_stream_yaml_next(s) < 0)
516 goto error;
517
518 switch (key) {
519 case isl_schedule_key_schedule:
520 schedule = isl_multi_union_pw_aff_free(multi: schedule);
521 tok = isl_stream_next_token(s);
522 if (!tok) {
523 isl_stream_error(s, NULL, msg: "unexpected EOF");
524 goto error;
525 }
526 str = isl_token_get_str(ctx, tok);
527 schedule = isl_multi_union_pw_aff_read_from_str(ctx,
528 str);
529 free(ptr: str);
530 isl_token_free(tok);
531 if (!schedule)
532 goto error;
533 break;
534 case isl_schedule_key_coincident:
535 coincident = read_coincident(s);
536 if (!coincident)
537 goto error;
538 break;
539 case isl_schedule_key_permutable:
540 v = isl_stream_read_val(s);
541 permutable = !isl_val_is_zero(v);
542 isl_val_free(v);
543 break;
544 case isl_schedule_key_options:
545 isl_union_set_free(uset: options);
546 tok = isl_stream_next_token(s);
547 str = isl_token_get_str(ctx, tok);
548 options = isl_union_set_read_from_str(ctx, str);
549 free(ptr: str);
550 isl_token_free(tok);
551 if (!options)
552 goto error;
553 break;
554 case isl_schedule_key_child:
555 isl_schedule_tree_free(tree);
556 tree = isl_stream_read_schedule_tree(s);
557 if (!tree)
558 goto error;
559 break;
560 default:
561 isl_die(ctx, isl_error_invalid, "unexpected key",
562 goto error);
563 }
564 } while ((more = isl_stream_yaml_next(s)) == isl_bool_true);
565
566 if (more < 0)
567 goto error;
568
569 if (!schedule)
570 isl_die(ctx, isl_error_invalid, "missing schedule", goto error);
571
572 band = isl_schedule_band_from_multi_union_pw_aff(mupa: schedule);
573 band = isl_schedule_band_set_permutable(band, permutable);
574 if (coincident)
575 band = set_coincident(band, coincident);
576 if (options)
577 band = isl_schedule_band_set_ast_build_options(band, options);
578 if (tree)
579 tree = isl_schedule_tree_insert_band(tree, band);
580 else
581 tree = isl_schedule_tree_from_band(band);
582
583 return tree;
584error:
585 isl_val_list_free(list: coincident);
586 isl_union_set_free(uset: options);
587 isl_schedule_tree_free(tree);
588 isl_multi_union_pw_aff_free(multi: schedule);
589 return NULL;
590}
591
592#undef EL_BASE
593#define EL_BASE schedule_tree
594
595#include <isl_list_read_yaml_templ.c>
596
597/* Read a subtree with root node of type "type" from "s".
598 * The node is represented by a sequence of children.
599 */
600static __isl_give isl_schedule_tree *read_children(isl_stream *s,
601 enum isl_schedule_node_type type)
602{
603 isl_schedule_tree_list *list;
604
605 isl_token_free(tok: isl_stream_next_token(s));
606
607 if (isl_stream_yaml_next(s) < 0)
608 return NULL;
609
610 list = isl_stream_yaml_read_schedule_tree_list(s);
611
612 return isl_schedule_tree_from_children(type, list);
613}
614
615/* Read a subtree with sequence root node from "s".
616 */
617static __isl_give isl_schedule_tree *read_sequence(isl_stream *s)
618{
619 return read_children(s, type: isl_schedule_node_sequence);
620}
621
622/* Read a subtree with set root node from "s".
623 */
624static __isl_give isl_schedule_tree *read_set(isl_stream *s)
625{
626 return read_children(s, type: isl_schedule_node_set);
627}
628
629/* Read a schedule (sub)tree from "s".
630 *
631 * We first determine the type of the root node based on the first
632 * mapping key and then hand over to a function tailored to reading
633 * nodes of this type.
634 */
635static __isl_give isl_schedule_tree *isl_stream_read_schedule_tree(
636 struct isl_stream *s)
637{
638 enum isl_schedule_key key;
639 struct isl_token *tok;
640 isl_schedule_tree *tree = NULL;
641 isl_bool more;
642
643 if (isl_stream_yaml_read_start_mapping(s) < 0)
644 return NULL;
645 more = isl_stream_yaml_next(s);
646 if (more < 0)
647 return NULL;
648 if (!more) {
649 isl_stream_error(s, NULL, msg: "missing key");
650 return NULL;
651 }
652
653 tok = isl_stream_next_token(s);
654 key = extract_key(s, tok);
655 isl_stream_push_token(s, tok);
656 if (key < 0)
657 return NULL;
658 switch (key) {
659 case isl_schedule_key_context:
660 tree = read_context(s);
661 break;
662 case isl_schedule_key_domain:
663 tree = read_domain(s);
664 break;
665 case isl_schedule_key_contraction:
666 case isl_schedule_key_expansion:
667 tree = read_expansion(s);
668 break;
669 case isl_schedule_key_extension:
670 tree = read_extension(s);
671 break;
672 case isl_schedule_key_filter:
673 tree = read_filter(s);
674 break;
675 case isl_schedule_key_guard:
676 tree = read_guard(s);
677 break;
678 case isl_schedule_key_leaf:
679 isl_token_free(tok: isl_stream_next_token(s));
680 tree = isl_schedule_tree_leaf(ctx: isl_stream_get_ctx(s));
681 break;
682 case isl_schedule_key_mark:
683 tree = read_mark(s);
684 break;
685 case isl_schedule_key_sequence:
686 tree = read_sequence(s);
687 break;
688 case isl_schedule_key_set:
689 tree = read_set(s);
690 break;
691 case isl_schedule_key_schedule:
692 case isl_schedule_key_coincident:
693 case isl_schedule_key_options:
694 case isl_schedule_key_permutable:
695 tree = read_band(s);
696 break;
697 case isl_schedule_key_child:
698 isl_die(isl_stream_get_ctx(s), isl_error_unsupported,
699 "cannot identify node type", return NULL);
700 case isl_schedule_key_end:
701 case isl_schedule_key_error:
702 return NULL;
703 }
704
705 if (isl_stream_yaml_read_end_mapping(s) < 0)
706 return isl_schedule_tree_free(tree);
707
708 return tree;
709}
710
711/* Read an isl_schedule from "s".
712 */
713__isl_give isl_schedule *isl_stream_read_schedule(isl_stream *s)
714{
715 isl_ctx *ctx;
716 isl_schedule_tree *tree;
717
718 if (!s)
719 return NULL;
720
721 ctx = isl_stream_get_ctx(s);
722 tree = isl_stream_read_schedule_tree(s);
723 return isl_schedule_from_schedule_tree(ctx, tree);
724}
725
726/* Read an isl_schedule from "input".
727 */
728__isl_give isl_schedule *isl_schedule_read_from_file(isl_ctx *ctx, FILE *input)
729{
730 struct isl_stream *s;
731 isl_schedule *schedule;
732
733 s = isl_stream_new_file(ctx, file: input);
734 if (!s)
735 return NULL;
736 schedule = isl_stream_read_schedule(s);
737 isl_stream_free(s);
738
739 return schedule;
740}
741
742#undef TYPE_BASE
743#define TYPE_BASE schedule
744#include "isl_read_from_str_templ.c"
745

source code of polly/lib/External/isl/isl_schedule_read.c