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
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
,
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",
52 #define KEY enum isl_schedule_key
54 #define KEY_ERROR isl_schedule_key_error
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
;
69 struct isl_token
*tok
;
70 enum isl_schedule_key key
;
74 ctx
= isl_stream_get_ctx(s
);
78 if (isl_stream_yaml_next(s
) < 0)
81 tok
= isl_stream_next_token(s
);
83 isl_stream_error(s
, NULL
, "unexpected EOF");
86 str
= isl_token_get_str(ctx
, tok
);
87 context
= isl_set_read_from_str(ctx
, str
);
91 more
= isl_stream_yaml_next(s
);
95 tree
= isl_schedule_tree_from_context(context
);
98 if (key
!= isl_schedule_key_child
)
99 isl_die(ctx
, isl_error_invalid
, "expecting child",
101 if (isl_stream_yaml_next(s
) < 0)
103 tree
= isl_stream_read_schedule_tree(s
);
104 tree
= isl_schedule_tree_insert_context(tree
, context
);
109 isl_set_free(context
);
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
;
120 struct isl_token
*tok
;
121 enum isl_schedule_key key
;
125 ctx
= isl_stream_get_ctx(s
);
129 if (isl_stream_yaml_next(s
) < 0)
132 tok
= isl_stream_next_token(s
);
134 isl_stream_error(s
, NULL
, "unexpected EOF");
137 str
= isl_token_get_str(ctx
, tok
);
138 domain
= isl_union_set_read_from_str(ctx
, str
);
142 more
= isl_stream_yaml_next(s
);
146 tree
= isl_schedule_tree_from_domain(domain
);
149 if (key
!= isl_schedule_key_child
)
150 isl_die(ctx
, isl_error_invalid
, "expecting child",
152 if (isl_stream_yaml_next(s
) < 0)
154 tree
= isl_stream_read_schedule_tree(s
);
155 tree
= isl_schedule_tree_insert_domain(tree
, domain
);
160 isl_union_set_free(domain
);
164 /* Read a subtree with expansion root node from "s".
166 static __isl_give isl_schedule_tree
*read_expansion(isl_stream
*s
)
169 isl_union_pw_multi_aff
*contraction
= NULL
;
170 isl_union_map
*expansion
= NULL
;
171 isl_schedule_tree
*tree
= NULL
;
174 ctx
= isl_stream_get_ctx(s
);
177 struct isl_token
*tok
;
178 enum isl_schedule_key key
;
182 if (isl_stream_yaml_next(s
) < 0)
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
,
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
);
207 case isl_schedule_key_child
:
208 isl_schedule_tree_free(tree
);
209 tree
= isl_stream_read_schedule_tree(s
);
214 isl_die(ctx
, isl_error_invalid
, "unexpected key",
217 } while ((more
= isl_stream_yaml_next(s
)) > 0);
223 isl_die(ctx
, isl_error_invalid
, "missing contraction",
226 isl_die(ctx
, isl_error_invalid
, "missing expansion",
230 return isl_schedule_tree_from_expansion(contraction
, expansion
);
231 return isl_schedule_tree_insert_expansion(tree
, contraction
, expansion
);
233 isl_schedule_tree_free(tree
);
234 isl_union_pw_multi_aff_free(contraction
);
235 isl_union_map_free(expansion
);
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
;
246 struct isl_token
*tok
;
247 enum isl_schedule_key key
;
251 ctx
= isl_stream_get_ctx(s
);
255 if (isl_stream_yaml_next(s
) < 0)
258 tok
= isl_stream_next_token(s
);
260 isl_stream_error(s
, NULL
, "unexpected EOF");
263 str
= isl_token_get_str(ctx
, tok
);
264 extension
= isl_union_map_read_from_str(ctx
, str
);
268 more
= isl_stream_yaml_next(s
);
272 tree
= isl_schedule_tree_from_extension(extension
);
275 if (key
!= isl_schedule_key_child
)
276 isl_die(ctx
, isl_error_invalid
, "expecting child",
278 if (isl_stream_yaml_next(s
) < 0)
280 tree
= isl_stream_read_schedule_tree(s
);
281 tree
= isl_schedule_tree_insert_extension(tree
, extension
);
286 isl_union_map_free(extension
);
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
;
297 struct isl_token
*tok
;
298 enum isl_schedule_key key
;
302 ctx
= isl_stream_get_ctx(s
);
306 if (isl_stream_yaml_next(s
) < 0)
309 tok
= isl_stream_next_token(s
);
311 isl_stream_error(s
, NULL
, "unexpected EOF");
314 str
= isl_token_get_str(ctx
, tok
);
315 filter
= isl_union_set_read_from_str(ctx
, str
);
319 more
= isl_stream_yaml_next(s
);
323 tree
= isl_schedule_tree_from_filter(filter
);
326 if (key
!= isl_schedule_key_child
)
327 isl_die(ctx
, isl_error_invalid
, "expecting child",
329 if (isl_stream_yaml_next(s
) < 0)
331 tree
= isl_stream_read_schedule_tree(s
);
332 tree
= isl_schedule_tree_insert_filter(tree
, filter
);
337 isl_union_set_free(filter
);
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
;
348 struct isl_token
*tok
;
349 enum isl_schedule_key key
;
353 ctx
= isl_stream_get_ctx(s
);
357 if (isl_stream_yaml_next(s
) < 0)
360 tok
= isl_stream_next_token(s
);
362 isl_stream_error(s
, NULL
, "unexpected EOF");
365 str
= isl_token_get_str(ctx
, tok
);
366 guard
= isl_set_read_from_str(ctx
, str
);
370 more
= isl_stream_yaml_next(s
);
374 tree
= isl_schedule_tree_from_guard(guard
);
377 if (key
!= isl_schedule_key_child
)
378 isl_die(ctx
, isl_error_invalid
, "expecting child",
380 if (isl_stream_yaml_next(s
) < 0)
382 tree
= isl_stream_read_schedule_tree(s
);
383 tree
= isl_schedule_tree_insert_guard(tree
, guard
);
392 /* Read a subtree with mark root node from "s".
394 static __isl_give isl_schedule_tree
*read_mark(isl_stream
*s
)
397 isl_schedule_tree
*tree
;
399 struct isl_token
*tok
;
400 enum isl_schedule_key key
;
404 ctx
= isl_stream_get_ctx(s
);
408 if (isl_stream_yaml_next(s
) < 0)
411 tok
= isl_stream_next_token(s
);
413 isl_stream_error(s
, NULL
, "unexpected EOF");
416 str
= isl_token_get_str(ctx
, tok
);
417 mark
= isl_id_alloc(ctx
, str
, NULL
);
421 more
= isl_stream_yaml_next(s
);
425 isl_die(ctx
, isl_error_invalid
, "expecting child",
429 if (key
!= isl_schedule_key_child
)
430 isl_die(ctx
, isl_error_invalid
, "expecting child",
432 if (isl_stream_yaml_next(s
) < 0)
434 tree
= isl_stream_read_schedule_tree(s
);
435 tree
= isl_schedule_tree_insert_mark(tree
, mark
);
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
)
453 ctx
= isl_stream_get_ctx(s
);
455 if (isl_stream_yaml_read_start_sequence(s
) < 0)
458 list
= isl_val_list_alloc(ctx
, 0);
459 while ((more
= isl_stream_yaml_next(s
)) > 0) {
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
);
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
)
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
) {
487 v
= isl_val_list_get_val(coincident
, i
);
489 band
= isl_schedule_band_free(band
);
490 band
= isl_schedule_band_member_set_coincident(band
, i
,
491 !isl_val_is_zero(v
));
494 isl_val_list_free(coincident
);
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
;
507 isl_schedule_band
*band
;
511 ctx
= isl_stream_get_ctx(s
);
514 struct isl_token
*tok
;
515 enum isl_schedule_key key
;
520 if (isl_stream_yaml_next(s
) < 0)
524 case isl_schedule_key_schedule
:
525 schedule
= isl_multi_union_pw_aff_free(schedule
);
526 tok
= isl_stream_next_token(s
);
528 isl_stream_error(s
, NULL
, "unexpected EOF");
531 str
= isl_token_get_str(ctx
, tok
);
532 schedule
= isl_multi_union_pw_aff_read_from_str(ctx
,
539 case isl_schedule_key_coincident
:
540 coincident
= read_coincident(s
);
544 case isl_schedule_key_permutable
:
545 v
= isl_stream_read_val(s
);
546 permutable
= !isl_val_is_zero(v
);
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
);
559 case isl_schedule_key_child
:
560 isl_schedule_tree_free(tree
);
561 tree
= isl_stream_read_schedule_tree(s
);
566 isl_die(ctx
, isl_error_invalid
, "unexpected key",
569 } while ((more
= isl_stream_yaml_next(s
)) > 0);
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
);
580 band
= set_coincident(band
, coincident
);
582 band
= isl_schedule_band_set_ast_build_options(band
, options
);
584 tree
= isl_schedule_tree_insert_band(tree
, band
);
586 tree
= isl_schedule_tree_from_band(band
);
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
);
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
)
604 isl_schedule_tree_list
*list
;
607 ctx
= isl_stream_get_ctx(s
);
609 isl_token_free(isl_stream_next_token(s
));
611 if (isl_stream_yaml_next(s
) < 0)
614 if (isl_stream_yaml_read_start_sequence(s
))
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
;
659 if (isl_stream_yaml_read_start_mapping(s
))
661 more
= isl_stream_yaml_next(s
);
665 isl_stream_error(s
, NULL
, "missing key");
669 tok
= isl_stream_next_token(s
);
670 key
= extract_key(s
, tok
);
671 isl_stream_push_token(s
, tok
);
675 case isl_schedule_key_context
:
676 tree
= read_context(s
);
678 case isl_schedule_key_domain
:
679 tree
= read_domain(s
);
681 case isl_schedule_key_contraction
:
682 case isl_schedule_key_expansion
:
683 tree
= read_expansion(s
);
685 case isl_schedule_key_extension
:
686 tree
= read_extension(s
);
688 case isl_schedule_key_filter
:
689 tree
= read_filter(s
);
691 case isl_schedule_key_guard
:
692 tree
= read_guard(s
);
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
));
698 case isl_schedule_key_mark
:
701 case isl_schedule_key_sequence
:
702 tree
= read_sequence(s
);
704 case isl_schedule_key_set
:
707 case isl_schedule_key_schedule
:
708 case isl_schedule_key_coincident
:
709 case isl_schedule_key_options
:
710 case isl_schedule_key_permutable
:
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
:
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
);
729 /* Read an isl_schedule from "s".
731 __isl_give isl_schedule
*isl_stream_read_schedule(isl_stream
*s
)
734 isl_schedule_tree
*tree
;
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
);
754 schedule
= isl_stream_read_schedule(s
);
760 /* Read an isl_schedule from "str".
762 __isl_give isl_schedule
*isl_schedule_read_from_str(isl_ctx
*ctx
,
765 struct isl_stream
*s
;
766 isl_schedule
*schedule
;
768 s
= isl_stream_new_str(ctx
, str
);
771 schedule
= isl_stream_read_schedule(s
);