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_domain
,
16 isl_schedule_key_filter
,
17 isl_schedule_key_leaf
,
18 isl_schedule_key_options
,
19 isl_schedule_key_permutable
,
20 isl_schedule_key_schedule
,
21 isl_schedule_key_sequence
,
25 /* Extract a mapping key from the token "tok".
26 * Return isl_schedule_key_error on error, i.e., if "tok" does not
27 * correspond to any known key.
29 static enum isl_schedule_key
extract_key(__isl_keep isl_stream
*s
,
30 struct isl_token
*tok
)
34 enum isl_schedule_key key
;
37 ctx
= isl_stream_get_ctx(s
);
38 type
= isl_token_get_type(tok
);
39 if (type
!= ISL_TOKEN_IDENT
&& type
!= ISL_TOKEN_STRING
) {
40 isl_stream_error(s
, tok
, "expecting key");
41 return isl_schedule_key_error
;
43 name
= isl_token_get_str(ctx
, tok
);
44 if (!strcmp(name
, "child"))
45 key
= isl_schedule_key_child
;
46 else if (!strcmp(name
, "coincident"))
47 key
= isl_schedule_key_coincident
;
48 else if (!strcmp(name
, "domain"))
49 key
= isl_schedule_key_domain
;
50 else if (!strcmp(name
, "filter"))
51 key
= isl_schedule_key_filter
;
52 else if (!strcmp(name
, "leaf"))
53 key
= isl_schedule_key_leaf
;
54 else if (!strcmp(name
, "options"))
55 key
= isl_schedule_key_options
;
56 else if (!strcmp(name
, "schedule"))
57 key
= isl_schedule_key_schedule
;
58 else if (!strcmp(name
, "sequence"))
59 key
= isl_schedule_key_sequence
;
60 else if (!strcmp(name
, "set"))
61 key
= isl_schedule_key_set
;
62 else if (!strcmp(name
, "permutable"))
63 key
= isl_schedule_key_permutable
;
65 isl_die(ctx
, isl_error_invalid
, "unknown key",
66 key
= isl_schedule_key_error
);
71 /* Read a key from "s" and return the corresponding enum.
72 * Return isl_schedule_key_error on error, i.e., if the first token
73 * on the stream does not correspond to any known key.
75 static enum isl_schedule_key
get_key(__isl_keep isl_stream
*s
)
77 struct isl_token
*tok
;
78 enum isl_schedule_key key
;
80 tok
= isl_stream_next_token(s
);
81 key
= extract_key(s
, tok
);
87 static __isl_give isl_schedule_tree
*isl_stream_read_schedule_tree(
88 __isl_keep isl_stream
*s
);
90 /* Read a subtree with domain root node from "s".
92 static __isl_give isl_schedule_tree
*read_domain(__isl_keep isl_stream
*s
)
94 isl_union_set
*domain
= NULL
;
95 isl_schedule_tree
*tree
;
97 struct isl_token
*tok
;
98 enum isl_schedule_key key
;
102 ctx
= isl_stream_get_ctx(s
);
106 if (isl_stream_yaml_next(s
) < 0)
109 tok
= isl_stream_next_token(s
);
111 isl_stream_error(s
, NULL
, "unexpected EOF");
114 str
= isl_token_get_str(ctx
, tok
);
115 domain
= isl_union_set_read_from_str(ctx
, str
);
119 more
= isl_stream_yaml_next(s
);
123 tree
= isl_schedule_tree_from_domain(domain
);
126 if (key
!= isl_schedule_key_child
)
127 isl_die(ctx
, isl_error_invalid
, "expecting child",
129 if (isl_stream_yaml_next(s
) < 0)
131 tree
= isl_stream_read_schedule_tree(s
);
132 tree
= isl_schedule_tree_insert_domain(tree
, domain
);
137 isl_union_set_free(domain
);
141 /* Read a subtree with filter root node from "s".
143 static __isl_give isl_schedule_tree
*read_filter(__isl_keep isl_stream
*s
)
145 isl_union_set
*filter
= NULL
;
146 isl_schedule_tree
*tree
;
148 struct isl_token
*tok
;
149 enum isl_schedule_key key
;
153 ctx
= isl_stream_get_ctx(s
);
157 if (isl_stream_yaml_next(s
) < 0)
160 tok
= isl_stream_next_token(s
);
162 isl_stream_error(s
, NULL
, "unexpected EOF");
165 str
= isl_token_get_str(ctx
, tok
);
166 filter
= isl_union_set_read_from_str(ctx
, str
);
170 more
= isl_stream_yaml_next(s
);
174 tree
= isl_schedule_tree_from_filter(filter
);
177 if (key
!= isl_schedule_key_child
)
178 isl_die(ctx
, isl_error_invalid
, "expecting child",
180 if (isl_stream_yaml_next(s
) < 0)
182 tree
= isl_stream_read_schedule_tree(s
);
183 tree
= isl_schedule_tree_insert_filter(tree
, filter
);
188 isl_union_set_free(filter
);
192 /* Read a sequence of integers from "s" (representing the coincident
193 * property of a band node).
195 static __isl_give isl_val_list
*read_coincident(__isl_keep isl_stream
*s
)
201 ctx
= isl_stream_get_ctx(s
);
203 if (isl_stream_yaml_read_start_sequence(s
) < 0)
206 list
= isl_val_list_alloc(ctx
, 0);
207 while ((more
= isl_stream_yaml_next(s
)) > 0) {
210 val
= isl_stream_read_val(s
);
211 list
= isl_val_list_add(list
, val
);
214 if (more
< 0 || isl_stream_yaml_read_end_sequence(s
))
215 list
= isl_val_list_free(list
);
220 /* Set the (initial) coincident properties of "band" according to
221 * the (initial) elements of "coincident".
223 static __isl_give isl_schedule_band
*set_coincident(
224 __isl_take isl_schedule_band
*band
, __isl_take isl_val_list
*coincident
)
229 n
= isl_schedule_band_n_member(band
);
230 m
= isl_val_list_n_val(coincident
);
232 for (i
= 0; i
< n
&& i
< m
; ++i
) {
235 v
= isl_val_list_get_val(coincident
, i
);
237 band
= isl_schedule_band_free(band
);
238 band
= isl_schedule_band_member_set_coincident(band
, i
,
239 !isl_val_is_zero(v
));
242 isl_val_list_free(coincident
);
246 /* Read a subtree with band root node from "s".
248 static __isl_give isl_schedule_tree
*read_band(isl_stream
*s
)
250 isl_multi_union_pw_aff
*schedule
= NULL
;
251 isl_schedule_tree
*tree
= NULL
;
252 isl_val_list
*coincident
= NULL
;
253 isl_union_set
*options
= NULL
;
255 isl_schedule_band
*band
;
259 ctx
= isl_stream_get_ctx(s
);
262 struct isl_token
*tok
;
263 enum isl_schedule_key key
;
268 if (isl_stream_yaml_next(s
) < 0)
272 case isl_schedule_key_schedule
:
273 isl_multi_union_pw_aff_free(schedule
);
274 tok
= isl_stream_next_token(s
);
276 isl_stream_error(s
, NULL
, "unexpected EOF");
279 str
= isl_token_get_str(ctx
, tok
);
280 schedule
= isl_multi_union_pw_aff_read_from_str(ctx
,
287 case isl_schedule_key_coincident
:
288 coincident
= read_coincident(s
);
292 case isl_schedule_key_permutable
:
293 v
= isl_stream_read_val(s
);
294 permutable
= !isl_val_is_zero(v
);
297 case isl_schedule_key_options
:
298 isl_union_set_free(options
);
299 tok
= isl_stream_next_token(s
);
300 str
= isl_token_get_str(ctx
, tok
);
301 options
= isl_union_set_read_from_str(ctx
, str
);
307 case isl_schedule_key_child
:
308 isl_schedule_tree_free(tree
);
309 tree
= isl_stream_read_schedule_tree(s
);
314 isl_die(ctx
, isl_error_invalid
, "unexpected key",
317 } while ((more
= isl_stream_yaml_next(s
)) > 0);
323 isl_die(ctx
, isl_error_invalid
, "missing schedule", goto error
);
325 band
= isl_schedule_band_from_multi_union_pw_aff(schedule
);
326 band
= isl_schedule_band_set_permutable(band
, permutable
);
328 band
= set_coincident(band
, coincident
);
330 band
= isl_schedule_band_set_ast_build_options(band
, options
);
332 tree
= isl_schedule_tree_insert_band(tree
, band
);
334 tree
= isl_schedule_tree_from_band(band
);
338 isl_val_list_free(coincident
);
339 isl_union_set_free(options
);
340 isl_schedule_tree_free(tree
);
341 isl_multi_union_pw_aff_free(schedule
);
345 /* Read a subtree with root node of type "type" from "s".
346 * The node is represented by a sequence of children.
348 static __isl_give isl_schedule_tree
*read_children(isl_stream
*s
,
349 enum isl_schedule_node_type type
)
352 isl_schedule_tree_list
*list
;
355 ctx
= isl_stream_get_ctx(s
);
357 isl_token_free(isl_stream_next_token(s
));
359 if (isl_stream_yaml_next(s
) < 0)
362 if (isl_stream_yaml_read_start_sequence(s
))
365 list
= isl_schedule_tree_list_alloc(ctx
, 0);
366 while ((more
= isl_stream_yaml_next(s
)) > 0) {
367 isl_schedule_tree
*tree
;
369 tree
= isl_stream_read_schedule_tree(s
);
370 list
= isl_schedule_tree_list_add(list
, tree
);
373 if (more
< 0 || isl_stream_yaml_read_end_sequence(s
))
374 list
= isl_schedule_tree_list_free(list
);
376 return isl_schedule_tree_from_children(type
, list
);
379 /* Read a subtree with sequence root node from "s".
381 static __isl_give isl_schedule_tree
*read_sequence(isl_stream
*s
)
383 return read_children(s
, isl_schedule_node_sequence
);
386 /* Read a subtree with set root node from "s".
388 static __isl_give isl_schedule_tree
*read_set(isl_stream
*s
)
390 return read_children(s
, isl_schedule_node_set
);
393 /* Read a schedule (sub)tree from "s".
395 * We first determine the type of the root node based on the first
396 * mapping key and then hand over to a function tailored to reading
397 * nodes of this type.
399 static __isl_give isl_schedule_tree
*isl_stream_read_schedule_tree(
400 struct isl_stream
*s
)
402 enum isl_schedule_key key
;
403 struct isl_token
*tok
;
404 isl_schedule_tree
*tree
= NULL
;
407 if (isl_stream_yaml_read_start_mapping(s
))
409 more
= isl_stream_yaml_next(s
);
413 isl_stream_error(s
, NULL
, "missing key");
417 tok
= isl_stream_next_token(s
);
418 key
= extract_key(s
, tok
);
419 isl_stream_push_token(s
, tok
);
423 case isl_schedule_key_domain
:
424 tree
= read_domain(s
);
426 case isl_schedule_key_filter
:
427 tree
= read_filter(s
);
429 case isl_schedule_key_leaf
:
430 isl_token_free(isl_stream_next_token(s
));
431 tree
= isl_schedule_tree_leaf(isl_stream_get_ctx(s
));
433 case isl_schedule_key_sequence
:
434 tree
= read_sequence(s
);
436 case isl_schedule_key_set
:
439 case isl_schedule_key_schedule
:
440 case isl_schedule_key_coincident
:
441 case isl_schedule_key_options
:
442 case isl_schedule_key_permutable
:
445 case isl_schedule_key_child
:
446 isl_die(isl_stream_get_ctx(s
), isl_error_unsupported
,
447 "cannot identity node type", return NULL
);
448 case isl_schedule_key_error
:
452 if (isl_stream_yaml_read_end_mapping(s
) < 0) {
453 isl_stream_error(s
, NULL
, "unexpected extra elements");
454 return isl_schedule_tree_free(tree
);
460 /* Read an isl_schedule from "s".
462 __isl_give isl_schedule
*isl_stream_read_schedule(isl_stream
*s
)
465 isl_schedule_tree
*tree
;
470 ctx
= isl_stream_get_ctx(s
);
471 tree
= isl_stream_read_schedule_tree(s
);
472 return isl_schedule_from_schedule_tree(ctx
, tree
);
475 /* Read an isl_schedule from "input".
477 __isl_give isl_schedule
*isl_schedule_read_from_file(isl_ctx
*ctx
, FILE *input
)
479 struct isl_stream
*s
;
480 isl_schedule
*schedule
;
482 s
= isl_stream_new_file(ctx
, input
);
485 schedule
= isl_stream_read_schedule(s
);
491 /* Read an isl_schedule from "str".
493 __isl_give isl_schedule
*isl_schedule_read_from_str(isl_ctx
*ctx
,
496 struct isl_stream
*s
;
497 isl_schedule
*schedule
;
499 s
= isl_stream_new_str(ctx
, str
);
502 schedule
= isl_stream_read_schedule(s
);