2 #include <isl/schedule.h>
3 #include <isl/stream.h>
4 #include <isl_schedule_private.h>
5 #include <isl_schedule_tree.h>
7 /* An enumeration of the various keys that may appear in a YAML mapping
10 enum isl_schedule_key
{
11 isl_schedule_key_error
= -1,
12 isl_schedule_key_child
,
13 isl_schedule_key_coincident
,
14 isl_schedule_key_context
,
15 isl_schedule_key_contraction
,
16 isl_schedule_key_domain
,
17 isl_schedule_key_expansion
,
18 isl_schedule_key_extension
,
19 isl_schedule_key_filter
,
20 isl_schedule_key_guard
,
21 isl_schedule_key_leaf
,
22 isl_schedule_key_mark
,
23 isl_schedule_key_options
,
24 isl_schedule_key_permutable
,
25 isl_schedule_key_schedule
,
26 isl_schedule_key_sequence
,
31 /* Textual representations of the YAML keys for an isl_schedule object.
33 static char *key_str
[] = {
34 [isl_schedule_key_child
] = "child",
35 [isl_schedule_key_coincident
] = "coincident",
36 [isl_schedule_key_context
] = "context",
37 [isl_schedule_key_contraction
] = "contraction",
38 [isl_schedule_key_domain
] = "domain",
39 [isl_schedule_key_expansion
] = "expansion",
40 [isl_schedule_key_extension
] = "extension",
41 [isl_schedule_key_filter
] = "filter",
42 [isl_schedule_key_guard
] = "guard",
43 [isl_schedule_key_leaf
] = "leaf",
44 [isl_schedule_key_mark
] = "mark",
45 [isl_schedule_key_options
] = "options",
46 [isl_schedule_key_permutable
] = "permutable",
47 [isl_schedule_key_schedule
] = "schedule",
48 [isl_schedule_key_sequence
] = "sequence",
49 [isl_schedule_key_set
] = "set",
53 #define KEY enum isl_schedule_key
55 #define KEY_ERROR isl_schedule_key_error
57 #define KEY_END isl_schedule_key_end
58 #include "extract_key.c"
60 static __isl_give isl_schedule_tree
*isl_stream_read_schedule_tree(
61 __isl_keep isl_stream
*s
);
63 /* Read a subtree with context root node from "s".
65 static __isl_give isl_schedule_tree
*read_context(__isl_keep isl_stream
*s
)
67 isl_set
*context
= NULL
;
68 isl_schedule_tree
*tree
;
70 struct isl_token
*tok
;
71 enum isl_schedule_key key
;
75 ctx
= isl_stream_get_ctx(s
);
79 if (isl_stream_yaml_next(s
) < 0)
82 tok
= isl_stream_next_token(s
);
84 isl_stream_error(s
, NULL
, "unexpected EOF");
87 str
= isl_token_get_str(ctx
, tok
);
88 context
= isl_set_read_from_str(ctx
, str
);
92 more
= isl_stream_yaml_next(s
);
96 tree
= isl_schedule_tree_from_context(context
);
99 if (key
!= isl_schedule_key_child
)
100 isl_die(ctx
, isl_error_invalid
, "expecting child",
102 if (isl_stream_yaml_next(s
) < 0)
104 tree
= isl_stream_read_schedule_tree(s
);
105 tree
= isl_schedule_tree_insert_context(tree
, context
);
110 isl_set_free(context
);
114 /* Read a subtree with domain root node from "s".
116 static __isl_give isl_schedule_tree
*read_domain(__isl_keep isl_stream
*s
)
118 isl_union_set
*domain
= NULL
;
119 isl_schedule_tree
*tree
;
121 struct isl_token
*tok
;
122 enum isl_schedule_key key
;
126 ctx
= isl_stream_get_ctx(s
);
130 if (isl_stream_yaml_next(s
) < 0)
133 tok
= isl_stream_next_token(s
);
135 isl_stream_error(s
, NULL
, "unexpected EOF");
138 str
= isl_token_get_str(ctx
, tok
);
139 domain
= isl_union_set_read_from_str(ctx
, str
);
143 more
= isl_stream_yaml_next(s
);
147 tree
= isl_schedule_tree_from_domain(domain
);
150 if (key
!= isl_schedule_key_child
)
151 isl_die(ctx
, isl_error_invalid
, "expecting child",
153 if (isl_stream_yaml_next(s
) < 0)
155 tree
= isl_stream_read_schedule_tree(s
);
156 tree
= isl_schedule_tree_insert_domain(tree
, domain
);
161 isl_union_set_free(domain
);
165 /* Read a subtree with expansion root node from "s".
167 static __isl_give isl_schedule_tree
*read_expansion(isl_stream
*s
)
170 isl_union_pw_multi_aff
*contraction
= NULL
;
171 isl_union_map
*expansion
= NULL
;
172 isl_schedule_tree
*tree
= NULL
;
175 ctx
= isl_stream_get_ctx(s
);
178 struct isl_token
*tok
;
179 enum isl_schedule_key key
;
183 if (isl_stream_yaml_next(s
) < 0)
187 case isl_schedule_key_contraction
:
188 isl_union_pw_multi_aff_free(contraction
);
189 tok
= isl_stream_next_token(s
);
190 str
= isl_token_get_str(ctx
, tok
);
191 contraction
= isl_union_pw_multi_aff_read_from_str(ctx
,
198 case isl_schedule_key_expansion
:
199 isl_union_map_free(expansion
);
200 tok
= isl_stream_next_token(s
);
201 str
= isl_token_get_str(ctx
, tok
);
202 expansion
= isl_union_map_read_from_str(ctx
, str
);
208 case isl_schedule_key_child
:
209 isl_schedule_tree_free(tree
);
210 tree
= isl_stream_read_schedule_tree(s
);
215 isl_die(ctx
, isl_error_invalid
, "unexpected key",
218 } while ((more
= isl_stream_yaml_next(s
)) > 0);
224 isl_die(ctx
, isl_error_invalid
, "missing contraction",
227 isl_die(ctx
, isl_error_invalid
, "missing expansion",
231 return isl_schedule_tree_from_expansion(contraction
, expansion
);
232 return isl_schedule_tree_insert_expansion(tree
, contraction
, expansion
);
234 isl_schedule_tree_free(tree
);
235 isl_union_pw_multi_aff_free(contraction
);
236 isl_union_map_free(expansion
);
240 /* Read a subtree with extension root node from "s".
242 static __isl_give isl_schedule_tree
*read_extension(isl_stream
*s
)
244 isl_union_map
*extension
= NULL
;
245 isl_schedule_tree
*tree
;
247 struct isl_token
*tok
;
248 enum isl_schedule_key key
;
252 ctx
= isl_stream_get_ctx(s
);
256 if (isl_stream_yaml_next(s
) < 0)
259 tok
= isl_stream_next_token(s
);
261 isl_stream_error(s
, NULL
, "unexpected EOF");
264 str
= isl_token_get_str(ctx
, tok
);
265 extension
= isl_union_map_read_from_str(ctx
, str
);
269 more
= isl_stream_yaml_next(s
);
273 tree
= isl_schedule_tree_from_extension(extension
);
276 if (key
!= isl_schedule_key_child
)
277 isl_die(ctx
, isl_error_invalid
, "expecting child",
279 if (isl_stream_yaml_next(s
) < 0)
281 tree
= isl_stream_read_schedule_tree(s
);
282 tree
= isl_schedule_tree_insert_extension(tree
, extension
);
287 isl_union_map_free(extension
);
291 /* Read a subtree with filter root node from "s".
293 static __isl_give isl_schedule_tree
*read_filter(__isl_keep isl_stream
*s
)
295 isl_union_set
*filter
= NULL
;
296 isl_schedule_tree
*tree
;
298 struct isl_token
*tok
;
299 enum isl_schedule_key key
;
303 ctx
= isl_stream_get_ctx(s
);
307 if (isl_stream_yaml_next(s
) < 0)
310 tok
= isl_stream_next_token(s
);
312 isl_stream_error(s
, NULL
, "unexpected EOF");
315 str
= isl_token_get_str(ctx
, tok
);
316 filter
= isl_union_set_read_from_str(ctx
, str
);
320 more
= isl_stream_yaml_next(s
);
324 tree
= isl_schedule_tree_from_filter(filter
);
327 if (key
!= isl_schedule_key_child
)
328 isl_die(ctx
, isl_error_invalid
, "expecting child",
330 if (isl_stream_yaml_next(s
) < 0)
332 tree
= isl_stream_read_schedule_tree(s
);
333 tree
= isl_schedule_tree_insert_filter(tree
, filter
);
338 isl_union_set_free(filter
);
342 /* Read a subtree with guard root node from "s".
344 static __isl_give isl_schedule_tree
*read_guard(isl_stream
*s
)
346 isl_set
*guard
= NULL
;
347 isl_schedule_tree
*tree
;
349 struct isl_token
*tok
;
350 enum isl_schedule_key key
;
354 ctx
= isl_stream_get_ctx(s
);
358 if (isl_stream_yaml_next(s
) < 0)
361 tok
= isl_stream_next_token(s
);
363 isl_stream_error(s
, NULL
, "unexpected EOF");
366 str
= isl_token_get_str(ctx
, tok
);
367 guard
= isl_set_read_from_str(ctx
, str
);
371 more
= isl_stream_yaml_next(s
);
375 tree
= isl_schedule_tree_from_guard(guard
);
378 if (key
!= isl_schedule_key_child
)
379 isl_die(ctx
, isl_error_invalid
, "expecting child",
381 if (isl_stream_yaml_next(s
) < 0)
383 tree
= isl_stream_read_schedule_tree(s
);
384 tree
= isl_schedule_tree_insert_guard(tree
, guard
);
393 /* Read a subtree with mark root node from "s".
395 static __isl_give isl_schedule_tree
*read_mark(isl_stream
*s
)
398 isl_schedule_tree
*tree
;
400 struct isl_token
*tok
;
401 enum isl_schedule_key key
;
405 ctx
= isl_stream_get_ctx(s
);
409 if (isl_stream_yaml_next(s
) < 0)
412 tok
= isl_stream_next_token(s
);
414 isl_stream_error(s
, NULL
, "unexpected EOF");
417 str
= isl_token_get_str(ctx
, tok
);
418 mark
= isl_id_alloc(ctx
, str
, NULL
);
422 more
= isl_stream_yaml_next(s
);
426 isl_die(ctx
, isl_error_invalid
, "expecting child",
430 if (key
!= isl_schedule_key_child
)
431 isl_die(ctx
, isl_error_invalid
, "expecting child",
433 if (isl_stream_yaml_next(s
) < 0)
435 tree
= isl_stream_read_schedule_tree(s
);
436 tree
= isl_schedule_tree_insert_mark(tree
, mark
);
445 /* Read a sequence of integers from "s" (representing the coincident
446 * property of a band node).
448 static __isl_give isl_val_list
*read_coincident(__isl_keep isl_stream
*s
)
454 ctx
= isl_stream_get_ctx(s
);
456 if (isl_stream_yaml_read_start_sequence(s
) < 0)
459 list
= isl_val_list_alloc(ctx
, 0);
460 while ((more
= isl_stream_yaml_next(s
)) > 0) {
463 val
= isl_stream_read_val(s
);
464 list
= isl_val_list_add(list
, val
);
467 if (more
< 0 || isl_stream_yaml_read_end_sequence(s
))
468 list
= isl_val_list_free(list
);
473 /* Set the (initial) coincident properties of "band" according to
474 * the (initial) elements of "coincident".
476 static __isl_give isl_schedule_band
*set_coincident(
477 __isl_take isl_schedule_band
*band
, __isl_take isl_val_list
*coincident
)
482 n
= isl_schedule_band_n_member(band
);
483 m
= isl_val_list_n_val(coincident
);
485 for (i
= 0; i
< n
&& i
< m
; ++i
) {
488 v
= isl_val_list_get_val(coincident
, i
);
490 band
= isl_schedule_band_free(band
);
491 band
= isl_schedule_band_member_set_coincident(band
, i
,
492 !isl_val_is_zero(v
));
495 isl_val_list_free(coincident
);
499 /* Read a subtree with band root node from "s".
501 static __isl_give isl_schedule_tree
*read_band(isl_stream
*s
)
503 isl_multi_union_pw_aff
*schedule
= NULL
;
504 isl_schedule_tree
*tree
= NULL
;
505 isl_val_list
*coincident
= NULL
;
506 isl_union_set
*options
= NULL
;
508 isl_schedule_band
*band
;
512 ctx
= isl_stream_get_ctx(s
);
515 struct isl_token
*tok
;
516 enum isl_schedule_key key
;
521 if (isl_stream_yaml_next(s
) < 0)
525 case isl_schedule_key_schedule
:
526 schedule
= isl_multi_union_pw_aff_free(schedule
);
527 tok
= isl_stream_next_token(s
);
529 isl_stream_error(s
, NULL
, "unexpected EOF");
532 str
= isl_token_get_str(ctx
, tok
);
533 schedule
= isl_multi_union_pw_aff_read_from_str(ctx
,
540 case isl_schedule_key_coincident
:
541 coincident
= read_coincident(s
);
545 case isl_schedule_key_permutable
:
546 v
= isl_stream_read_val(s
);
547 permutable
= !isl_val_is_zero(v
);
550 case isl_schedule_key_options
:
551 isl_union_set_free(options
);
552 tok
= isl_stream_next_token(s
);
553 str
= isl_token_get_str(ctx
, tok
);
554 options
= isl_union_set_read_from_str(ctx
, str
);
560 case isl_schedule_key_child
:
561 isl_schedule_tree_free(tree
);
562 tree
= isl_stream_read_schedule_tree(s
);
567 isl_die(ctx
, isl_error_invalid
, "unexpected key",
570 } while ((more
= isl_stream_yaml_next(s
)) > 0);
576 isl_die(ctx
, isl_error_invalid
, "missing schedule", goto error
);
578 band
= isl_schedule_band_from_multi_union_pw_aff(schedule
);
579 band
= isl_schedule_band_set_permutable(band
, permutable
);
581 band
= set_coincident(band
, coincident
);
583 band
= isl_schedule_band_set_ast_build_options(band
, options
);
585 tree
= isl_schedule_tree_insert_band(tree
, band
);
587 tree
= isl_schedule_tree_from_band(band
);
591 isl_val_list_free(coincident
);
592 isl_union_set_free(options
);
593 isl_schedule_tree_free(tree
);
594 isl_multi_union_pw_aff_free(schedule
);
598 /* Read a subtree with root node of type "type" from "s".
599 * The node is represented by a sequence of children.
601 static __isl_give isl_schedule_tree
*read_children(isl_stream
*s
,
602 enum isl_schedule_node_type type
)
605 isl_schedule_tree_list
*list
;
608 ctx
= isl_stream_get_ctx(s
);
610 isl_token_free(isl_stream_next_token(s
));
612 if (isl_stream_yaml_next(s
) < 0)
615 if (isl_stream_yaml_read_start_sequence(s
))
618 list
= isl_schedule_tree_list_alloc(ctx
, 0);
619 while ((more
= isl_stream_yaml_next(s
)) > 0) {
620 isl_schedule_tree
*tree
;
622 tree
= isl_stream_read_schedule_tree(s
);
623 list
= isl_schedule_tree_list_add(list
, tree
);
626 if (more
< 0 || isl_stream_yaml_read_end_sequence(s
))
627 list
= isl_schedule_tree_list_free(list
);
629 return isl_schedule_tree_from_children(type
, list
);
632 /* Read a subtree with sequence root node from "s".
634 static __isl_give isl_schedule_tree
*read_sequence(isl_stream
*s
)
636 return read_children(s
, isl_schedule_node_sequence
);
639 /* Read a subtree with set root node from "s".
641 static __isl_give isl_schedule_tree
*read_set(isl_stream
*s
)
643 return read_children(s
, isl_schedule_node_set
);
646 /* Read a schedule (sub)tree from "s".
648 * We first determine the type of the root node based on the first
649 * mapping key and then hand over to a function tailored to reading
650 * nodes of this type.
652 static __isl_give isl_schedule_tree
*isl_stream_read_schedule_tree(
653 struct isl_stream
*s
)
655 enum isl_schedule_key key
;
656 struct isl_token
*tok
;
657 isl_schedule_tree
*tree
= NULL
;
660 if (isl_stream_yaml_read_start_mapping(s
))
662 more
= isl_stream_yaml_next(s
);
666 isl_stream_error(s
, NULL
, "missing key");
670 tok
= isl_stream_next_token(s
);
671 key
= extract_key(s
, tok
);
672 isl_stream_push_token(s
, tok
);
676 case isl_schedule_key_context
:
677 tree
= read_context(s
);
679 case isl_schedule_key_domain
:
680 tree
= read_domain(s
);
682 case isl_schedule_key_contraction
:
683 case isl_schedule_key_expansion
:
684 tree
= read_expansion(s
);
686 case isl_schedule_key_extension
:
687 tree
= read_extension(s
);
689 case isl_schedule_key_filter
:
690 tree
= read_filter(s
);
692 case isl_schedule_key_guard
:
693 tree
= read_guard(s
);
695 case isl_schedule_key_leaf
:
696 isl_token_free(isl_stream_next_token(s
));
697 tree
= isl_schedule_tree_leaf(isl_stream_get_ctx(s
));
699 case isl_schedule_key_mark
:
702 case isl_schedule_key_sequence
:
703 tree
= read_sequence(s
);
705 case isl_schedule_key_set
:
708 case isl_schedule_key_schedule
:
709 case isl_schedule_key_coincident
:
710 case isl_schedule_key_options
:
711 case isl_schedule_key_permutable
:
714 case isl_schedule_key_child
:
715 isl_die(isl_stream_get_ctx(s
), isl_error_unsupported
,
716 "cannot identity node type", return NULL
);
717 case isl_schedule_key_end
:
718 case isl_schedule_key_error
:
722 if (isl_stream_yaml_read_end_mapping(s
) < 0) {
723 isl_stream_error(s
, NULL
, "unexpected extra elements");
724 return isl_schedule_tree_free(tree
);
730 /* Read an isl_schedule from "s".
732 __isl_give isl_schedule
*isl_stream_read_schedule(isl_stream
*s
)
735 isl_schedule_tree
*tree
;
740 ctx
= isl_stream_get_ctx(s
);
741 tree
= isl_stream_read_schedule_tree(s
);
742 return isl_schedule_from_schedule_tree(ctx
, tree
);
745 /* Read an isl_schedule from "input".
747 __isl_give isl_schedule
*isl_schedule_read_from_file(isl_ctx
*ctx
, FILE *input
)
749 struct isl_stream
*s
;
750 isl_schedule
*schedule
;
752 s
= isl_stream_new_file(ctx
, input
);
755 schedule
= isl_stream_read_schedule(s
);
761 /* Read an isl_schedule from "str".
763 __isl_give isl_schedule
*isl_schedule_read_from_str(isl_ctx
*ctx
,
766 struct isl_stream
*s
;
767 isl_schedule
*schedule
;
769 s
= isl_stream_new_str(ctx
, str
);
772 schedule
= isl_stream_read_schedule(s
);