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
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
,
31 /* Extract a mapping key from the token "tok".
32 * Return isl_schedule_key_error on error, i.e., if "tok" does not
33 * correspond to any known key.
35 static enum isl_schedule_key
extract_key(__isl_keep isl_stream
*s
,
36 struct isl_token
*tok
)
40 enum isl_schedule_key key
;
43 ctx
= isl_stream_get_ctx(s
);
44 type
= isl_token_get_type(tok
);
45 if (type
!= ISL_TOKEN_IDENT
&& type
!= ISL_TOKEN_STRING
) {
46 isl_stream_error(s
, tok
, "expecting key");
47 return isl_schedule_key_error
;
49 name
= isl_token_get_str(ctx
, tok
);
50 if (!strcmp(name
, "child"))
51 key
= isl_schedule_key_child
;
52 else if (!strcmp(name
, "coincident"))
53 key
= isl_schedule_key_coincident
;
54 else if (!strcmp(name
, "context"))
55 key
= isl_schedule_key_context
;
56 else if (!strcmp(name
, "contraction"))
57 key
= isl_schedule_key_contraction
;
58 else if (!strcmp(name
, "domain"))
59 key
= isl_schedule_key_domain
;
60 else if (!strcmp(name
, "expansion"))
61 key
= isl_schedule_key_expansion
;
62 else if (!strcmp(name
, "extension"))
63 key
= isl_schedule_key_extension
;
64 else if (!strcmp(name
, "filter"))
65 key
= isl_schedule_key_filter
;
66 else if (!strcmp(name
, "guard"))
67 key
= isl_schedule_key_guard
;
68 else if (!strcmp(name
, "leaf"))
69 key
= isl_schedule_key_leaf
;
70 else if (!strcmp(name
, "mark"))
71 key
= isl_schedule_key_mark
;
72 else if (!strcmp(name
, "options"))
73 key
= isl_schedule_key_options
;
74 else if (!strcmp(name
, "schedule"))
75 key
= isl_schedule_key_schedule
;
76 else if (!strcmp(name
, "sequence"))
77 key
= isl_schedule_key_sequence
;
78 else if (!strcmp(name
, "set"))
79 key
= isl_schedule_key_set
;
80 else if (!strcmp(name
, "permutable"))
81 key
= isl_schedule_key_permutable
;
83 isl_die(ctx
, isl_error_invalid
, "unknown key",
84 key
= isl_schedule_key_error
);
89 /* Read a key from "s" and return the corresponding enum.
90 * Return isl_schedule_key_error on error, i.e., if the first token
91 * on the stream does not correspond to any known key.
93 static enum isl_schedule_key
get_key(__isl_keep isl_stream
*s
)
95 struct isl_token
*tok
;
96 enum isl_schedule_key key
;
98 tok
= isl_stream_next_token(s
);
99 key
= extract_key(s
, tok
);
105 static __isl_give isl_schedule_tree
*isl_stream_read_schedule_tree(
106 __isl_keep isl_stream
*s
);
108 /* Read a subtree with context root node from "s".
110 static __isl_give isl_schedule_tree
*read_context(__isl_keep isl_stream
*s
)
112 isl_set
*context
= NULL
;
113 isl_schedule_tree
*tree
;
115 struct isl_token
*tok
;
116 enum isl_schedule_key key
;
120 ctx
= isl_stream_get_ctx(s
);
124 if (isl_stream_yaml_next(s
) < 0)
127 tok
= isl_stream_next_token(s
);
129 isl_stream_error(s
, NULL
, "unexpected EOF");
132 str
= isl_token_get_str(ctx
, tok
);
133 context
= isl_set_read_from_str(ctx
, str
);
137 more
= isl_stream_yaml_next(s
);
141 tree
= isl_schedule_tree_from_context(context
);
144 if (key
!= isl_schedule_key_child
)
145 isl_die(ctx
, isl_error_invalid
, "expecting child",
147 if (isl_stream_yaml_next(s
) < 0)
149 tree
= isl_stream_read_schedule_tree(s
);
150 tree
= isl_schedule_tree_insert_context(tree
, context
);
155 isl_set_free(context
);
159 /* Read a subtree with domain root node from "s".
161 static __isl_give isl_schedule_tree
*read_domain(__isl_keep isl_stream
*s
)
163 isl_union_set
*domain
= NULL
;
164 isl_schedule_tree
*tree
;
166 struct isl_token
*tok
;
167 enum isl_schedule_key key
;
171 ctx
= isl_stream_get_ctx(s
);
175 if (isl_stream_yaml_next(s
) < 0)
178 tok
= isl_stream_next_token(s
);
180 isl_stream_error(s
, NULL
, "unexpected EOF");
183 str
= isl_token_get_str(ctx
, tok
);
184 domain
= isl_union_set_read_from_str(ctx
, str
);
188 more
= isl_stream_yaml_next(s
);
192 tree
= isl_schedule_tree_from_domain(domain
);
195 if (key
!= isl_schedule_key_child
)
196 isl_die(ctx
, isl_error_invalid
, "expecting child",
198 if (isl_stream_yaml_next(s
) < 0)
200 tree
= isl_stream_read_schedule_tree(s
);
201 tree
= isl_schedule_tree_insert_domain(tree
, domain
);
206 isl_union_set_free(domain
);
210 /* Read a subtree with expansion root node from "s".
212 static __isl_give isl_schedule_tree
*read_expansion(isl_stream
*s
)
215 isl_union_pw_multi_aff
*contraction
= NULL
;
216 isl_union_map
*expansion
= NULL
;
217 isl_schedule_tree
*tree
= NULL
;
220 ctx
= isl_stream_get_ctx(s
);
223 struct isl_token
*tok
;
224 enum isl_schedule_key key
;
228 if (isl_stream_yaml_next(s
) < 0)
232 case isl_schedule_key_contraction
:
233 isl_union_pw_multi_aff_free(contraction
);
234 tok
= isl_stream_next_token(s
);
235 str
= isl_token_get_str(ctx
, tok
);
236 contraction
= isl_union_pw_multi_aff_read_from_str(ctx
,
243 case isl_schedule_key_expansion
:
244 isl_union_map_free(expansion
);
245 tok
= isl_stream_next_token(s
);
246 str
= isl_token_get_str(ctx
, tok
);
247 expansion
= isl_union_map_read_from_str(ctx
, str
);
253 case isl_schedule_key_child
:
254 isl_schedule_tree_free(tree
);
255 tree
= isl_stream_read_schedule_tree(s
);
260 isl_die(ctx
, isl_error_invalid
, "unexpected key",
263 } while ((more
= isl_stream_yaml_next(s
)) > 0);
269 isl_die(ctx
, isl_error_invalid
, "missing contraction",
272 isl_die(ctx
, isl_error_invalid
, "missing expansion",
276 return isl_schedule_tree_from_expansion(contraction
, expansion
);
277 return isl_schedule_tree_insert_expansion(tree
, contraction
, expansion
);
279 isl_schedule_tree_free(tree
);
280 isl_union_pw_multi_aff_free(contraction
);
281 isl_union_map_free(expansion
);
285 /* Read a subtree with extension root node from "s".
287 static __isl_give isl_schedule_tree
*read_extension(isl_stream
*s
)
289 isl_union_map
*extension
= NULL
;
290 isl_schedule_tree
*tree
;
292 struct isl_token
*tok
;
293 enum isl_schedule_key key
;
297 ctx
= isl_stream_get_ctx(s
);
301 if (isl_stream_yaml_next(s
) < 0)
304 tok
= isl_stream_next_token(s
);
306 isl_stream_error(s
, NULL
, "unexpected EOF");
309 str
= isl_token_get_str(ctx
, tok
);
310 extension
= isl_union_map_read_from_str(ctx
, str
);
314 more
= isl_stream_yaml_next(s
);
318 tree
= isl_schedule_tree_from_extension(extension
);
321 if (key
!= isl_schedule_key_child
)
322 isl_die(ctx
, isl_error_invalid
, "expecting child",
324 if (isl_stream_yaml_next(s
) < 0)
326 tree
= isl_stream_read_schedule_tree(s
);
327 tree
= isl_schedule_tree_insert_extension(tree
, extension
);
332 isl_union_map_free(extension
);
336 /* Read a subtree with filter root node from "s".
338 static __isl_give isl_schedule_tree
*read_filter(__isl_keep isl_stream
*s
)
340 isl_union_set
*filter
= NULL
;
341 isl_schedule_tree
*tree
;
343 struct isl_token
*tok
;
344 enum isl_schedule_key key
;
348 ctx
= isl_stream_get_ctx(s
);
352 if (isl_stream_yaml_next(s
) < 0)
355 tok
= isl_stream_next_token(s
);
357 isl_stream_error(s
, NULL
, "unexpected EOF");
360 str
= isl_token_get_str(ctx
, tok
);
361 filter
= isl_union_set_read_from_str(ctx
, str
);
365 more
= isl_stream_yaml_next(s
);
369 tree
= isl_schedule_tree_from_filter(filter
);
372 if (key
!= isl_schedule_key_child
)
373 isl_die(ctx
, isl_error_invalid
, "expecting child",
375 if (isl_stream_yaml_next(s
) < 0)
377 tree
= isl_stream_read_schedule_tree(s
);
378 tree
= isl_schedule_tree_insert_filter(tree
, filter
);
383 isl_union_set_free(filter
);
387 /* Read a subtree with guard root node from "s".
389 static __isl_give isl_schedule_tree
*read_guard(isl_stream
*s
)
391 isl_set
*guard
= NULL
;
392 isl_schedule_tree
*tree
;
394 struct isl_token
*tok
;
395 enum isl_schedule_key key
;
399 ctx
= isl_stream_get_ctx(s
);
403 if (isl_stream_yaml_next(s
) < 0)
406 tok
= isl_stream_next_token(s
);
408 isl_stream_error(s
, NULL
, "unexpected EOF");
411 str
= isl_token_get_str(ctx
, tok
);
412 guard
= isl_set_read_from_str(ctx
, str
);
416 more
= isl_stream_yaml_next(s
);
420 tree
= isl_schedule_tree_from_guard(guard
);
423 if (key
!= isl_schedule_key_child
)
424 isl_die(ctx
, isl_error_invalid
, "expecting child",
426 if (isl_stream_yaml_next(s
) < 0)
428 tree
= isl_stream_read_schedule_tree(s
);
429 tree
= isl_schedule_tree_insert_guard(tree
, guard
);
438 /* Read a subtree with mark root node from "s".
440 static __isl_give isl_schedule_tree
*read_mark(isl_stream
*s
)
443 isl_schedule_tree
*tree
;
445 struct isl_token
*tok
;
446 enum isl_schedule_key key
;
450 ctx
= isl_stream_get_ctx(s
);
454 if (isl_stream_yaml_next(s
) < 0)
457 tok
= isl_stream_next_token(s
);
459 isl_stream_error(s
, NULL
, "unexpected EOF");
462 str
= isl_token_get_str(ctx
, tok
);
463 mark
= isl_id_alloc(ctx
, str
, NULL
);
467 more
= isl_stream_yaml_next(s
);
471 isl_die(ctx
, isl_error_invalid
, "expecting child",
475 if (key
!= isl_schedule_key_child
)
476 isl_die(ctx
, isl_error_invalid
, "expecting child",
478 if (isl_stream_yaml_next(s
) < 0)
480 tree
= isl_stream_read_schedule_tree(s
);
481 tree
= isl_schedule_tree_insert_mark(tree
, mark
);
490 /* Read a sequence of integers from "s" (representing the coincident
491 * property of a band node).
493 static __isl_give isl_val_list
*read_coincident(__isl_keep isl_stream
*s
)
499 ctx
= isl_stream_get_ctx(s
);
501 if (isl_stream_yaml_read_start_sequence(s
) < 0)
504 list
= isl_val_list_alloc(ctx
, 0);
505 while ((more
= isl_stream_yaml_next(s
)) > 0) {
508 val
= isl_stream_read_val(s
);
509 list
= isl_val_list_add(list
, val
);
512 if (more
< 0 || isl_stream_yaml_read_end_sequence(s
))
513 list
= isl_val_list_free(list
);
518 /* Set the (initial) coincident properties of "band" according to
519 * the (initial) elements of "coincident".
521 static __isl_give isl_schedule_band
*set_coincident(
522 __isl_take isl_schedule_band
*band
, __isl_take isl_val_list
*coincident
)
527 n
= isl_schedule_band_n_member(band
);
528 m
= isl_val_list_n_val(coincident
);
530 for (i
= 0; i
< n
&& i
< m
; ++i
) {
533 v
= isl_val_list_get_val(coincident
, i
);
535 band
= isl_schedule_band_free(band
);
536 band
= isl_schedule_band_member_set_coincident(band
, i
,
537 !isl_val_is_zero(v
));
540 isl_val_list_free(coincident
);
544 /* Read a subtree with band root node from "s".
546 static __isl_give isl_schedule_tree
*read_band(isl_stream
*s
)
548 isl_multi_union_pw_aff
*schedule
= NULL
;
549 isl_schedule_tree
*tree
= NULL
;
550 isl_val_list
*coincident
= NULL
;
551 isl_union_set
*options
= NULL
;
553 isl_schedule_band
*band
;
557 ctx
= isl_stream_get_ctx(s
);
560 struct isl_token
*tok
;
561 enum isl_schedule_key key
;
566 if (isl_stream_yaml_next(s
) < 0)
570 case isl_schedule_key_schedule
:
571 isl_multi_union_pw_aff_free(schedule
);
572 tok
= isl_stream_next_token(s
);
574 isl_stream_error(s
, NULL
, "unexpected EOF");
577 str
= isl_token_get_str(ctx
, tok
);
578 schedule
= isl_multi_union_pw_aff_read_from_str(ctx
,
585 case isl_schedule_key_coincident
:
586 coincident
= read_coincident(s
);
590 case isl_schedule_key_permutable
:
591 v
= isl_stream_read_val(s
);
592 permutable
= !isl_val_is_zero(v
);
595 case isl_schedule_key_options
:
596 isl_union_set_free(options
);
597 tok
= isl_stream_next_token(s
);
598 str
= isl_token_get_str(ctx
, tok
);
599 options
= isl_union_set_read_from_str(ctx
, str
);
605 case isl_schedule_key_child
:
606 isl_schedule_tree_free(tree
);
607 tree
= isl_stream_read_schedule_tree(s
);
612 isl_die(ctx
, isl_error_invalid
, "unexpected key",
615 } while ((more
= isl_stream_yaml_next(s
)) > 0);
621 isl_die(ctx
, isl_error_invalid
, "missing schedule", goto error
);
623 band
= isl_schedule_band_from_multi_union_pw_aff(schedule
);
624 band
= isl_schedule_band_set_permutable(band
, permutable
);
626 band
= set_coincident(band
, coincident
);
628 band
= isl_schedule_band_set_ast_build_options(band
, options
);
630 tree
= isl_schedule_tree_insert_band(tree
, band
);
632 tree
= isl_schedule_tree_from_band(band
);
636 isl_val_list_free(coincident
);
637 isl_union_set_free(options
);
638 isl_schedule_tree_free(tree
);
639 isl_multi_union_pw_aff_free(schedule
);
643 /* Read a subtree with root node of type "type" from "s".
644 * The node is represented by a sequence of children.
646 static __isl_give isl_schedule_tree
*read_children(isl_stream
*s
,
647 enum isl_schedule_node_type type
)
650 isl_schedule_tree_list
*list
;
653 ctx
= isl_stream_get_ctx(s
);
655 isl_token_free(isl_stream_next_token(s
));
657 if (isl_stream_yaml_next(s
) < 0)
660 if (isl_stream_yaml_read_start_sequence(s
))
663 list
= isl_schedule_tree_list_alloc(ctx
, 0);
664 while ((more
= isl_stream_yaml_next(s
)) > 0) {
665 isl_schedule_tree
*tree
;
667 tree
= isl_stream_read_schedule_tree(s
);
668 list
= isl_schedule_tree_list_add(list
, tree
);
671 if (more
< 0 || isl_stream_yaml_read_end_sequence(s
))
672 list
= isl_schedule_tree_list_free(list
);
674 return isl_schedule_tree_from_children(type
, list
);
677 /* Read a subtree with sequence root node from "s".
679 static __isl_give isl_schedule_tree
*read_sequence(isl_stream
*s
)
681 return read_children(s
, isl_schedule_node_sequence
);
684 /* Read a subtree with set root node from "s".
686 static __isl_give isl_schedule_tree
*read_set(isl_stream
*s
)
688 return read_children(s
, isl_schedule_node_set
);
691 /* Read a schedule (sub)tree from "s".
693 * We first determine the type of the root node based on the first
694 * mapping key and then hand over to a function tailored to reading
695 * nodes of this type.
697 static __isl_give isl_schedule_tree
*isl_stream_read_schedule_tree(
698 struct isl_stream
*s
)
700 enum isl_schedule_key key
;
701 struct isl_token
*tok
;
702 isl_schedule_tree
*tree
= NULL
;
705 if (isl_stream_yaml_read_start_mapping(s
))
707 more
= isl_stream_yaml_next(s
);
711 isl_stream_error(s
, NULL
, "missing key");
715 tok
= isl_stream_next_token(s
);
716 key
= extract_key(s
, tok
);
717 isl_stream_push_token(s
, tok
);
721 case isl_schedule_key_context
:
722 tree
= read_context(s
);
724 case isl_schedule_key_domain
:
725 tree
= read_domain(s
);
727 case isl_schedule_key_contraction
:
728 case isl_schedule_key_expansion
:
729 tree
= read_expansion(s
);
731 case isl_schedule_key_extension
:
732 tree
= read_extension(s
);
734 case isl_schedule_key_filter
:
735 tree
= read_filter(s
);
737 case isl_schedule_key_guard
:
738 tree
= read_guard(s
);
740 case isl_schedule_key_leaf
:
741 isl_token_free(isl_stream_next_token(s
));
742 tree
= isl_schedule_tree_leaf(isl_stream_get_ctx(s
));
744 case isl_schedule_key_mark
:
747 case isl_schedule_key_sequence
:
748 tree
= read_sequence(s
);
750 case isl_schedule_key_set
:
753 case isl_schedule_key_schedule
:
754 case isl_schedule_key_coincident
:
755 case isl_schedule_key_options
:
756 case isl_schedule_key_permutable
:
759 case isl_schedule_key_child
:
760 isl_die(isl_stream_get_ctx(s
), isl_error_unsupported
,
761 "cannot identity node type", return NULL
);
762 case isl_schedule_key_error
:
766 if (isl_stream_yaml_read_end_mapping(s
) < 0) {
767 isl_stream_error(s
, NULL
, "unexpected extra elements");
768 return isl_schedule_tree_free(tree
);
774 /* Read an isl_schedule from "s".
776 __isl_give isl_schedule
*isl_stream_read_schedule(isl_stream
*s
)
779 isl_schedule_tree
*tree
;
784 ctx
= isl_stream_get_ctx(s
);
785 tree
= isl_stream_read_schedule_tree(s
);
786 return isl_schedule_from_schedule_tree(ctx
, tree
);
789 /* Read an isl_schedule from "input".
791 __isl_give isl_schedule
*isl_schedule_read_from_file(isl_ctx
*ctx
, FILE *input
)
793 struct isl_stream
*s
;
794 isl_schedule
*schedule
;
796 s
= isl_stream_new_file(ctx
, input
);
799 schedule
= isl_stream_read_schedule(s
);
805 /* Read an isl_schedule from "str".
807 __isl_give isl_schedule
*isl_schedule_read_from_str(isl_ctx
*ctx
,
810 struct isl_stream
*s
;
811 isl_schedule
*schedule
;
813 s
= isl_stream_new_str(ctx
, str
);
816 schedule
= isl_stream_read_schedule(s
);