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_leaf
,
21 isl_schedule_key_mark
,
22 isl_schedule_key_options
,
23 isl_schedule_key_permutable
,
24 isl_schedule_key_schedule
,
25 isl_schedule_key_sequence
,
29 /* Extract a mapping key from the token "tok".
30 * Return isl_schedule_key_error on error, i.e., if "tok" does not
31 * correspond to any known key.
33 static enum isl_schedule_key
extract_key(__isl_keep isl_stream
*s
,
34 struct isl_token
*tok
)
38 enum isl_schedule_key key
;
41 ctx
= isl_stream_get_ctx(s
);
42 type
= isl_token_get_type(tok
);
43 if (type
!= ISL_TOKEN_IDENT
&& type
!= ISL_TOKEN_STRING
) {
44 isl_stream_error(s
, tok
, "expecting key");
45 return isl_schedule_key_error
;
47 name
= isl_token_get_str(ctx
, tok
);
48 if (!strcmp(name
, "child"))
49 key
= isl_schedule_key_child
;
50 else if (!strcmp(name
, "coincident"))
51 key
= isl_schedule_key_coincident
;
52 else if (!strcmp(name
, "context"))
53 key
= isl_schedule_key_context
;
54 else if (!strcmp(name
, "contraction"))
55 key
= isl_schedule_key_contraction
;
56 else if (!strcmp(name
, "domain"))
57 key
= isl_schedule_key_domain
;
58 else if (!strcmp(name
, "expansion"))
59 key
= isl_schedule_key_expansion
;
60 else if (!strcmp(name
, "filter"))
61 key
= isl_schedule_key_filter
;
62 else if (!strcmp(name
, "leaf"))
63 key
= isl_schedule_key_leaf
;
64 else if (!strcmp(name
, "mark"))
65 key
= isl_schedule_key_mark
;
66 else if (!strcmp(name
, "options"))
67 key
= isl_schedule_key_options
;
68 else if (!strcmp(name
, "schedule"))
69 key
= isl_schedule_key_schedule
;
70 else if (!strcmp(name
, "sequence"))
71 key
= isl_schedule_key_sequence
;
72 else if (!strcmp(name
, "set"))
73 key
= isl_schedule_key_set
;
74 else if (!strcmp(name
, "permutable"))
75 key
= isl_schedule_key_permutable
;
77 isl_die(ctx
, isl_error_invalid
, "unknown key",
78 key
= isl_schedule_key_error
);
83 /* Read a key from "s" and return the corresponding enum.
84 * Return isl_schedule_key_error on error, i.e., if the first token
85 * on the stream does not correspond to any known key.
87 static enum isl_schedule_key
get_key(__isl_keep isl_stream
*s
)
89 struct isl_token
*tok
;
90 enum isl_schedule_key key
;
92 tok
= isl_stream_next_token(s
);
93 key
= extract_key(s
, tok
);
99 static __isl_give isl_schedule_tree
*isl_stream_read_schedule_tree(
100 __isl_keep isl_stream
*s
);
102 /* Read a subtree with context root node from "s".
104 static __isl_give isl_schedule_tree
*read_context(__isl_keep isl_stream
*s
)
106 isl_set
*context
= NULL
;
107 isl_schedule_tree
*tree
;
109 struct isl_token
*tok
;
110 enum isl_schedule_key key
;
114 ctx
= isl_stream_get_ctx(s
);
118 if (isl_stream_yaml_next(s
) < 0)
121 tok
= isl_stream_next_token(s
);
123 isl_stream_error(s
, NULL
, "unexpected EOF");
126 str
= isl_token_get_str(ctx
, tok
);
127 context
= isl_set_read_from_str(ctx
, str
);
131 more
= isl_stream_yaml_next(s
);
135 tree
= isl_schedule_tree_from_context(context
);
138 if (key
!= isl_schedule_key_child
)
139 isl_die(ctx
, isl_error_invalid
, "expecting child",
141 if (isl_stream_yaml_next(s
) < 0)
143 tree
= isl_stream_read_schedule_tree(s
);
144 tree
= isl_schedule_tree_insert_context(tree
, context
);
149 isl_set_free(context
);
153 /* Read a subtree with domain root node from "s".
155 static __isl_give isl_schedule_tree
*read_domain(__isl_keep isl_stream
*s
)
157 isl_union_set
*domain
= NULL
;
158 isl_schedule_tree
*tree
;
160 struct isl_token
*tok
;
161 enum isl_schedule_key key
;
165 ctx
= isl_stream_get_ctx(s
);
169 if (isl_stream_yaml_next(s
) < 0)
172 tok
= isl_stream_next_token(s
);
174 isl_stream_error(s
, NULL
, "unexpected EOF");
177 str
= isl_token_get_str(ctx
, tok
);
178 domain
= isl_union_set_read_from_str(ctx
, str
);
182 more
= isl_stream_yaml_next(s
);
186 tree
= isl_schedule_tree_from_domain(domain
);
189 if (key
!= isl_schedule_key_child
)
190 isl_die(ctx
, isl_error_invalid
, "expecting child",
192 if (isl_stream_yaml_next(s
) < 0)
194 tree
= isl_stream_read_schedule_tree(s
);
195 tree
= isl_schedule_tree_insert_domain(tree
, domain
);
200 isl_union_set_free(domain
);
204 /* Read a subtree with expansion root node from "s".
206 static __isl_give isl_schedule_tree
*read_expansion(isl_stream
*s
)
209 isl_union_pw_multi_aff
*contraction
= NULL
;
210 isl_union_map
*expansion
= NULL
;
211 isl_schedule_tree
*tree
= NULL
;
214 ctx
= isl_stream_get_ctx(s
);
217 struct isl_token
*tok
;
218 enum isl_schedule_key key
;
222 if (isl_stream_yaml_next(s
) < 0)
226 case isl_schedule_key_contraction
:
227 isl_union_pw_multi_aff_free(contraction
);
228 tok
= isl_stream_next_token(s
);
229 str
= isl_token_get_str(ctx
, tok
);
230 contraction
= isl_union_pw_multi_aff_read_from_str(ctx
,
237 case isl_schedule_key_expansion
:
238 isl_union_map_free(expansion
);
239 tok
= isl_stream_next_token(s
);
240 str
= isl_token_get_str(ctx
, tok
);
241 expansion
= isl_union_map_read_from_str(ctx
, str
);
247 case isl_schedule_key_child
:
248 isl_schedule_tree_free(tree
);
249 tree
= isl_stream_read_schedule_tree(s
);
254 isl_die(ctx
, isl_error_invalid
, "unexpected key",
257 } while ((more
= isl_stream_yaml_next(s
)) > 0);
263 isl_die(ctx
, isl_error_invalid
, "missing contraction",
266 isl_die(ctx
, isl_error_invalid
, "missing expansion",
270 return isl_schedule_tree_from_expansion(contraction
, expansion
);
271 return isl_schedule_tree_insert_expansion(tree
, contraction
, expansion
);
273 isl_schedule_tree_free(tree
);
274 isl_union_pw_multi_aff_free(contraction
);
275 isl_union_map_free(expansion
);
279 /* Read a subtree with filter root node from "s".
281 static __isl_give isl_schedule_tree
*read_filter(__isl_keep isl_stream
*s
)
283 isl_union_set
*filter
= NULL
;
284 isl_schedule_tree
*tree
;
286 struct isl_token
*tok
;
287 enum isl_schedule_key key
;
291 ctx
= isl_stream_get_ctx(s
);
295 if (isl_stream_yaml_next(s
) < 0)
298 tok
= isl_stream_next_token(s
);
300 isl_stream_error(s
, NULL
, "unexpected EOF");
303 str
= isl_token_get_str(ctx
, tok
);
304 filter
= isl_union_set_read_from_str(ctx
, str
);
308 more
= isl_stream_yaml_next(s
);
312 tree
= isl_schedule_tree_from_filter(filter
);
315 if (key
!= isl_schedule_key_child
)
316 isl_die(ctx
, isl_error_invalid
, "expecting child",
318 if (isl_stream_yaml_next(s
) < 0)
320 tree
= isl_stream_read_schedule_tree(s
);
321 tree
= isl_schedule_tree_insert_filter(tree
, filter
);
326 isl_union_set_free(filter
);
330 /* Read a subtree with mark root node from "s".
332 static __isl_give isl_schedule_tree
*read_mark(isl_stream
*s
)
335 isl_schedule_tree
*tree
;
337 struct isl_token
*tok
;
338 enum isl_schedule_key key
;
342 ctx
= isl_stream_get_ctx(s
);
346 if (isl_stream_yaml_next(s
) < 0)
349 tok
= isl_stream_next_token(s
);
351 isl_stream_error(s
, NULL
, "unexpected EOF");
354 str
= isl_token_get_str(ctx
, tok
);
355 mark
= isl_id_alloc(ctx
, str
, NULL
);
359 more
= isl_stream_yaml_next(s
);
363 isl_die(ctx
, isl_error_invalid
, "expecting child",
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_mark(tree
, mark
);
382 /* Read a sequence of integers from "s" (representing the coincident
383 * property of a band node).
385 static __isl_give isl_val_list
*read_coincident(__isl_keep isl_stream
*s
)
391 ctx
= isl_stream_get_ctx(s
);
393 if (isl_stream_yaml_read_start_sequence(s
) < 0)
396 list
= isl_val_list_alloc(ctx
, 0);
397 while ((more
= isl_stream_yaml_next(s
)) > 0) {
400 val
= isl_stream_read_val(s
);
401 list
= isl_val_list_add(list
, val
);
404 if (more
< 0 || isl_stream_yaml_read_end_sequence(s
))
405 list
= isl_val_list_free(list
);
410 /* Set the (initial) coincident properties of "band" according to
411 * the (initial) elements of "coincident".
413 static __isl_give isl_schedule_band
*set_coincident(
414 __isl_take isl_schedule_band
*band
, __isl_take isl_val_list
*coincident
)
419 n
= isl_schedule_band_n_member(band
);
420 m
= isl_val_list_n_val(coincident
);
422 for (i
= 0; i
< n
&& i
< m
; ++i
) {
425 v
= isl_val_list_get_val(coincident
, i
);
427 band
= isl_schedule_band_free(band
);
428 band
= isl_schedule_band_member_set_coincident(band
, i
,
429 !isl_val_is_zero(v
));
432 isl_val_list_free(coincident
);
436 /* Read a subtree with band root node from "s".
438 static __isl_give isl_schedule_tree
*read_band(isl_stream
*s
)
440 isl_multi_union_pw_aff
*schedule
= NULL
;
441 isl_schedule_tree
*tree
= NULL
;
442 isl_val_list
*coincident
= NULL
;
443 isl_union_set
*options
= NULL
;
445 isl_schedule_band
*band
;
449 ctx
= isl_stream_get_ctx(s
);
452 struct isl_token
*tok
;
453 enum isl_schedule_key key
;
458 if (isl_stream_yaml_next(s
) < 0)
462 case isl_schedule_key_schedule
:
463 isl_multi_union_pw_aff_free(schedule
);
464 tok
= isl_stream_next_token(s
);
466 isl_stream_error(s
, NULL
, "unexpected EOF");
469 str
= isl_token_get_str(ctx
, tok
);
470 schedule
= isl_multi_union_pw_aff_read_from_str(ctx
,
477 case isl_schedule_key_coincident
:
478 coincident
= read_coincident(s
);
482 case isl_schedule_key_permutable
:
483 v
= isl_stream_read_val(s
);
484 permutable
= !isl_val_is_zero(v
);
487 case isl_schedule_key_options
:
488 isl_union_set_free(options
);
489 tok
= isl_stream_next_token(s
);
490 str
= isl_token_get_str(ctx
, tok
);
491 options
= isl_union_set_read_from_str(ctx
, str
);
497 case isl_schedule_key_child
:
498 isl_schedule_tree_free(tree
);
499 tree
= isl_stream_read_schedule_tree(s
);
504 isl_die(ctx
, isl_error_invalid
, "unexpected key",
507 } while ((more
= isl_stream_yaml_next(s
)) > 0);
513 isl_die(ctx
, isl_error_invalid
, "missing schedule", goto error
);
515 band
= isl_schedule_band_from_multi_union_pw_aff(schedule
);
516 band
= isl_schedule_band_set_permutable(band
, permutable
);
518 band
= set_coincident(band
, coincident
);
520 band
= isl_schedule_band_set_ast_build_options(band
, options
);
522 tree
= isl_schedule_tree_insert_band(tree
, band
);
524 tree
= isl_schedule_tree_from_band(band
);
528 isl_val_list_free(coincident
);
529 isl_union_set_free(options
);
530 isl_schedule_tree_free(tree
);
531 isl_multi_union_pw_aff_free(schedule
);
535 /* Read a subtree with root node of type "type" from "s".
536 * The node is represented by a sequence of children.
538 static __isl_give isl_schedule_tree
*read_children(isl_stream
*s
,
539 enum isl_schedule_node_type type
)
542 isl_schedule_tree_list
*list
;
545 ctx
= isl_stream_get_ctx(s
);
547 isl_token_free(isl_stream_next_token(s
));
549 if (isl_stream_yaml_next(s
) < 0)
552 if (isl_stream_yaml_read_start_sequence(s
))
555 list
= isl_schedule_tree_list_alloc(ctx
, 0);
556 while ((more
= isl_stream_yaml_next(s
)) > 0) {
557 isl_schedule_tree
*tree
;
559 tree
= isl_stream_read_schedule_tree(s
);
560 list
= isl_schedule_tree_list_add(list
, tree
);
563 if (more
< 0 || isl_stream_yaml_read_end_sequence(s
))
564 list
= isl_schedule_tree_list_free(list
);
566 return isl_schedule_tree_from_children(type
, list
);
569 /* Read a subtree with sequence root node from "s".
571 static __isl_give isl_schedule_tree
*read_sequence(isl_stream
*s
)
573 return read_children(s
, isl_schedule_node_sequence
);
576 /* Read a subtree with set root node from "s".
578 static __isl_give isl_schedule_tree
*read_set(isl_stream
*s
)
580 return read_children(s
, isl_schedule_node_set
);
583 /* Read a schedule (sub)tree from "s".
585 * We first determine the type of the root node based on the first
586 * mapping key and then hand over to a function tailored to reading
587 * nodes of this type.
589 static __isl_give isl_schedule_tree
*isl_stream_read_schedule_tree(
590 struct isl_stream
*s
)
592 enum isl_schedule_key key
;
593 struct isl_token
*tok
;
594 isl_schedule_tree
*tree
= NULL
;
597 if (isl_stream_yaml_read_start_mapping(s
))
599 more
= isl_stream_yaml_next(s
);
603 isl_stream_error(s
, NULL
, "missing key");
607 tok
= isl_stream_next_token(s
);
608 key
= extract_key(s
, tok
);
609 isl_stream_push_token(s
, tok
);
613 case isl_schedule_key_context
:
614 tree
= read_context(s
);
616 case isl_schedule_key_domain
:
617 tree
= read_domain(s
);
619 case isl_schedule_key_contraction
:
620 case isl_schedule_key_expansion
:
621 tree
= read_expansion(s
);
623 case isl_schedule_key_filter
:
624 tree
= read_filter(s
);
626 case isl_schedule_key_leaf
:
627 isl_token_free(isl_stream_next_token(s
));
628 tree
= isl_schedule_tree_leaf(isl_stream_get_ctx(s
));
630 case isl_schedule_key_mark
:
633 case isl_schedule_key_sequence
:
634 tree
= read_sequence(s
);
636 case isl_schedule_key_set
:
639 case isl_schedule_key_schedule
:
640 case isl_schedule_key_coincident
:
641 case isl_schedule_key_options
:
642 case isl_schedule_key_permutable
:
645 case isl_schedule_key_child
:
646 isl_die(isl_stream_get_ctx(s
), isl_error_unsupported
,
647 "cannot identity node type", return NULL
);
648 case isl_schedule_key_error
:
652 if (isl_stream_yaml_read_end_mapping(s
) < 0) {
653 isl_stream_error(s
, NULL
, "unexpected extra elements");
654 return isl_schedule_tree_free(tree
);
660 /* Read an isl_schedule from "s".
662 __isl_give isl_schedule
*isl_stream_read_schedule(isl_stream
*s
)
665 isl_schedule_tree
*tree
;
670 ctx
= isl_stream_get_ctx(s
);
671 tree
= isl_stream_read_schedule_tree(s
);
672 return isl_schedule_from_schedule_tree(ctx
, tree
);
675 /* Read an isl_schedule from "input".
677 __isl_give isl_schedule
*isl_schedule_read_from_file(isl_ctx
*ctx
, FILE *input
)
679 struct isl_stream
*s
;
680 isl_schedule
*schedule
;
682 s
= isl_stream_new_file(ctx
, input
);
685 schedule
= isl_stream_read_schedule(s
);
691 /* Read an isl_schedule from "str".
693 __isl_give isl_schedule
*isl_schedule_read_from_str(isl_ctx
*ctx
,
696 struct isl_stream
*s
;
697 isl_schedule
*schedule
;
699 s
= isl_stream_new_str(ctx
, str
);
702 schedule
= isl_stream_read_schedule(s
);