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_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
,
30 /* Extract a mapping key from the token "tok".
31 * Return isl_schedule_key_error on error, i.e., if "tok" does not
32 * correspond to any known key.
34 static enum isl_schedule_key
extract_key(__isl_keep isl_stream
*s
,
35 struct isl_token
*tok
)
39 enum isl_schedule_key key
;
42 ctx
= isl_stream_get_ctx(s
);
43 type
= isl_token_get_type(tok
);
44 if (type
!= ISL_TOKEN_IDENT
&& type
!= ISL_TOKEN_STRING
) {
45 isl_stream_error(s
, tok
, "expecting key");
46 return isl_schedule_key_error
;
48 name
= isl_token_get_str(ctx
, tok
);
49 if (!strcmp(name
, "child"))
50 key
= isl_schedule_key_child
;
51 else if (!strcmp(name
, "coincident"))
52 key
= isl_schedule_key_coincident
;
53 else if (!strcmp(name
, "context"))
54 key
= isl_schedule_key_context
;
55 else if (!strcmp(name
, "contraction"))
56 key
= isl_schedule_key_contraction
;
57 else if (!strcmp(name
, "domain"))
58 key
= isl_schedule_key_domain
;
59 else if (!strcmp(name
, "expansion"))
60 key
= isl_schedule_key_expansion
;
61 else if (!strcmp(name
, "filter"))
62 key
= isl_schedule_key_filter
;
63 else if (!strcmp(name
, "guard"))
64 key
= isl_schedule_key_guard
;
65 else if (!strcmp(name
, "leaf"))
66 key
= isl_schedule_key_leaf
;
67 else if (!strcmp(name
, "mark"))
68 key
= isl_schedule_key_mark
;
69 else if (!strcmp(name
, "options"))
70 key
= isl_schedule_key_options
;
71 else if (!strcmp(name
, "schedule"))
72 key
= isl_schedule_key_schedule
;
73 else if (!strcmp(name
, "sequence"))
74 key
= isl_schedule_key_sequence
;
75 else if (!strcmp(name
, "set"))
76 key
= isl_schedule_key_set
;
77 else if (!strcmp(name
, "permutable"))
78 key
= isl_schedule_key_permutable
;
80 isl_die(ctx
, isl_error_invalid
, "unknown key",
81 key
= isl_schedule_key_error
);
86 /* Read a key from "s" and return the corresponding enum.
87 * Return isl_schedule_key_error on error, i.e., if the first token
88 * on the stream does not correspond to any known key.
90 static enum isl_schedule_key
get_key(__isl_keep isl_stream
*s
)
92 struct isl_token
*tok
;
93 enum isl_schedule_key key
;
95 tok
= isl_stream_next_token(s
);
96 key
= extract_key(s
, tok
);
102 static __isl_give isl_schedule_tree
*isl_stream_read_schedule_tree(
103 __isl_keep isl_stream
*s
);
105 /* Read a subtree with context root node from "s".
107 static __isl_give isl_schedule_tree
*read_context(__isl_keep isl_stream
*s
)
109 isl_set
*context
= NULL
;
110 isl_schedule_tree
*tree
;
112 struct isl_token
*tok
;
113 enum isl_schedule_key key
;
117 ctx
= isl_stream_get_ctx(s
);
121 if (isl_stream_yaml_next(s
) < 0)
124 tok
= isl_stream_next_token(s
);
126 isl_stream_error(s
, NULL
, "unexpected EOF");
129 str
= isl_token_get_str(ctx
, tok
);
130 context
= isl_set_read_from_str(ctx
, str
);
134 more
= isl_stream_yaml_next(s
);
138 tree
= isl_schedule_tree_from_context(context
);
141 if (key
!= isl_schedule_key_child
)
142 isl_die(ctx
, isl_error_invalid
, "expecting child",
144 if (isl_stream_yaml_next(s
) < 0)
146 tree
= isl_stream_read_schedule_tree(s
);
147 tree
= isl_schedule_tree_insert_context(tree
, context
);
152 isl_set_free(context
);
156 /* Read a subtree with domain root node from "s".
158 static __isl_give isl_schedule_tree
*read_domain(__isl_keep isl_stream
*s
)
160 isl_union_set
*domain
= NULL
;
161 isl_schedule_tree
*tree
;
163 struct isl_token
*tok
;
164 enum isl_schedule_key key
;
168 ctx
= isl_stream_get_ctx(s
);
172 if (isl_stream_yaml_next(s
) < 0)
175 tok
= isl_stream_next_token(s
);
177 isl_stream_error(s
, NULL
, "unexpected EOF");
180 str
= isl_token_get_str(ctx
, tok
);
181 domain
= isl_union_set_read_from_str(ctx
, str
);
185 more
= isl_stream_yaml_next(s
);
189 tree
= isl_schedule_tree_from_domain(domain
);
192 if (key
!= isl_schedule_key_child
)
193 isl_die(ctx
, isl_error_invalid
, "expecting child",
195 if (isl_stream_yaml_next(s
) < 0)
197 tree
= isl_stream_read_schedule_tree(s
);
198 tree
= isl_schedule_tree_insert_domain(tree
, domain
);
203 isl_union_set_free(domain
);
207 /* Read a subtree with expansion root node from "s".
209 static __isl_give isl_schedule_tree
*read_expansion(isl_stream
*s
)
212 isl_union_pw_multi_aff
*contraction
= NULL
;
213 isl_union_map
*expansion
= NULL
;
214 isl_schedule_tree
*tree
= NULL
;
217 ctx
= isl_stream_get_ctx(s
);
220 struct isl_token
*tok
;
221 enum isl_schedule_key key
;
225 if (isl_stream_yaml_next(s
) < 0)
229 case isl_schedule_key_contraction
:
230 isl_union_pw_multi_aff_free(contraction
);
231 tok
= isl_stream_next_token(s
);
232 str
= isl_token_get_str(ctx
, tok
);
233 contraction
= isl_union_pw_multi_aff_read_from_str(ctx
,
240 case isl_schedule_key_expansion
:
241 isl_union_map_free(expansion
);
242 tok
= isl_stream_next_token(s
);
243 str
= isl_token_get_str(ctx
, tok
);
244 expansion
= isl_union_map_read_from_str(ctx
, str
);
250 case isl_schedule_key_child
:
251 isl_schedule_tree_free(tree
);
252 tree
= isl_stream_read_schedule_tree(s
);
257 isl_die(ctx
, isl_error_invalid
, "unexpected key",
260 } while ((more
= isl_stream_yaml_next(s
)) > 0);
266 isl_die(ctx
, isl_error_invalid
, "missing contraction",
269 isl_die(ctx
, isl_error_invalid
, "missing expansion",
273 return isl_schedule_tree_from_expansion(contraction
, expansion
);
274 return isl_schedule_tree_insert_expansion(tree
, contraction
, expansion
);
276 isl_schedule_tree_free(tree
);
277 isl_union_pw_multi_aff_free(contraction
);
278 isl_union_map_free(expansion
);
282 /* Read a subtree with filter root node from "s".
284 static __isl_give isl_schedule_tree
*read_filter(__isl_keep isl_stream
*s
)
286 isl_union_set
*filter
= NULL
;
287 isl_schedule_tree
*tree
;
289 struct isl_token
*tok
;
290 enum isl_schedule_key key
;
294 ctx
= isl_stream_get_ctx(s
);
298 if (isl_stream_yaml_next(s
) < 0)
301 tok
= isl_stream_next_token(s
);
303 isl_stream_error(s
, NULL
, "unexpected EOF");
306 str
= isl_token_get_str(ctx
, tok
);
307 filter
= isl_union_set_read_from_str(ctx
, str
);
311 more
= isl_stream_yaml_next(s
);
315 tree
= isl_schedule_tree_from_filter(filter
);
318 if (key
!= isl_schedule_key_child
)
319 isl_die(ctx
, isl_error_invalid
, "expecting child",
321 if (isl_stream_yaml_next(s
) < 0)
323 tree
= isl_stream_read_schedule_tree(s
);
324 tree
= isl_schedule_tree_insert_filter(tree
, filter
);
329 isl_union_set_free(filter
);
333 /* Read a subtree with guard root node from "s".
335 static __isl_give isl_schedule_tree
*read_guard(isl_stream
*s
)
337 isl_set
*guard
= NULL
;
338 isl_schedule_tree
*tree
;
340 struct isl_token
*tok
;
341 enum isl_schedule_key key
;
345 ctx
= isl_stream_get_ctx(s
);
349 if (isl_stream_yaml_next(s
) < 0)
352 tok
= isl_stream_next_token(s
);
354 isl_stream_error(s
, NULL
, "unexpected EOF");
357 str
= isl_token_get_str(ctx
, tok
);
358 guard
= isl_set_read_from_str(ctx
, str
);
362 more
= isl_stream_yaml_next(s
);
366 tree
= isl_schedule_tree_from_guard(guard
);
369 if (key
!= isl_schedule_key_child
)
370 isl_die(ctx
, isl_error_invalid
, "expecting child",
372 if (isl_stream_yaml_next(s
) < 0)
374 tree
= isl_stream_read_schedule_tree(s
);
375 tree
= isl_schedule_tree_insert_guard(tree
, guard
);
384 /* Read a subtree with mark root node from "s".
386 static __isl_give isl_schedule_tree
*read_mark(isl_stream
*s
)
389 isl_schedule_tree
*tree
;
391 struct isl_token
*tok
;
392 enum isl_schedule_key key
;
396 ctx
= isl_stream_get_ctx(s
);
400 if (isl_stream_yaml_next(s
) < 0)
403 tok
= isl_stream_next_token(s
);
405 isl_stream_error(s
, NULL
, "unexpected EOF");
408 str
= isl_token_get_str(ctx
, tok
);
409 mark
= isl_id_alloc(ctx
, str
, NULL
);
413 more
= isl_stream_yaml_next(s
);
417 isl_die(ctx
, isl_error_invalid
, "expecting child",
421 if (key
!= isl_schedule_key_child
)
422 isl_die(ctx
, isl_error_invalid
, "expecting child",
424 if (isl_stream_yaml_next(s
) < 0)
426 tree
= isl_stream_read_schedule_tree(s
);
427 tree
= isl_schedule_tree_insert_mark(tree
, mark
);
436 /* Read a sequence of integers from "s" (representing the coincident
437 * property of a band node).
439 static __isl_give isl_val_list
*read_coincident(__isl_keep isl_stream
*s
)
445 ctx
= isl_stream_get_ctx(s
);
447 if (isl_stream_yaml_read_start_sequence(s
) < 0)
450 list
= isl_val_list_alloc(ctx
, 0);
451 while ((more
= isl_stream_yaml_next(s
)) > 0) {
454 val
= isl_stream_read_val(s
);
455 list
= isl_val_list_add(list
, val
);
458 if (more
< 0 || isl_stream_yaml_read_end_sequence(s
))
459 list
= isl_val_list_free(list
);
464 /* Set the (initial) coincident properties of "band" according to
465 * the (initial) elements of "coincident".
467 static __isl_give isl_schedule_band
*set_coincident(
468 __isl_take isl_schedule_band
*band
, __isl_take isl_val_list
*coincident
)
473 n
= isl_schedule_band_n_member(band
);
474 m
= isl_val_list_n_val(coincident
);
476 for (i
= 0; i
< n
&& i
< m
; ++i
) {
479 v
= isl_val_list_get_val(coincident
, i
);
481 band
= isl_schedule_band_free(band
);
482 band
= isl_schedule_band_member_set_coincident(band
, i
,
483 !isl_val_is_zero(v
));
486 isl_val_list_free(coincident
);
490 /* Read a subtree with band root node from "s".
492 static __isl_give isl_schedule_tree
*read_band(isl_stream
*s
)
494 isl_multi_union_pw_aff
*schedule
= NULL
;
495 isl_schedule_tree
*tree
= NULL
;
496 isl_val_list
*coincident
= NULL
;
497 isl_union_set
*options
= NULL
;
499 isl_schedule_band
*band
;
503 ctx
= isl_stream_get_ctx(s
);
506 struct isl_token
*tok
;
507 enum isl_schedule_key key
;
512 if (isl_stream_yaml_next(s
) < 0)
516 case isl_schedule_key_schedule
:
517 isl_multi_union_pw_aff_free(schedule
);
518 tok
= isl_stream_next_token(s
);
520 isl_stream_error(s
, NULL
, "unexpected EOF");
523 str
= isl_token_get_str(ctx
, tok
);
524 schedule
= isl_multi_union_pw_aff_read_from_str(ctx
,
531 case isl_schedule_key_coincident
:
532 coincident
= read_coincident(s
);
536 case isl_schedule_key_permutable
:
537 v
= isl_stream_read_val(s
);
538 permutable
= !isl_val_is_zero(v
);
541 case isl_schedule_key_options
:
542 isl_union_set_free(options
);
543 tok
= isl_stream_next_token(s
);
544 str
= isl_token_get_str(ctx
, tok
);
545 options
= isl_union_set_read_from_str(ctx
, str
);
551 case isl_schedule_key_child
:
552 isl_schedule_tree_free(tree
);
553 tree
= isl_stream_read_schedule_tree(s
);
558 isl_die(ctx
, isl_error_invalid
, "unexpected key",
561 } while ((more
= isl_stream_yaml_next(s
)) > 0);
567 isl_die(ctx
, isl_error_invalid
, "missing schedule", goto error
);
569 band
= isl_schedule_band_from_multi_union_pw_aff(schedule
);
570 band
= isl_schedule_band_set_permutable(band
, permutable
);
572 band
= set_coincident(band
, coincident
);
574 band
= isl_schedule_band_set_ast_build_options(band
, options
);
576 tree
= isl_schedule_tree_insert_band(tree
, band
);
578 tree
= isl_schedule_tree_from_band(band
);
582 isl_val_list_free(coincident
);
583 isl_union_set_free(options
);
584 isl_schedule_tree_free(tree
);
585 isl_multi_union_pw_aff_free(schedule
);
589 /* Read a subtree with root node of type "type" from "s".
590 * The node is represented by a sequence of children.
592 static __isl_give isl_schedule_tree
*read_children(isl_stream
*s
,
593 enum isl_schedule_node_type type
)
596 isl_schedule_tree_list
*list
;
599 ctx
= isl_stream_get_ctx(s
);
601 isl_token_free(isl_stream_next_token(s
));
603 if (isl_stream_yaml_next(s
) < 0)
606 if (isl_stream_yaml_read_start_sequence(s
))
609 list
= isl_schedule_tree_list_alloc(ctx
, 0);
610 while ((more
= isl_stream_yaml_next(s
)) > 0) {
611 isl_schedule_tree
*tree
;
613 tree
= isl_stream_read_schedule_tree(s
);
614 list
= isl_schedule_tree_list_add(list
, tree
);
617 if (more
< 0 || isl_stream_yaml_read_end_sequence(s
))
618 list
= isl_schedule_tree_list_free(list
);
620 return isl_schedule_tree_from_children(type
, list
);
623 /* Read a subtree with sequence root node from "s".
625 static __isl_give isl_schedule_tree
*read_sequence(isl_stream
*s
)
627 return read_children(s
, isl_schedule_node_sequence
);
630 /* Read a subtree with set root node from "s".
632 static __isl_give isl_schedule_tree
*read_set(isl_stream
*s
)
634 return read_children(s
, isl_schedule_node_set
);
637 /* Read a schedule (sub)tree from "s".
639 * We first determine the type of the root node based on the first
640 * mapping key and then hand over to a function tailored to reading
641 * nodes of this type.
643 static __isl_give isl_schedule_tree
*isl_stream_read_schedule_tree(
644 struct isl_stream
*s
)
646 enum isl_schedule_key key
;
647 struct isl_token
*tok
;
648 isl_schedule_tree
*tree
= NULL
;
651 if (isl_stream_yaml_read_start_mapping(s
))
653 more
= isl_stream_yaml_next(s
);
657 isl_stream_error(s
, NULL
, "missing key");
661 tok
= isl_stream_next_token(s
);
662 key
= extract_key(s
, tok
);
663 isl_stream_push_token(s
, tok
);
667 case isl_schedule_key_context
:
668 tree
= read_context(s
);
670 case isl_schedule_key_domain
:
671 tree
= read_domain(s
);
673 case isl_schedule_key_contraction
:
674 case isl_schedule_key_expansion
:
675 tree
= read_expansion(s
);
677 case isl_schedule_key_filter
:
678 tree
= read_filter(s
);
680 case isl_schedule_key_guard
:
681 tree
= read_guard(s
);
683 case isl_schedule_key_leaf
:
684 isl_token_free(isl_stream_next_token(s
));
685 tree
= isl_schedule_tree_leaf(isl_stream_get_ctx(s
));
687 case isl_schedule_key_mark
:
690 case isl_schedule_key_sequence
:
691 tree
= read_sequence(s
);
693 case isl_schedule_key_set
:
696 case isl_schedule_key_schedule
:
697 case isl_schedule_key_coincident
:
698 case isl_schedule_key_options
:
699 case isl_schedule_key_permutable
:
702 case isl_schedule_key_child
:
703 isl_die(isl_stream_get_ctx(s
), isl_error_unsupported
,
704 "cannot identity node type", return NULL
);
705 case isl_schedule_key_error
:
709 if (isl_stream_yaml_read_end_mapping(s
) < 0) {
710 isl_stream_error(s
, NULL
, "unexpected extra elements");
711 return isl_schedule_tree_free(tree
);
717 /* Read an isl_schedule from "s".
719 __isl_give isl_schedule
*isl_stream_read_schedule(isl_stream
*s
)
722 isl_schedule_tree
*tree
;
727 ctx
= isl_stream_get_ctx(s
);
728 tree
= isl_stream_read_schedule_tree(s
);
729 return isl_schedule_from_schedule_tree(ctx
, tree
);
732 /* Read an isl_schedule from "input".
734 __isl_give isl_schedule
*isl_schedule_read_from_file(isl_ctx
*ctx
, FILE *input
)
736 struct isl_stream
*s
;
737 isl_schedule
*schedule
;
739 s
= isl_stream_new_file(ctx
, input
);
742 schedule
= isl_stream_read_schedule(s
);
748 /* Read an isl_schedule from "str".
750 __isl_give isl_schedule
*isl_schedule_read_from_str(isl_ctx
*ctx
,
753 struct isl_stream
*s
;
754 isl_schedule
*schedule
;
756 s
= isl_stream_new_str(ctx
, str
);
759 schedule
= isl_stream_read_schedule(s
);