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_options
,
22 isl_schedule_key_permutable
,
23 isl_schedule_key_schedule
,
24 isl_schedule_key_sequence
,
28 /* Extract a mapping key from the token "tok".
29 * Return isl_schedule_key_error on error, i.e., if "tok" does not
30 * correspond to any known key.
32 static enum isl_schedule_key
extract_key(__isl_keep isl_stream
*s
,
33 struct isl_token
*tok
)
37 enum isl_schedule_key key
;
40 ctx
= isl_stream_get_ctx(s
);
41 type
= isl_token_get_type(tok
);
42 if (type
!= ISL_TOKEN_IDENT
&& type
!= ISL_TOKEN_STRING
) {
43 isl_stream_error(s
, tok
, "expecting key");
44 return isl_schedule_key_error
;
46 name
= isl_token_get_str(ctx
, tok
);
47 if (!strcmp(name
, "child"))
48 key
= isl_schedule_key_child
;
49 else if (!strcmp(name
, "coincident"))
50 key
= isl_schedule_key_coincident
;
51 else if (!strcmp(name
, "context"))
52 key
= isl_schedule_key_context
;
53 else if (!strcmp(name
, "contraction"))
54 key
= isl_schedule_key_contraction
;
55 else if (!strcmp(name
, "domain"))
56 key
= isl_schedule_key_domain
;
57 else if (!strcmp(name
, "expansion"))
58 key
= isl_schedule_key_expansion
;
59 else if (!strcmp(name
, "filter"))
60 key
= isl_schedule_key_filter
;
61 else if (!strcmp(name
, "leaf"))
62 key
= isl_schedule_key_leaf
;
63 else if (!strcmp(name
, "options"))
64 key
= isl_schedule_key_options
;
65 else if (!strcmp(name
, "schedule"))
66 key
= isl_schedule_key_schedule
;
67 else if (!strcmp(name
, "sequence"))
68 key
= isl_schedule_key_sequence
;
69 else if (!strcmp(name
, "set"))
70 key
= isl_schedule_key_set
;
71 else if (!strcmp(name
, "permutable"))
72 key
= isl_schedule_key_permutable
;
74 isl_die(ctx
, isl_error_invalid
, "unknown key",
75 key
= isl_schedule_key_error
);
80 /* Read a key from "s" and return the corresponding enum.
81 * Return isl_schedule_key_error on error, i.e., if the first token
82 * on the stream does not correspond to any known key.
84 static enum isl_schedule_key
get_key(__isl_keep isl_stream
*s
)
86 struct isl_token
*tok
;
87 enum isl_schedule_key key
;
89 tok
= isl_stream_next_token(s
);
90 key
= extract_key(s
, tok
);
96 static __isl_give isl_schedule_tree
*isl_stream_read_schedule_tree(
97 __isl_keep isl_stream
*s
);
99 /* Read a subtree with context root node from "s".
101 static __isl_give isl_schedule_tree
*read_context(__isl_keep isl_stream
*s
)
103 isl_set
*context
= NULL
;
104 isl_schedule_tree
*tree
;
106 struct isl_token
*tok
;
107 enum isl_schedule_key key
;
111 ctx
= isl_stream_get_ctx(s
);
115 if (isl_stream_yaml_next(s
) < 0)
118 tok
= isl_stream_next_token(s
);
120 isl_stream_error(s
, NULL
, "unexpected EOF");
123 str
= isl_token_get_str(ctx
, tok
);
124 context
= isl_set_read_from_str(ctx
, str
);
128 more
= isl_stream_yaml_next(s
);
132 tree
= isl_schedule_tree_from_context(context
);
135 if (key
!= isl_schedule_key_child
)
136 isl_die(ctx
, isl_error_invalid
, "expecting child",
138 if (isl_stream_yaml_next(s
) < 0)
140 tree
= isl_stream_read_schedule_tree(s
);
141 tree
= isl_schedule_tree_insert_context(tree
, context
);
146 isl_set_free(context
);
150 /* Read a subtree with domain root node from "s".
152 static __isl_give isl_schedule_tree
*read_domain(__isl_keep isl_stream
*s
)
154 isl_union_set
*domain
= NULL
;
155 isl_schedule_tree
*tree
;
157 struct isl_token
*tok
;
158 enum isl_schedule_key key
;
162 ctx
= isl_stream_get_ctx(s
);
166 if (isl_stream_yaml_next(s
) < 0)
169 tok
= isl_stream_next_token(s
);
171 isl_stream_error(s
, NULL
, "unexpected EOF");
174 str
= isl_token_get_str(ctx
, tok
);
175 domain
= isl_union_set_read_from_str(ctx
, str
);
179 more
= isl_stream_yaml_next(s
);
183 tree
= isl_schedule_tree_from_domain(domain
);
186 if (key
!= isl_schedule_key_child
)
187 isl_die(ctx
, isl_error_invalid
, "expecting child",
189 if (isl_stream_yaml_next(s
) < 0)
191 tree
= isl_stream_read_schedule_tree(s
);
192 tree
= isl_schedule_tree_insert_domain(tree
, domain
);
197 isl_union_set_free(domain
);
201 /* Read a subtree with expansion root node from "s".
203 static __isl_give isl_schedule_tree
*read_expansion(isl_stream
*s
)
206 isl_union_pw_multi_aff
*contraction
= NULL
;
207 isl_union_map
*expansion
= NULL
;
208 isl_schedule_tree
*tree
= NULL
;
211 ctx
= isl_stream_get_ctx(s
);
214 struct isl_token
*tok
;
215 enum isl_schedule_key key
;
219 if (isl_stream_yaml_next(s
) < 0)
223 case isl_schedule_key_contraction
:
224 isl_union_pw_multi_aff_free(contraction
);
225 tok
= isl_stream_next_token(s
);
226 str
= isl_token_get_str(ctx
, tok
);
227 contraction
= isl_union_pw_multi_aff_read_from_str(ctx
,
234 case isl_schedule_key_expansion
:
235 isl_union_map_free(expansion
);
236 tok
= isl_stream_next_token(s
);
237 str
= isl_token_get_str(ctx
, tok
);
238 expansion
= isl_union_map_read_from_str(ctx
, str
);
244 case isl_schedule_key_child
:
245 isl_schedule_tree_free(tree
);
246 tree
= isl_stream_read_schedule_tree(s
);
251 isl_die(ctx
, isl_error_invalid
, "unexpected key",
254 } while ((more
= isl_stream_yaml_next(s
)) > 0);
260 isl_die(ctx
, isl_error_invalid
, "missing contraction",
263 isl_die(ctx
, isl_error_invalid
, "missing expansion",
267 return isl_schedule_tree_from_expansion(contraction
, expansion
);
268 return isl_schedule_tree_insert_expansion(tree
, contraction
, expansion
);
270 isl_schedule_tree_free(tree
);
271 isl_union_pw_multi_aff_free(contraction
);
272 isl_union_map_free(expansion
);
276 /* Read a subtree with filter root node from "s".
278 static __isl_give isl_schedule_tree
*read_filter(__isl_keep isl_stream
*s
)
280 isl_union_set
*filter
= NULL
;
281 isl_schedule_tree
*tree
;
283 struct isl_token
*tok
;
284 enum isl_schedule_key key
;
288 ctx
= isl_stream_get_ctx(s
);
292 if (isl_stream_yaml_next(s
) < 0)
295 tok
= isl_stream_next_token(s
);
297 isl_stream_error(s
, NULL
, "unexpected EOF");
300 str
= isl_token_get_str(ctx
, tok
);
301 filter
= isl_union_set_read_from_str(ctx
, str
);
305 more
= isl_stream_yaml_next(s
);
309 tree
= isl_schedule_tree_from_filter(filter
);
312 if (key
!= isl_schedule_key_child
)
313 isl_die(ctx
, isl_error_invalid
, "expecting child",
315 if (isl_stream_yaml_next(s
) < 0)
317 tree
= isl_stream_read_schedule_tree(s
);
318 tree
= isl_schedule_tree_insert_filter(tree
, filter
);
323 isl_union_set_free(filter
);
327 /* Read a sequence of integers from "s" (representing the coincident
328 * property of a band node).
330 static __isl_give isl_val_list
*read_coincident(__isl_keep isl_stream
*s
)
336 ctx
= isl_stream_get_ctx(s
);
338 if (isl_stream_yaml_read_start_sequence(s
) < 0)
341 list
= isl_val_list_alloc(ctx
, 0);
342 while ((more
= isl_stream_yaml_next(s
)) > 0) {
345 val
= isl_stream_read_val(s
);
346 list
= isl_val_list_add(list
, val
);
349 if (more
< 0 || isl_stream_yaml_read_end_sequence(s
))
350 list
= isl_val_list_free(list
);
355 /* Set the (initial) coincident properties of "band" according to
356 * the (initial) elements of "coincident".
358 static __isl_give isl_schedule_band
*set_coincident(
359 __isl_take isl_schedule_band
*band
, __isl_take isl_val_list
*coincident
)
364 n
= isl_schedule_band_n_member(band
);
365 m
= isl_val_list_n_val(coincident
);
367 for (i
= 0; i
< n
&& i
< m
; ++i
) {
370 v
= isl_val_list_get_val(coincident
, i
);
372 band
= isl_schedule_band_free(band
);
373 band
= isl_schedule_band_member_set_coincident(band
, i
,
374 !isl_val_is_zero(v
));
377 isl_val_list_free(coincident
);
381 /* Read a subtree with band root node from "s".
383 static __isl_give isl_schedule_tree
*read_band(isl_stream
*s
)
385 isl_multi_union_pw_aff
*schedule
= NULL
;
386 isl_schedule_tree
*tree
= NULL
;
387 isl_val_list
*coincident
= NULL
;
388 isl_union_set
*options
= NULL
;
390 isl_schedule_band
*band
;
394 ctx
= isl_stream_get_ctx(s
);
397 struct isl_token
*tok
;
398 enum isl_schedule_key key
;
403 if (isl_stream_yaml_next(s
) < 0)
407 case isl_schedule_key_schedule
:
408 isl_multi_union_pw_aff_free(schedule
);
409 tok
= isl_stream_next_token(s
);
411 isl_stream_error(s
, NULL
, "unexpected EOF");
414 str
= isl_token_get_str(ctx
, tok
);
415 schedule
= isl_multi_union_pw_aff_read_from_str(ctx
,
422 case isl_schedule_key_coincident
:
423 coincident
= read_coincident(s
);
427 case isl_schedule_key_permutable
:
428 v
= isl_stream_read_val(s
);
429 permutable
= !isl_val_is_zero(v
);
432 case isl_schedule_key_options
:
433 isl_union_set_free(options
);
434 tok
= isl_stream_next_token(s
);
435 str
= isl_token_get_str(ctx
, tok
);
436 options
= isl_union_set_read_from_str(ctx
, str
);
442 case isl_schedule_key_child
:
443 isl_schedule_tree_free(tree
);
444 tree
= isl_stream_read_schedule_tree(s
);
449 isl_die(ctx
, isl_error_invalid
, "unexpected key",
452 } while ((more
= isl_stream_yaml_next(s
)) > 0);
458 isl_die(ctx
, isl_error_invalid
, "missing schedule", goto error
);
460 band
= isl_schedule_band_from_multi_union_pw_aff(schedule
);
461 band
= isl_schedule_band_set_permutable(band
, permutable
);
463 band
= set_coincident(band
, coincident
);
465 band
= isl_schedule_band_set_ast_build_options(band
, options
);
467 tree
= isl_schedule_tree_insert_band(tree
, band
);
469 tree
= isl_schedule_tree_from_band(band
);
473 isl_val_list_free(coincident
);
474 isl_union_set_free(options
);
475 isl_schedule_tree_free(tree
);
476 isl_multi_union_pw_aff_free(schedule
);
480 /* Read a subtree with root node of type "type" from "s".
481 * The node is represented by a sequence of children.
483 static __isl_give isl_schedule_tree
*read_children(isl_stream
*s
,
484 enum isl_schedule_node_type type
)
487 isl_schedule_tree_list
*list
;
490 ctx
= isl_stream_get_ctx(s
);
492 isl_token_free(isl_stream_next_token(s
));
494 if (isl_stream_yaml_next(s
) < 0)
497 if (isl_stream_yaml_read_start_sequence(s
))
500 list
= isl_schedule_tree_list_alloc(ctx
, 0);
501 while ((more
= isl_stream_yaml_next(s
)) > 0) {
502 isl_schedule_tree
*tree
;
504 tree
= isl_stream_read_schedule_tree(s
);
505 list
= isl_schedule_tree_list_add(list
, tree
);
508 if (more
< 0 || isl_stream_yaml_read_end_sequence(s
))
509 list
= isl_schedule_tree_list_free(list
);
511 return isl_schedule_tree_from_children(type
, list
);
514 /* Read a subtree with sequence root node from "s".
516 static __isl_give isl_schedule_tree
*read_sequence(isl_stream
*s
)
518 return read_children(s
, isl_schedule_node_sequence
);
521 /* Read a subtree with set root node from "s".
523 static __isl_give isl_schedule_tree
*read_set(isl_stream
*s
)
525 return read_children(s
, isl_schedule_node_set
);
528 /* Read a schedule (sub)tree from "s".
530 * We first determine the type of the root node based on the first
531 * mapping key and then hand over to a function tailored to reading
532 * nodes of this type.
534 static __isl_give isl_schedule_tree
*isl_stream_read_schedule_tree(
535 struct isl_stream
*s
)
537 enum isl_schedule_key key
;
538 struct isl_token
*tok
;
539 isl_schedule_tree
*tree
= NULL
;
542 if (isl_stream_yaml_read_start_mapping(s
))
544 more
= isl_stream_yaml_next(s
);
548 isl_stream_error(s
, NULL
, "missing key");
552 tok
= isl_stream_next_token(s
);
553 key
= extract_key(s
, tok
);
554 isl_stream_push_token(s
, tok
);
558 case isl_schedule_key_context
:
559 tree
= read_context(s
);
561 case isl_schedule_key_domain
:
562 tree
= read_domain(s
);
564 case isl_schedule_key_contraction
:
565 case isl_schedule_key_expansion
:
566 tree
= read_expansion(s
);
568 case isl_schedule_key_filter
:
569 tree
= read_filter(s
);
571 case isl_schedule_key_leaf
:
572 isl_token_free(isl_stream_next_token(s
));
573 tree
= isl_schedule_tree_leaf(isl_stream_get_ctx(s
));
575 case isl_schedule_key_sequence
:
576 tree
= read_sequence(s
);
578 case isl_schedule_key_set
:
581 case isl_schedule_key_schedule
:
582 case isl_schedule_key_coincident
:
583 case isl_schedule_key_options
:
584 case isl_schedule_key_permutable
:
587 case isl_schedule_key_child
:
588 isl_die(isl_stream_get_ctx(s
), isl_error_unsupported
,
589 "cannot identity node type", return NULL
);
590 case isl_schedule_key_error
:
594 if (isl_stream_yaml_read_end_mapping(s
) < 0) {
595 isl_stream_error(s
, NULL
, "unexpected extra elements");
596 return isl_schedule_tree_free(tree
);
602 /* Read an isl_schedule from "s".
604 __isl_give isl_schedule
*isl_stream_read_schedule(isl_stream
*s
)
607 isl_schedule_tree
*tree
;
612 ctx
= isl_stream_get_ctx(s
);
613 tree
= isl_stream_read_schedule_tree(s
);
614 return isl_schedule_from_schedule_tree(ctx
, tree
);
617 /* Read an isl_schedule from "input".
619 __isl_give isl_schedule
*isl_schedule_read_from_file(isl_ctx
*ctx
, FILE *input
)
621 struct isl_stream
*s
;
622 isl_schedule
*schedule
;
624 s
= isl_stream_new_file(ctx
, input
);
627 schedule
= isl_stream_read_schedule(s
);
633 /* Read an isl_schedule from "str".
635 __isl_give isl_schedule
*isl_schedule_read_from_str(isl_ctx
*ctx
,
638 struct isl_stream
*s
;
639 isl_schedule
*schedule
;
641 s
= isl_stream_new_str(ctx
, str
);
644 schedule
= isl_stream_read_schedule(s
);