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
,
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 /* Extract a mapping key from the token "tok".
54 * Return isl_schedule_key_error on error, i.e., if "tok" does not
55 * correspond to any known key.
57 static enum isl_schedule_key
extract_key(__isl_keep isl_stream
*s
,
58 struct isl_token
*tok
)
62 enum isl_schedule_key key
;
65 ctx
= isl_stream_get_ctx(s
);
66 type
= isl_token_get_type(tok
);
67 if (type
!= ISL_TOKEN_IDENT
&& type
!= ISL_TOKEN_STRING
) {
68 isl_stream_error(s
, tok
, "expecting key");
69 return isl_schedule_key_error
;
71 name
= isl_token_get_str(ctx
, tok
);
72 for (key
= 0; key
< isl_schedule_key_end
; ++key
) {
73 if (!strcmp(name
, key_str
[key
]))
78 if (key
>= isl_schedule_key_end
)
79 isl_die(ctx
, isl_error_invalid
, "unknown key",
80 return isl_schedule_key_error
);
84 /* Read a key from "s" and return the corresponding enum.
85 * Return isl_schedule_key_error on error, i.e., if the first token
86 * on the stream does not correspond to any known key.
88 static enum isl_schedule_key
get_key(__isl_keep isl_stream
*s
)
90 struct isl_token
*tok
;
91 enum isl_schedule_key key
;
93 tok
= isl_stream_next_token(s
);
94 key
= extract_key(s
, tok
);
100 static __isl_give isl_schedule_tree
*isl_stream_read_schedule_tree(
101 __isl_keep isl_stream
*s
);
103 /* Read a subtree with context root node from "s".
105 static __isl_give isl_schedule_tree
*read_context(__isl_keep isl_stream
*s
)
107 isl_set
*context
= NULL
;
108 isl_schedule_tree
*tree
;
110 struct isl_token
*tok
;
111 enum isl_schedule_key key
;
115 ctx
= isl_stream_get_ctx(s
);
119 if (isl_stream_yaml_next(s
) < 0)
122 tok
= isl_stream_next_token(s
);
124 isl_stream_error(s
, NULL
, "unexpected EOF");
127 str
= isl_token_get_str(ctx
, tok
);
128 context
= isl_set_read_from_str(ctx
, str
);
132 more
= isl_stream_yaml_next(s
);
136 tree
= isl_schedule_tree_from_context(context
);
139 if (key
!= isl_schedule_key_child
)
140 isl_die(ctx
, isl_error_invalid
, "expecting child",
142 if (isl_stream_yaml_next(s
) < 0)
144 tree
= isl_stream_read_schedule_tree(s
);
145 tree
= isl_schedule_tree_insert_context(tree
, context
);
150 isl_set_free(context
);
154 /* Read a subtree with domain root node from "s".
156 static __isl_give isl_schedule_tree
*read_domain(__isl_keep isl_stream
*s
)
158 isl_union_set
*domain
= NULL
;
159 isl_schedule_tree
*tree
;
161 struct isl_token
*tok
;
162 enum isl_schedule_key key
;
166 ctx
= isl_stream_get_ctx(s
);
170 if (isl_stream_yaml_next(s
) < 0)
173 tok
= isl_stream_next_token(s
);
175 isl_stream_error(s
, NULL
, "unexpected EOF");
178 str
= isl_token_get_str(ctx
, tok
);
179 domain
= isl_union_set_read_from_str(ctx
, str
);
183 more
= isl_stream_yaml_next(s
);
187 tree
= isl_schedule_tree_from_domain(domain
);
190 if (key
!= isl_schedule_key_child
)
191 isl_die(ctx
, isl_error_invalid
, "expecting child",
193 if (isl_stream_yaml_next(s
) < 0)
195 tree
= isl_stream_read_schedule_tree(s
);
196 tree
= isl_schedule_tree_insert_domain(tree
, domain
);
201 isl_union_set_free(domain
);
205 /* Read a subtree with expansion root node from "s".
207 static __isl_give isl_schedule_tree
*read_expansion(isl_stream
*s
)
210 isl_union_pw_multi_aff
*contraction
= NULL
;
211 isl_union_map
*expansion
= NULL
;
212 isl_schedule_tree
*tree
= NULL
;
215 ctx
= isl_stream_get_ctx(s
);
218 struct isl_token
*tok
;
219 enum isl_schedule_key key
;
223 if (isl_stream_yaml_next(s
) < 0)
227 case isl_schedule_key_contraction
:
228 isl_union_pw_multi_aff_free(contraction
);
229 tok
= isl_stream_next_token(s
);
230 str
= isl_token_get_str(ctx
, tok
);
231 contraction
= isl_union_pw_multi_aff_read_from_str(ctx
,
238 case isl_schedule_key_expansion
:
239 isl_union_map_free(expansion
);
240 tok
= isl_stream_next_token(s
);
241 str
= isl_token_get_str(ctx
, tok
);
242 expansion
= isl_union_map_read_from_str(ctx
, str
);
248 case isl_schedule_key_child
:
249 isl_schedule_tree_free(tree
);
250 tree
= isl_stream_read_schedule_tree(s
);
255 isl_die(ctx
, isl_error_invalid
, "unexpected key",
258 } while ((more
= isl_stream_yaml_next(s
)) > 0);
264 isl_die(ctx
, isl_error_invalid
, "missing contraction",
267 isl_die(ctx
, isl_error_invalid
, "missing expansion",
271 return isl_schedule_tree_from_expansion(contraction
, expansion
);
272 return isl_schedule_tree_insert_expansion(tree
, contraction
, expansion
);
274 isl_schedule_tree_free(tree
);
275 isl_union_pw_multi_aff_free(contraction
);
276 isl_union_map_free(expansion
);
280 /* Read a subtree with extension root node from "s".
282 static __isl_give isl_schedule_tree
*read_extension(isl_stream
*s
)
284 isl_union_map
*extension
= NULL
;
285 isl_schedule_tree
*tree
;
287 struct isl_token
*tok
;
288 enum isl_schedule_key key
;
292 ctx
= isl_stream_get_ctx(s
);
296 if (isl_stream_yaml_next(s
) < 0)
299 tok
= isl_stream_next_token(s
);
301 isl_stream_error(s
, NULL
, "unexpected EOF");
304 str
= isl_token_get_str(ctx
, tok
);
305 extension
= isl_union_map_read_from_str(ctx
, str
);
309 more
= isl_stream_yaml_next(s
);
313 tree
= isl_schedule_tree_from_extension(extension
);
316 if (key
!= isl_schedule_key_child
)
317 isl_die(ctx
, isl_error_invalid
, "expecting child",
319 if (isl_stream_yaml_next(s
) < 0)
321 tree
= isl_stream_read_schedule_tree(s
);
322 tree
= isl_schedule_tree_insert_extension(tree
, extension
);
327 isl_union_map_free(extension
);
331 /* Read a subtree with filter root node from "s".
333 static __isl_give isl_schedule_tree
*read_filter(__isl_keep isl_stream
*s
)
335 isl_union_set
*filter
= NULL
;
336 isl_schedule_tree
*tree
;
338 struct isl_token
*tok
;
339 enum isl_schedule_key key
;
343 ctx
= isl_stream_get_ctx(s
);
347 if (isl_stream_yaml_next(s
) < 0)
350 tok
= isl_stream_next_token(s
);
352 isl_stream_error(s
, NULL
, "unexpected EOF");
355 str
= isl_token_get_str(ctx
, tok
);
356 filter
= isl_union_set_read_from_str(ctx
, str
);
360 more
= isl_stream_yaml_next(s
);
364 tree
= isl_schedule_tree_from_filter(filter
);
367 if (key
!= isl_schedule_key_child
)
368 isl_die(ctx
, isl_error_invalid
, "expecting child",
370 if (isl_stream_yaml_next(s
) < 0)
372 tree
= isl_stream_read_schedule_tree(s
);
373 tree
= isl_schedule_tree_insert_filter(tree
, filter
);
378 isl_union_set_free(filter
);
382 /* Read a subtree with guard root node from "s".
384 static __isl_give isl_schedule_tree
*read_guard(isl_stream
*s
)
386 isl_set
*guard
= NULL
;
387 isl_schedule_tree
*tree
;
389 struct isl_token
*tok
;
390 enum isl_schedule_key key
;
394 ctx
= isl_stream_get_ctx(s
);
398 if (isl_stream_yaml_next(s
) < 0)
401 tok
= isl_stream_next_token(s
);
403 isl_stream_error(s
, NULL
, "unexpected EOF");
406 str
= isl_token_get_str(ctx
, tok
);
407 guard
= isl_set_read_from_str(ctx
, str
);
411 more
= isl_stream_yaml_next(s
);
415 tree
= isl_schedule_tree_from_guard(guard
);
418 if (key
!= isl_schedule_key_child
)
419 isl_die(ctx
, isl_error_invalid
, "expecting child",
421 if (isl_stream_yaml_next(s
) < 0)
423 tree
= isl_stream_read_schedule_tree(s
);
424 tree
= isl_schedule_tree_insert_guard(tree
, guard
);
433 /* Read a subtree with mark root node from "s".
435 static __isl_give isl_schedule_tree
*read_mark(isl_stream
*s
)
438 isl_schedule_tree
*tree
;
440 struct isl_token
*tok
;
441 enum isl_schedule_key key
;
445 ctx
= isl_stream_get_ctx(s
);
449 if (isl_stream_yaml_next(s
) < 0)
452 tok
= isl_stream_next_token(s
);
454 isl_stream_error(s
, NULL
, "unexpected EOF");
457 str
= isl_token_get_str(ctx
, tok
);
458 mark
= isl_id_alloc(ctx
, str
, NULL
);
462 more
= isl_stream_yaml_next(s
);
466 isl_die(ctx
, isl_error_invalid
, "expecting child",
470 if (key
!= isl_schedule_key_child
)
471 isl_die(ctx
, isl_error_invalid
, "expecting child",
473 if (isl_stream_yaml_next(s
) < 0)
475 tree
= isl_stream_read_schedule_tree(s
);
476 tree
= isl_schedule_tree_insert_mark(tree
, mark
);
485 /* Read a sequence of integers from "s" (representing the coincident
486 * property of a band node).
488 static __isl_give isl_val_list
*read_coincident(__isl_keep isl_stream
*s
)
494 ctx
= isl_stream_get_ctx(s
);
496 if (isl_stream_yaml_read_start_sequence(s
) < 0)
499 list
= isl_val_list_alloc(ctx
, 0);
500 while ((more
= isl_stream_yaml_next(s
)) > 0) {
503 val
= isl_stream_read_val(s
);
504 list
= isl_val_list_add(list
, val
);
507 if (more
< 0 || isl_stream_yaml_read_end_sequence(s
))
508 list
= isl_val_list_free(list
);
513 /* Set the (initial) coincident properties of "band" according to
514 * the (initial) elements of "coincident".
516 static __isl_give isl_schedule_band
*set_coincident(
517 __isl_take isl_schedule_band
*band
, __isl_take isl_val_list
*coincident
)
522 n
= isl_schedule_band_n_member(band
);
523 m
= isl_val_list_n_val(coincident
);
525 for (i
= 0; i
< n
&& i
< m
; ++i
) {
528 v
= isl_val_list_get_val(coincident
, i
);
530 band
= isl_schedule_band_free(band
);
531 band
= isl_schedule_band_member_set_coincident(band
, i
,
532 !isl_val_is_zero(v
));
535 isl_val_list_free(coincident
);
539 /* Read a subtree with band root node from "s".
541 static __isl_give isl_schedule_tree
*read_band(isl_stream
*s
)
543 isl_multi_union_pw_aff
*schedule
= NULL
;
544 isl_schedule_tree
*tree
= NULL
;
545 isl_val_list
*coincident
= NULL
;
546 isl_union_set
*options
= NULL
;
548 isl_schedule_band
*band
;
552 ctx
= isl_stream_get_ctx(s
);
555 struct isl_token
*tok
;
556 enum isl_schedule_key key
;
561 if (isl_stream_yaml_next(s
) < 0)
565 case isl_schedule_key_schedule
:
566 schedule
= isl_multi_union_pw_aff_free(schedule
);
567 tok
= isl_stream_next_token(s
);
569 isl_stream_error(s
, NULL
, "unexpected EOF");
572 str
= isl_token_get_str(ctx
, tok
);
573 schedule
= isl_multi_union_pw_aff_read_from_str(ctx
,
580 case isl_schedule_key_coincident
:
581 coincident
= read_coincident(s
);
585 case isl_schedule_key_permutable
:
586 v
= isl_stream_read_val(s
);
587 permutable
= !isl_val_is_zero(v
);
590 case isl_schedule_key_options
:
591 isl_union_set_free(options
);
592 tok
= isl_stream_next_token(s
);
593 str
= isl_token_get_str(ctx
, tok
);
594 options
= isl_union_set_read_from_str(ctx
, str
);
600 case isl_schedule_key_child
:
601 isl_schedule_tree_free(tree
);
602 tree
= isl_stream_read_schedule_tree(s
);
607 isl_die(ctx
, isl_error_invalid
, "unexpected key",
610 } while ((more
= isl_stream_yaml_next(s
)) > 0);
616 isl_die(ctx
, isl_error_invalid
, "missing schedule", goto error
);
618 band
= isl_schedule_band_from_multi_union_pw_aff(schedule
);
619 band
= isl_schedule_band_set_permutable(band
, permutable
);
621 band
= set_coincident(band
, coincident
);
623 band
= isl_schedule_band_set_ast_build_options(band
, options
);
625 tree
= isl_schedule_tree_insert_band(tree
, band
);
627 tree
= isl_schedule_tree_from_band(band
);
631 isl_val_list_free(coincident
);
632 isl_union_set_free(options
);
633 isl_schedule_tree_free(tree
);
634 isl_multi_union_pw_aff_free(schedule
);
638 /* Read a subtree with root node of type "type" from "s".
639 * The node is represented by a sequence of children.
641 static __isl_give isl_schedule_tree
*read_children(isl_stream
*s
,
642 enum isl_schedule_node_type type
)
645 isl_schedule_tree_list
*list
;
648 ctx
= isl_stream_get_ctx(s
);
650 isl_token_free(isl_stream_next_token(s
));
652 if (isl_stream_yaml_next(s
) < 0)
655 if (isl_stream_yaml_read_start_sequence(s
))
658 list
= isl_schedule_tree_list_alloc(ctx
, 0);
659 while ((more
= isl_stream_yaml_next(s
)) > 0) {
660 isl_schedule_tree
*tree
;
662 tree
= isl_stream_read_schedule_tree(s
);
663 list
= isl_schedule_tree_list_add(list
, tree
);
666 if (more
< 0 || isl_stream_yaml_read_end_sequence(s
))
667 list
= isl_schedule_tree_list_free(list
);
669 return isl_schedule_tree_from_children(type
, list
);
672 /* Read a subtree with sequence root node from "s".
674 static __isl_give isl_schedule_tree
*read_sequence(isl_stream
*s
)
676 return read_children(s
, isl_schedule_node_sequence
);
679 /* Read a subtree with set root node from "s".
681 static __isl_give isl_schedule_tree
*read_set(isl_stream
*s
)
683 return read_children(s
, isl_schedule_node_set
);
686 /* Read a schedule (sub)tree from "s".
688 * We first determine the type of the root node based on the first
689 * mapping key and then hand over to a function tailored to reading
690 * nodes of this type.
692 static __isl_give isl_schedule_tree
*isl_stream_read_schedule_tree(
693 struct isl_stream
*s
)
695 enum isl_schedule_key key
;
696 struct isl_token
*tok
;
697 isl_schedule_tree
*tree
= NULL
;
700 if (isl_stream_yaml_read_start_mapping(s
))
702 more
= isl_stream_yaml_next(s
);
706 isl_stream_error(s
, NULL
, "missing key");
710 tok
= isl_stream_next_token(s
);
711 key
= extract_key(s
, tok
);
712 isl_stream_push_token(s
, tok
);
716 case isl_schedule_key_context
:
717 tree
= read_context(s
);
719 case isl_schedule_key_domain
:
720 tree
= read_domain(s
);
722 case isl_schedule_key_contraction
:
723 case isl_schedule_key_expansion
:
724 tree
= read_expansion(s
);
726 case isl_schedule_key_extension
:
727 tree
= read_extension(s
);
729 case isl_schedule_key_filter
:
730 tree
= read_filter(s
);
732 case isl_schedule_key_guard
:
733 tree
= read_guard(s
);
735 case isl_schedule_key_leaf
:
736 isl_token_free(isl_stream_next_token(s
));
737 tree
= isl_schedule_tree_leaf(isl_stream_get_ctx(s
));
739 case isl_schedule_key_mark
:
742 case isl_schedule_key_sequence
:
743 tree
= read_sequence(s
);
745 case isl_schedule_key_set
:
748 case isl_schedule_key_schedule
:
749 case isl_schedule_key_coincident
:
750 case isl_schedule_key_options
:
751 case isl_schedule_key_permutable
:
754 case isl_schedule_key_child
:
755 isl_die(isl_stream_get_ctx(s
), isl_error_unsupported
,
756 "cannot identity node type", return NULL
);
757 case isl_schedule_key_end
:
758 case isl_schedule_key_error
:
762 if (isl_stream_yaml_read_end_mapping(s
) < 0) {
763 isl_stream_error(s
, NULL
, "unexpected extra elements");
764 return isl_schedule_tree_free(tree
);
770 /* Read an isl_schedule from "s".
772 __isl_give isl_schedule
*isl_stream_read_schedule(isl_stream
*s
)
775 isl_schedule_tree
*tree
;
780 ctx
= isl_stream_get_ctx(s
);
781 tree
= isl_stream_read_schedule_tree(s
);
782 return isl_schedule_from_schedule_tree(ctx
, tree
);
785 /* Read an isl_schedule from "input".
787 __isl_give isl_schedule
*isl_schedule_read_from_file(isl_ctx
*ctx
, FILE *input
)
789 struct isl_stream
*s
;
790 isl_schedule
*schedule
;
792 s
= isl_stream_new_file(ctx
, input
);
795 schedule
= isl_stream_read_schedule(s
);
801 /* Read an isl_schedule from "str".
803 __isl_give isl_schedule
*isl_schedule_read_from_str(isl_ctx
*ctx
,
806 struct isl_stream
*s
;
807 isl_schedule
*schedule
;
809 s
= isl_stream_new_str(ctx
, str
);
812 schedule
= isl_stream_read_schedule(s
);