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",
54 #define KEY enum isl_schedule_key
56 #define KEY_ERROR isl_schedule_key_error
58 #define KEY_END isl_schedule_key_end
59 #include "extract_key.c"
61 static __isl_give isl_schedule_tree
*isl_stream_read_schedule_tree(
62 __isl_keep isl_stream
*s
);
64 /* Read a subtree with context root node from "s".
66 static __isl_give isl_schedule_tree
*read_context(__isl_keep isl_stream
*s
)
68 isl_set
*context
= NULL
;
69 isl_schedule_tree
*tree
;
71 struct isl_token
*tok
;
72 enum isl_schedule_key key
;
76 ctx
= isl_stream_get_ctx(s
);
80 if (isl_stream_yaml_next(s
) < 0)
83 tok
= isl_stream_next_token(s
);
85 isl_stream_error(s
, NULL
, "unexpected EOF");
88 str
= isl_token_get_str(ctx
, tok
);
89 context
= isl_set_read_from_str(ctx
, str
);
93 more
= isl_stream_yaml_next(s
);
97 tree
= isl_schedule_tree_from_context(context
);
100 if (key
!= isl_schedule_key_child
)
101 isl_die(ctx
, isl_error_invalid
, "expecting child",
103 if (isl_stream_yaml_next(s
) < 0)
105 tree
= isl_stream_read_schedule_tree(s
);
106 tree
= isl_schedule_tree_insert_context(tree
, context
);
111 isl_set_free(context
);
115 /* Read a subtree with domain root node from "s".
117 static __isl_give isl_schedule_tree
*read_domain(__isl_keep isl_stream
*s
)
119 isl_union_set
*domain
= NULL
;
120 isl_schedule_tree
*tree
;
122 struct isl_token
*tok
;
123 enum isl_schedule_key key
;
127 ctx
= isl_stream_get_ctx(s
);
131 if (isl_stream_yaml_next(s
) < 0)
134 tok
= isl_stream_next_token(s
);
136 isl_stream_error(s
, NULL
, "unexpected EOF");
139 str
= isl_token_get_str(ctx
, tok
);
140 domain
= isl_union_set_read_from_str(ctx
, str
);
144 more
= isl_stream_yaml_next(s
);
148 tree
= isl_schedule_tree_from_domain(domain
);
151 if (key
!= isl_schedule_key_child
)
152 isl_die(ctx
, isl_error_invalid
, "expecting child",
154 if (isl_stream_yaml_next(s
) < 0)
156 tree
= isl_stream_read_schedule_tree(s
);
157 tree
= isl_schedule_tree_insert_domain(tree
, domain
);
162 isl_union_set_free(domain
);
166 /* Read a subtree with expansion root node from "s".
168 static __isl_give isl_schedule_tree
*read_expansion(isl_stream
*s
)
171 isl_union_pw_multi_aff
*contraction
= NULL
;
172 isl_union_map
*expansion
= NULL
;
173 isl_schedule_tree
*tree
= NULL
;
176 ctx
= isl_stream_get_ctx(s
);
179 struct isl_token
*tok
;
180 enum isl_schedule_key key
;
184 if (isl_stream_yaml_next(s
) < 0)
188 case isl_schedule_key_contraction
:
189 isl_union_pw_multi_aff_free(contraction
);
190 tok
= isl_stream_next_token(s
);
191 str
= isl_token_get_str(ctx
, tok
);
192 contraction
= isl_union_pw_multi_aff_read_from_str(ctx
,
199 case isl_schedule_key_expansion
:
200 isl_union_map_free(expansion
);
201 tok
= isl_stream_next_token(s
);
202 str
= isl_token_get_str(ctx
, tok
);
203 expansion
= isl_union_map_read_from_str(ctx
, str
);
209 case isl_schedule_key_child
:
210 isl_schedule_tree_free(tree
);
211 tree
= isl_stream_read_schedule_tree(s
);
216 isl_die(ctx
, isl_error_invalid
, "unexpected key",
219 } while ((more
= isl_stream_yaml_next(s
)) > 0);
225 isl_die(ctx
, isl_error_invalid
, "missing contraction",
228 isl_die(ctx
, isl_error_invalid
, "missing expansion",
232 return isl_schedule_tree_from_expansion(contraction
, expansion
);
233 return isl_schedule_tree_insert_expansion(tree
, contraction
, expansion
);
235 isl_schedule_tree_free(tree
);
236 isl_union_pw_multi_aff_free(contraction
);
237 isl_union_map_free(expansion
);
241 /* Read a subtree with extension root node from "s".
243 static __isl_give isl_schedule_tree
*read_extension(isl_stream
*s
)
245 isl_union_map
*extension
= NULL
;
246 isl_schedule_tree
*tree
;
248 struct isl_token
*tok
;
249 enum isl_schedule_key key
;
253 ctx
= isl_stream_get_ctx(s
);
257 if (isl_stream_yaml_next(s
) < 0)
260 tok
= isl_stream_next_token(s
);
262 isl_stream_error(s
, NULL
, "unexpected EOF");
265 str
= isl_token_get_str(ctx
, tok
);
266 extension
= isl_union_map_read_from_str(ctx
, str
);
270 more
= isl_stream_yaml_next(s
);
274 tree
= isl_schedule_tree_from_extension(extension
);
277 if (key
!= isl_schedule_key_child
)
278 isl_die(ctx
, isl_error_invalid
, "expecting child",
280 if (isl_stream_yaml_next(s
) < 0)
282 tree
= isl_stream_read_schedule_tree(s
);
283 tree
= isl_schedule_tree_insert_extension(tree
, extension
);
288 isl_union_map_free(extension
);
292 /* Read a subtree with filter root node from "s".
294 static __isl_give isl_schedule_tree
*read_filter(__isl_keep isl_stream
*s
)
296 isl_union_set
*filter
= NULL
;
297 isl_schedule_tree
*tree
;
299 struct isl_token
*tok
;
300 enum isl_schedule_key key
;
304 ctx
= isl_stream_get_ctx(s
);
308 if (isl_stream_yaml_next(s
) < 0)
311 tok
= isl_stream_next_token(s
);
313 isl_stream_error(s
, NULL
, "unexpected EOF");
316 str
= isl_token_get_str(ctx
, tok
);
317 filter
= isl_union_set_read_from_str(ctx
, str
);
321 more
= isl_stream_yaml_next(s
);
325 tree
= isl_schedule_tree_from_filter(filter
);
328 if (key
!= isl_schedule_key_child
)
329 isl_die(ctx
, isl_error_invalid
, "expecting child",
331 if (isl_stream_yaml_next(s
) < 0)
333 tree
= isl_stream_read_schedule_tree(s
);
334 tree
= isl_schedule_tree_insert_filter(tree
, filter
);
339 isl_union_set_free(filter
);
343 /* Read a subtree with guard root node from "s".
345 static __isl_give isl_schedule_tree
*read_guard(isl_stream
*s
)
347 isl_set
*guard
= NULL
;
348 isl_schedule_tree
*tree
;
350 struct isl_token
*tok
;
351 enum isl_schedule_key key
;
355 ctx
= isl_stream_get_ctx(s
);
359 if (isl_stream_yaml_next(s
) < 0)
362 tok
= isl_stream_next_token(s
);
364 isl_stream_error(s
, NULL
, "unexpected EOF");
367 str
= isl_token_get_str(ctx
, tok
);
368 guard
= isl_set_read_from_str(ctx
, str
);
372 more
= isl_stream_yaml_next(s
);
376 tree
= isl_schedule_tree_from_guard(guard
);
379 if (key
!= isl_schedule_key_child
)
380 isl_die(ctx
, isl_error_invalid
, "expecting child",
382 if (isl_stream_yaml_next(s
) < 0)
384 tree
= isl_stream_read_schedule_tree(s
);
385 tree
= isl_schedule_tree_insert_guard(tree
, guard
);
394 /* Read a subtree with mark root node from "s".
396 static __isl_give isl_schedule_tree
*read_mark(isl_stream
*s
)
399 isl_schedule_tree
*tree
;
401 struct isl_token
*tok
;
402 enum isl_schedule_key key
;
406 ctx
= isl_stream_get_ctx(s
);
410 if (isl_stream_yaml_next(s
) < 0)
413 tok
= isl_stream_next_token(s
);
415 isl_stream_error(s
, NULL
, "unexpected EOF");
418 str
= isl_token_get_str(ctx
, tok
);
419 mark
= isl_id_alloc(ctx
, str
, NULL
);
423 more
= isl_stream_yaml_next(s
);
427 isl_die(ctx
, isl_error_invalid
, "expecting child",
431 if (key
!= isl_schedule_key_child
)
432 isl_die(ctx
, isl_error_invalid
, "expecting child",
434 if (isl_stream_yaml_next(s
) < 0)
436 tree
= isl_stream_read_schedule_tree(s
);
437 tree
= isl_schedule_tree_insert_mark(tree
, mark
);
446 /* Read a sequence of integers from "s" (representing the coincident
447 * property of a band node).
449 static __isl_give isl_val_list
*read_coincident(__isl_keep isl_stream
*s
)
455 ctx
= isl_stream_get_ctx(s
);
457 if (isl_stream_yaml_read_start_sequence(s
) < 0)
460 list
= isl_val_list_alloc(ctx
, 0);
461 while ((more
= isl_stream_yaml_next(s
)) > 0) {
464 val
= isl_stream_read_val(s
);
465 list
= isl_val_list_add(list
, val
);
468 if (more
< 0 || isl_stream_yaml_read_end_sequence(s
))
469 list
= isl_val_list_free(list
);
474 /* Set the (initial) coincident properties of "band" according to
475 * the (initial) elements of "coincident".
477 static __isl_give isl_schedule_band
*set_coincident(
478 __isl_take isl_schedule_band
*band
, __isl_take isl_val_list
*coincident
)
483 n
= isl_schedule_band_n_member(band
);
484 m
= isl_val_list_n_val(coincident
);
486 band
= isl_schedule_band_free(band
);
488 for (i
= 0; i
< n
&& i
< m
; ++i
) {
491 v
= isl_val_list_get_val(coincident
, i
);
493 band
= isl_schedule_band_free(band
);
494 band
= isl_schedule_band_member_set_coincident(band
, i
,
495 !isl_val_is_zero(v
));
498 isl_val_list_free(coincident
);
502 /* Read a subtree with band root node from "s".
504 static __isl_give isl_schedule_tree
*read_band(isl_stream
*s
)
506 isl_multi_union_pw_aff
*schedule
= NULL
;
507 isl_schedule_tree
*tree
= NULL
;
508 isl_val_list
*coincident
= NULL
;
509 isl_union_set
*options
= NULL
;
511 isl_schedule_band
*band
;
515 ctx
= isl_stream_get_ctx(s
);
518 struct isl_token
*tok
;
519 enum isl_schedule_key key
;
524 if (isl_stream_yaml_next(s
) < 0)
528 case isl_schedule_key_schedule
:
529 schedule
= isl_multi_union_pw_aff_free(schedule
);
530 tok
= isl_stream_next_token(s
);
532 isl_stream_error(s
, NULL
, "unexpected EOF");
535 str
= isl_token_get_str(ctx
, tok
);
536 schedule
= isl_multi_union_pw_aff_read_from_str(ctx
,
543 case isl_schedule_key_coincident
:
544 coincident
= read_coincident(s
);
548 case isl_schedule_key_permutable
:
549 v
= isl_stream_read_val(s
);
550 permutable
= !isl_val_is_zero(v
);
553 case isl_schedule_key_options
:
554 isl_union_set_free(options
);
555 tok
= isl_stream_next_token(s
);
556 str
= isl_token_get_str(ctx
, tok
);
557 options
= isl_union_set_read_from_str(ctx
, str
);
563 case isl_schedule_key_child
:
564 isl_schedule_tree_free(tree
);
565 tree
= isl_stream_read_schedule_tree(s
);
570 isl_die(ctx
, isl_error_invalid
, "unexpected key",
573 } while ((more
= isl_stream_yaml_next(s
)) > 0);
579 isl_die(ctx
, isl_error_invalid
, "missing schedule", goto error
);
581 band
= isl_schedule_band_from_multi_union_pw_aff(schedule
);
582 band
= isl_schedule_band_set_permutable(band
, permutable
);
584 band
= set_coincident(band
, coincident
);
586 band
= isl_schedule_band_set_ast_build_options(band
, options
);
588 tree
= isl_schedule_tree_insert_band(tree
, band
);
590 tree
= isl_schedule_tree_from_band(band
);
594 isl_val_list_free(coincident
);
595 isl_union_set_free(options
);
596 isl_schedule_tree_free(tree
);
597 isl_multi_union_pw_aff_free(schedule
);
601 /* Read a subtree with root node of type "type" from "s".
602 * The node is represented by a sequence of children.
604 static __isl_give isl_schedule_tree
*read_children(isl_stream
*s
,
605 enum isl_schedule_node_type type
)
608 isl_schedule_tree_list
*list
;
611 ctx
= isl_stream_get_ctx(s
);
613 isl_token_free(isl_stream_next_token(s
));
615 if (isl_stream_yaml_next(s
) < 0)
618 if (isl_stream_yaml_read_start_sequence(s
))
621 list
= isl_schedule_tree_list_alloc(ctx
, 0);
622 while ((more
= isl_stream_yaml_next(s
)) > 0) {
623 isl_schedule_tree
*tree
;
625 tree
= isl_stream_read_schedule_tree(s
);
626 list
= isl_schedule_tree_list_add(list
, tree
);
629 if (more
< 0 || isl_stream_yaml_read_end_sequence(s
))
630 list
= isl_schedule_tree_list_free(list
);
632 return isl_schedule_tree_from_children(type
, list
);
635 /* Read a subtree with sequence root node from "s".
637 static __isl_give isl_schedule_tree
*read_sequence(isl_stream
*s
)
639 return read_children(s
, isl_schedule_node_sequence
);
642 /* Read a subtree with set root node from "s".
644 static __isl_give isl_schedule_tree
*read_set(isl_stream
*s
)
646 return read_children(s
, isl_schedule_node_set
);
649 /* Read a schedule (sub)tree from "s".
651 * We first determine the type of the root node based on the first
652 * mapping key and then hand over to a function tailored to reading
653 * nodes of this type.
655 static __isl_give isl_schedule_tree
*isl_stream_read_schedule_tree(
656 struct isl_stream
*s
)
658 enum isl_schedule_key key
;
659 struct isl_token
*tok
;
660 isl_schedule_tree
*tree
= NULL
;
663 if (isl_stream_yaml_read_start_mapping(s
))
665 more
= isl_stream_yaml_next(s
);
669 isl_stream_error(s
, NULL
, "missing key");
673 tok
= isl_stream_next_token(s
);
674 key
= extract_key(s
, tok
);
675 isl_stream_push_token(s
, tok
);
679 case isl_schedule_key_context
:
680 tree
= read_context(s
);
682 case isl_schedule_key_domain
:
683 tree
= read_domain(s
);
685 case isl_schedule_key_contraction
:
686 case isl_schedule_key_expansion
:
687 tree
= read_expansion(s
);
689 case isl_schedule_key_extension
:
690 tree
= read_extension(s
);
692 case isl_schedule_key_filter
:
693 tree
= read_filter(s
);
695 case isl_schedule_key_guard
:
696 tree
= read_guard(s
);
698 case isl_schedule_key_leaf
:
699 isl_token_free(isl_stream_next_token(s
));
700 tree
= isl_schedule_tree_leaf(isl_stream_get_ctx(s
));
702 case isl_schedule_key_mark
:
705 case isl_schedule_key_sequence
:
706 tree
= read_sequence(s
);
708 case isl_schedule_key_set
:
711 case isl_schedule_key_schedule
:
712 case isl_schedule_key_coincident
:
713 case isl_schedule_key_options
:
714 case isl_schedule_key_permutable
:
717 case isl_schedule_key_child
:
718 isl_die(isl_stream_get_ctx(s
), isl_error_unsupported
,
719 "cannot identify node type", return NULL
);
720 case isl_schedule_key_end
:
721 case isl_schedule_key_error
:
725 if (isl_stream_yaml_read_end_mapping(s
) < 0) {
726 isl_stream_error(s
, NULL
, "unexpected extra elements");
727 return isl_schedule_tree_free(tree
);
733 /* Read an isl_schedule from "s".
735 __isl_give isl_schedule
*isl_stream_read_schedule(isl_stream
*s
)
738 isl_schedule_tree
*tree
;
743 ctx
= isl_stream_get_ctx(s
);
744 tree
= isl_stream_read_schedule_tree(s
);
745 return isl_schedule_from_schedule_tree(ctx
, tree
);
748 /* Read an isl_schedule from "input".
750 __isl_give isl_schedule
*isl_schedule_read_from_file(isl_ctx
*ctx
, FILE *input
)
752 struct isl_stream
*s
;
753 isl_schedule
*schedule
;
755 s
= isl_stream_new_file(ctx
, input
);
758 schedule
= isl_stream_read_schedule(s
);
764 /* Read an isl_schedule from "str".
766 __isl_give isl_schedule
*isl_schedule_read_from_str(isl_ctx
*ctx
,
769 struct isl_stream
*s
;
770 isl_schedule
*schedule
;
772 s
= isl_stream_new_str(ctx
, str
);
775 schedule
= isl_stream_read_schedule(s
);