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_domain
,
17 isl_schedule_key_filter
,
18 isl_schedule_key_leaf
,
19 isl_schedule_key_options
,
20 isl_schedule_key_permutable
,
21 isl_schedule_key_schedule
,
22 isl_schedule_key_sequence
,
26 /* Extract a mapping key from the token "tok".
27 * Return isl_schedule_key_error on error, i.e., if "tok" does not
28 * correspond to any known key.
30 static enum isl_schedule_key
extract_key(__isl_keep isl_stream
*s
,
31 struct isl_token
*tok
)
35 enum isl_schedule_key key
;
38 ctx
= isl_stream_get_ctx(s
);
39 type
= isl_token_get_type(tok
);
40 if (type
!= ISL_TOKEN_IDENT
&& type
!= ISL_TOKEN_STRING
) {
41 isl_stream_error(s
, tok
, "expecting key");
42 return isl_schedule_key_error
;
44 name
= isl_token_get_str(ctx
, tok
);
45 if (!strcmp(name
, "child"))
46 key
= isl_schedule_key_child
;
47 else if (!strcmp(name
, "coincident"))
48 key
= isl_schedule_key_coincident
;
49 else if (!strcmp(name
, "context"))
50 key
= isl_schedule_key_context
;
51 else if (!strcmp(name
, "domain"))
52 key
= isl_schedule_key_domain
;
53 else if (!strcmp(name
, "filter"))
54 key
= isl_schedule_key_filter
;
55 else if (!strcmp(name
, "leaf"))
56 key
= isl_schedule_key_leaf
;
57 else if (!strcmp(name
, "options"))
58 key
= isl_schedule_key_options
;
59 else if (!strcmp(name
, "schedule"))
60 key
= isl_schedule_key_schedule
;
61 else if (!strcmp(name
, "sequence"))
62 key
= isl_schedule_key_sequence
;
63 else if (!strcmp(name
, "set"))
64 key
= isl_schedule_key_set
;
65 else if (!strcmp(name
, "permutable"))
66 key
= isl_schedule_key_permutable
;
68 isl_die(ctx
, isl_error_invalid
, "unknown key",
69 key
= isl_schedule_key_error
);
74 /* Read a key from "s" and return the corresponding enum.
75 * Return isl_schedule_key_error on error, i.e., if the first token
76 * on the stream does not correspond to any known key.
78 static enum isl_schedule_key
get_key(__isl_keep isl_stream
*s
)
80 struct isl_token
*tok
;
81 enum isl_schedule_key key
;
83 tok
= isl_stream_next_token(s
);
84 key
= extract_key(s
, tok
);
90 static __isl_give isl_schedule_tree
*isl_stream_read_schedule_tree(
91 __isl_keep isl_stream
*s
);
93 /* Read a subtree with context root node from "s".
95 static __isl_give isl_schedule_tree
*read_context(__isl_keep isl_stream
*s
)
97 isl_set
*context
= NULL
;
98 isl_schedule_tree
*tree
;
100 struct isl_token
*tok
;
101 enum isl_schedule_key key
;
105 ctx
= isl_stream_get_ctx(s
);
109 if (isl_stream_yaml_next(s
) < 0)
112 tok
= isl_stream_next_token(s
);
114 isl_stream_error(s
, NULL
, "unexpected EOF");
117 str
= isl_token_get_str(ctx
, tok
);
118 context
= isl_set_read_from_str(ctx
, str
);
122 more
= isl_stream_yaml_next(s
);
126 tree
= isl_schedule_tree_from_context(context
);
129 if (key
!= isl_schedule_key_child
)
130 isl_die(ctx
, isl_error_invalid
, "expecting child",
132 if (isl_stream_yaml_next(s
) < 0)
134 tree
= isl_stream_read_schedule_tree(s
);
135 tree
= isl_schedule_tree_insert_context(tree
, context
);
140 isl_set_free(context
);
144 /* Read a subtree with domain root node from "s".
146 static __isl_give isl_schedule_tree
*read_domain(__isl_keep isl_stream
*s
)
148 isl_union_set
*domain
= NULL
;
149 isl_schedule_tree
*tree
;
151 struct isl_token
*tok
;
152 enum isl_schedule_key key
;
156 ctx
= isl_stream_get_ctx(s
);
160 if (isl_stream_yaml_next(s
) < 0)
163 tok
= isl_stream_next_token(s
);
165 isl_stream_error(s
, NULL
, "unexpected EOF");
168 str
= isl_token_get_str(ctx
, tok
);
169 domain
= isl_union_set_read_from_str(ctx
, str
);
173 more
= isl_stream_yaml_next(s
);
177 tree
= isl_schedule_tree_from_domain(domain
);
180 if (key
!= isl_schedule_key_child
)
181 isl_die(ctx
, isl_error_invalid
, "expecting child",
183 if (isl_stream_yaml_next(s
) < 0)
185 tree
= isl_stream_read_schedule_tree(s
);
186 tree
= isl_schedule_tree_insert_domain(tree
, domain
);
191 isl_union_set_free(domain
);
195 /* Read a subtree with filter root node from "s".
197 static __isl_give isl_schedule_tree
*read_filter(__isl_keep isl_stream
*s
)
199 isl_union_set
*filter
= NULL
;
200 isl_schedule_tree
*tree
;
202 struct isl_token
*tok
;
203 enum isl_schedule_key key
;
207 ctx
= isl_stream_get_ctx(s
);
211 if (isl_stream_yaml_next(s
) < 0)
214 tok
= isl_stream_next_token(s
);
216 isl_stream_error(s
, NULL
, "unexpected EOF");
219 str
= isl_token_get_str(ctx
, tok
);
220 filter
= isl_union_set_read_from_str(ctx
, str
);
224 more
= isl_stream_yaml_next(s
);
228 tree
= isl_schedule_tree_from_filter(filter
);
231 if (key
!= isl_schedule_key_child
)
232 isl_die(ctx
, isl_error_invalid
, "expecting child",
234 if (isl_stream_yaml_next(s
) < 0)
236 tree
= isl_stream_read_schedule_tree(s
);
237 tree
= isl_schedule_tree_insert_filter(tree
, filter
);
242 isl_union_set_free(filter
);
246 /* Read a sequence of integers from "s" (representing the coincident
247 * property of a band node).
249 static __isl_give isl_val_list
*read_coincident(__isl_keep isl_stream
*s
)
255 ctx
= isl_stream_get_ctx(s
);
257 if (isl_stream_yaml_read_start_sequence(s
) < 0)
260 list
= isl_val_list_alloc(ctx
, 0);
261 while ((more
= isl_stream_yaml_next(s
)) > 0) {
264 val
= isl_stream_read_val(s
);
265 list
= isl_val_list_add(list
, val
);
268 if (more
< 0 || isl_stream_yaml_read_end_sequence(s
))
269 list
= isl_val_list_free(list
);
274 /* Set the (initial) coincident properties of "band" according to
275 * the (initial) elements of "coincident".
277 static __isl_give isl_schedule_band
*set_coincident(
278 __isl_take isl_schedule_band
*band
, __isl_take isl_val_list
*coincident
)
283 n
= isl_schedule_band_n_member(band
);
284 m
= isl_val_list_n_val(coincident
);
286 for (i
= 0; i
< n
&& i
< m
; ++i
) {
289 v
= isl_val_list_get_val(coincident
, i
);
291 band
= isl_schedule_band_free(band
);
292 band
= isl_schedule_band_member_set_coincident(band
, i
,
293 !isl_val_is_zero(v
));
296 isl_val_list_free(coincident
);
300 /* Read a subtree with band root node from "s".
302 static __isl_give isl_schedule_tree
*read_band(isl_stream
*s
)
304 isl_multi_union_pw_aff
*schedule
= NULL
;
305 isl_schedule_tree
*tree
= NULL
;
306 isl_val_list
*coincident
= NULL
;
307 isl_union_set
*options
= NULL
;
309 isl_schedule_band
*band
;
313 ctx
= isl_stream_get_ctx(s
);
316 struct isl_token
*tok
;
317 enum isl_schedule_key key
;
322 if (isl_stream_yaml_next(s
) < 0)
326 case isl_schedule_key_schedule
:
327 isl_multi_union_pw_aff_free(schedule
);
328 tok
= isl_stream_next_token(s
);
330 isl_stream_error(s
, NULL
, "unexpected EOF");
333 str
= isl_token_get_str(ctx
, tok
);
334 schedule
= isl_multi_union_pw_aff_read_from_str(ctx
,
341 case isl_schedule_key_coincident
:
342 coincident
= read_coincident(s
);
346 case isl_schedule_key_permutable
:
347 v
= isl_stream_read_val(s
);
348 permutable
= !isl_val_is_zero(v
);
351 case isl_schedule_key_options
:
352 isl_union_set_free(options
);
353 tok
= isl_stream_next_token(s
);
354 str
= isl_token_get_str(ctx
, tok
);
355 options
= isl_union_set_read_from_str(ctx
, str
);
361 case isl_schedule_key_child
:
362 isl_schedule_tree_free(tree
);
363 tree
= isl_stream_read_schedule_tree(s
);
368 isl_die(ctx
, isl_error_invalid
, "unexpected key",
371 } while ((more
= isl_stream_yaml_next(s
)) > 0);
377 isl_die(ctx
, isl_error_invalid
, "missing schedule", goto error
);
379 band
= isl_schedule_band_from_multi_union_pw_aff(schedule
);
380 band
= isl_schedule_band_set_permutable(band
, permutable
);
382 band
= set_coincident(band
, coincident
);
384 band
= isl_schedule_band_set_ast_build_options(band
, options
);
386 tree
= isl_schedule_tree_insert_band(tree
, band
);
388 tree
= isl_schedule_tree_from_band(band
);
392 isl_val_list_free(coincident
);
393 isl_union_set_free(options
);
394 isl_schedule_tree_free(tree
);
395 isl_multi_union_pw_aff_free(schedule
);
399 /* Read a subtree with root node of type "type" from "s".
400 * The node is represented by a sequence of children.
402 static __isl_give isl_schedule_tree
*read_children(isl_stream
*s
,
403 enum isl_schedule_node_type type
)
406 isl_schedule_tree_list
*list
;
409 ctx
= isl_stream_get_ctx(s
);
411 isl_token_free(isl_stream_next_token(s
));
413 if (isl_stream_yaml_next(s
) < 0)
416 if (isl_stream_yaml_read_start_sequence(s
))
419 list
= isl_schedule_tree_list_alloc(ctx
, 0);
420 while ((more
= isl_stream_yaml_next(s
)) > 0) {
421 isl_schedule_tree
*tree
;
423 tree
= isl_stream_read_schedule_tree(s
);
424 list
= isl_schedule_tree_list_add(list
, tree
);
427 if (more
< 0 || isl_stream_yaml_read_end_sequence(s
))
428 list
= isl_schedule_tree_list_free(list
);
430 return isl_schedule_tree_from_children(type
, list
);
433 /* Read a subtree with sequence root node from "s".
435 static __isl_give isl_schedule_tree
*read_sequence(isl_stream
*s
)
437 return read_children(s
, isl_schedule_node_sequence
);
440 /* Read a subtree with set root node from "s".
442 static __isl_give isl_schedule_tree
*read_set(isl_stream
*s
)
444 return read_children(s
, isl_schedule_node_set
);
447 /* Read a schedule (sub)tree from "s".
449 * We first determine the type of the root node based on the first
450 * mapping key and then hand over to a function tailored to reading
451 * nodes of this type.
453 static __isl_give isl_schedule_tree
*isl_stream_read_schedule_tree(
454 struct isl_stream
*s
)
456 enum isl_schedule_key key
;
457 struct isl_token
*tok
;
458 isl_schedule_tree
*tree
= NULL
;
461 if (isl_stream_yaml_read_start_mapping(s
))
463 more
= isl_stream_yaml_next(s
);
467 isl_stream_error(s
, NULL
, "missing key");
471 tok
= isl_stream_next_token(s
);
472 key
= extract_key(s
, tok
);
473 isl_stream_push_token(s
, tok
);
477 case isl_schedule_key_context
:
478 tree
= read_context(s
);
480 case isl_schedule_key_domain
:
481 tree
= read_domain(s
);
483 case isl_schedule_key_filter
:
484 tree
= read_filter(s
);
486 case isl_schedule_key_leaf
:
487 isl_token_free(isl_stream_next_token(s
));
488 tree
= isl_schedule_tree_leaf(isl_stream_get_ctx(s
));
490 case isl_schedule_key_sequence
:
491 tree
= read_sequence(s
);
493 case isl_schedule_key_set
:
496 case isl_schedule_key_schedule
:
497 case isl_schedule_key_coincident
:
498 case isl_schedule_key_options
:
499 case isl_schedule_key_permutable
:
502 case isl_schedule_key_child
:
503 isl_die(isl_stream_get_ctx(s
), isl_error_unsupported
,
504 "cannot identity node type", return NULL
);
505 case isl_schedule_key_error
:
509 if (isl_stream_yaml_read_end_mapping(s
) < 0) {
510 isl_stream_error(s
, NULL
, "unexpected extra elements");
511 return isl_schedule_tree_free(tree
);
517 /* Read an isl_schedule from "s".
519 __isl_give isl_schedule
*isl_stream_read_schedule(isl_stream
*s
)
522 isl_schedule_tree
*tree
;
527 ctx
= isl_stream_get_ctx(s
);
528 tree
= isl_stream_read_schedule_tree(s
);
529 return isl_schedule_from_schedule_tree(ctx
, tree
);
532 /* Read an isl_schedule from "input".
534 __isl_give isl_schedule
*isl_schedule_read_from_file(isl_ctx
*ctx
, FILE *input
)
536 struct isl_stream
*s
;
537 isl_schedule
*schedule
;
539 s
= isl_stream_new_file(ctx
, input
);
542 schedule
= isl_stream_read_schedule(s
);
548 /* Read an isl_schedule from "str".
550 __isl_give isl_schedule
*isl_schedule_read_from_str(isl_ctx
*ctx
,
553 struct isl_stream
*s
;
554 isl_schedule
*schedule
;
556 s
= isl_stream_new_str(ctx
, str
);
559 schedule
= isl_stream_read_schedule(s
);