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_permutable
,
19 isl_schedule_key_schedule
,
20 isl_schedule_key_sequence
,
24 /* Extract a mapping key from the token "tok".
25 * Return isl_schedule_key_error on error, i.e., if "tok" does not
26 * correspond to any known key.
28 static enum isl_schedule_key
extract_key(__isl_keep isl_stream
*s
,
29 struct isl_token
*tok
)
33 enum isl_schedule_key key
;
36 ctx
= isl_stream_get_ctx(s
);
37 type
= isl_token_get_type(tok
);
38 if (type
!= ISL_TOKEN_IDENT
&& type
!= ISL_TOKEN_STRING
) {
39 isl_stream_error(s
, tok
, "expecting key");
40 return isl_schedule_key_error
;
42 name
= isl_token_get_str(ctx
, tok
);
43 if (!strcmp(name
, "child"))
44 key
= isl_schedule_key_child
;
45 else if (!strcmp(name
, "coincident"))
46 key
= isl_schedule_key_coincident
;
47 else if (!strcmp(name
, "domain"))
48 key
= isl_schedule_key_domain
;
49 else if (!strcmp(name
, "filter"))
50 key
= isl_schedule_key_filter
;
51 else if (!strcmp(name
, "leaf"))
52 key
= isl_schedule_key_leaf
;
53 else if (!strcmp(name
, "schedule"))
54 key
= isl_schedule_key_schedule
;
55 else if (!strcmp(name
, "sequence"))
56 key
= isl_schedule_key_sequence
;
57 else if (!strcmp(name
, "set"))
58 key
= isl_schedule_key_set
;
59 else if (!strcmp(name
, "permutable"))
60 key
= isl_schedule_key_permutable
;
62 isl_die(ctx
, isl_error_invalid
, "unknown key",
63 key
= isl_schedule_key_error
);
68 /* Read a key from "s" and return the corresponding enum.
69 * Return isl_schedule_key_error on error, i.e., if the first token
70 * on the stream does not correspond to any known key.
72 static enum isl_schedule_key
get_key(__isl_keep isl_stream
*s
)
74 struct isl_token
*tok
;
75 enum isl_schedule_key key
;
77 tok
= isl_stream_next_token(s
);
78 key
= extract_key(s
, tok
);
84 static __isl_give isl_schedule_tree
*isl_stream_read_schedule_tree(
85 __isl_keep isl_stream
*s
);
87 /* Read a subtree with domain root node from "s".
89 static __isl_give isl_schedule_tree
*read_domain(__isl_keep isl_stream
*s
)
91 isl_union_set
*domain
= NULL
;
92 isl_schedule_tree
*tree
;
94 struct isl_token
*tok
;
95 enum isl_schedule_key key
;
99 ctx
= isl_stream_get_ctx(s
);
103 if (isl_stream_yaml_next(s
) < 0)
106 tok
= isl_stream_next_token(s
);
108 isl_stream_error(s
, NULL
, "unexpected EOF");
111 str
= isl_token_get_str(ctx
, tok
);
112 domain
= isl_union_set_read_from_str(ctx
, str
);
116 more
= isl_stream_yaml_next(s
);
120 tree
= isl_schedule_tree_from_domain(domain
);
123 if (key
!= isl_schedule_key_child
)
124 isl_die(ctx
, isl_error_invalid
, "expecting child",
126 if (isl_stream_yaml_next(s
) < 0)
128 tree
= isl_stream_read_schedule_tree(s
);
129 tree
= isl_schedule_tree_insert_domain(tree
, domain
);
134 isl_union_set_free(domain
);
138 /* Read a subtree with filter root node from "s".
140 static __isl_give isl_schedule_tree
*read_filter(__isl_keep isl_stream
*s
)
142 isl_union_set
*filter
= NULL
;
143 isl_schedule_tree
*tree
;
145 struct isl_token
*tok
;
146 enum isl_schedule_key key
;
150 ctx
= isl_stream_get_ctx(s
);
154 if (isl_stream_yaml_next(s
) < 0)
157 tok
= isl_stream_next_token(s
);
159 isl_stream_error(s
, NULL
, "unexpected EOF");
162 str
= isl_token_get_str(ctx
, tok
);
163 filter
= isl_union_set_read_from_str(ctx
, str
);
167 more
= isl_stream_yaml_next(s
);
171 tree
= isl_schedule_tree_from_filter(filter
);
174 if (key
!= isl_schedule_key_child
)
175 isl_die(ctx
, isl_error_invalid
, "expecting child",
177 if (isl_stream_yaml_next(s
) < 0)
179 tree
= isl_stream_read_schedule_tree(s
);
180 tree
= isl_schedule_tree_insert_filter(tree
, filter
);
185 isl_union_set_free(filter
);
189 /* Read a sequence of integers from "s" (representing the coincident
190 * property of a band node).
192 static __isl_give isl_val_list
*read_coincident(__isl_keep isl_stream
*s
)
198 ctx
= isl_stream_get_ctx(s
);
200 if (isl_stream_yaml_read_start_sequence(s
) < 0)
203 list
= isl_val_list_alloc(ctx
, 0);
204 while ((more
= isl_stream_yaml_next(s
)) > 0) {
207 val
= isl_stream_read_val(s
);
208 list
= isl_val_list_add(list
, val
);
211 if (more
< 0 || isl_stream_yaml_read_end_sequence(s
))
212 list
= isl_val_list_free(list
);
217 /* Set the (initial) coincident properties of "band" according to
218 * the (initial) elements of "coincident".
220 static __isl_give isl_schedule_band
*set_coincident(
221 __isl_take isl_schedule_band
*band
, __isl_take isl_val_list
*coincident
)
226 n
= isl_schedule_band_n_member(band
);
227 m
= isl_val_list_n_val(coincident
);
229 for (i
= 0; i
< n
&& i
< m
; ++i
) {
232 v
= isl_val_list_get_val(coincident
, i
);
234 band
= isl_schedule_band_free(band
);
235 band
= isl_schedule_band_member_set_coincident(band
, i
,
236 !isl_val_is_zero(v
));
239 isl_val_list_free(coincident
);
243 /* Read a subtree with band root node from "s".
245 static __isl_give isl_schedule_tree
*read_band(isl_stream
*s
)
247 isl_multi_union_pw_aff
*schedule
= NULL
;
248 isl_schedule_tree
*tree
= NULL
;
249 isl_val_list
*coincident
= NULL
;
251 isl_schedule_band
*band
;
255 ctx
= isl_stream_get_ctx(s
);
258 struct isl_token
*tok
;
259 enum isl_schedule_key key
;
264 if (isl_stream_yaml_next(s
) < 0)
268 case isl_schedule_key_schedule
:
269 isl_multi_union_pw_aff_free(schedule
);
270 tok
= isl_stream_next_token(s
);
272 isl_stream_error(s
, NULL
, "unexpected EOF");
275 str
= isl_token_get_str(ctx
, tok
);
276 schedule
= isl_multi_union_pw_aff_read_from_str(ctx
,
283 case isl_schedule_key_coincident
:
284 coincident
= read_coincident(s
);
288 case isl_schedule_key_permutable
:
289 v
= isl_stream_read_val(s
);
290 permutable
= !isl_val_is_zero(v
);
293 case isl_schedule_key_child
:
294 isl_schedule_tree_free(tree
);
295 tree
= isl_stream_read_schedule_tree(s
);
300 isl_die(ctx
, isl_error_invalid
, "unexpected key",
303 } while ((more
= isl_stream_yaml_next(s
)) > 0);
309 isl_die(ctx
, isl_error_invalid
, "missing schedule", goto error
);
311 band
= isl_schedule_band_from_multi_union_pw_aff(schedule
);
312 band
= isl_schedule_band_set_permutable(band
, permutable
);
314 band
= set_coincident(band
, coincident
);
316 tree
= isl_schedule_tree_insert_band(tree
, band
);
318 tree
= isl_schedule_tree_from_band(band
);
322 isl_val_list_free(coincident
);
323 isl_schedule_tree_free(tree
);
324 isl_multi_union_pw_aff_free(schedule
);
328 /* Read a subtree with root node of type "type" from "s".
329 * The node is represented by a sequence of children.
331 static __isl_give isl_schedule_tree
*read_children(isl_stream
*s
,
332 enum isl_schedule_node_type type
)
335 isl_schedule_tree_list
*list
;
338 ctx
= isl_stream_get_ctx(s
);
340 isl_token_free(isl_stream_next_token(s
));
342 if (isl_stream_yaml_next(s
) < 0)
345 if (isl_stream_yaml_read_start_sequence(s
))
348 list
= isl_schedule_tree_list_alloc(ctx
, 0);
349 while ((more
= isl_stream_yaml_next(s
)) > 0) {
350 isl_schedule_tree
*tree
;
352 tree
= isl_stream_read_schedule_tree(s
);
353 list
= isl_schedule_tree_list_add(list
, tree
);
356 if (more
< 0 || isl_stream_yaml_read_end_sequence(s
))
357 list
= isl_schedule_tree_list_free(list
);
359 return isl_schedule_tree_from_children(type
, list
);
362 /* Read a subtree with sequence root node from "s".
364 static __isl_give isl_schedule_tree
*read_sequence(isl_stream
*s
)
366 return read_children(s
, isl_schedule_node_sequence
);
369 /* Read a subtree with set root node from "s".
371 static __isl_give isl_schedule_tree
*read_set(isl_stream
*s
)
373 return read_children(s
, isl_schedule_node_set
);
376 /* Read a schedule (sub)tree from "s".
378 * We first determine the type of the root node based on the first
379 * mapping key and then hand over to a function tailored to reading
380 * nodes of this type.
382 static __isl_give isl_schedule_tree
*isl_stream_read_schedule_tree(
383 struct isl_stream
*s
)
385 enum isl_schedule_key key
;
386 struct isl_token
*tok
;
387 isl_schedule_tree
*tree
= NULL
;
390 if (isl_stream_yaml_read_start_mapping(s
))
392 more
= isl_stream_yaml_next(s
);
396 isl_stream_error(s
, NULL
, "missing key");
400 tok
= isl_stream_next_token(s
);
401 key
= extract_key(s
, tok
);
402 isl_stream_push_token(s
, tok
);
406 case isl_schedule_key_domain
:
407 tree
= read_domain(s
);
409 case isl_schedule_key_filter
:
410 tree
= read_filter(s
);
412 case isl_schedule_key_leaf
:
413 isl_token_free(isl_stream_next_token(s
));
414 tree
= isl_schedule_tree_leaf(isl_stream_get_ctx(s
));
416 case isl_schedule_key_sequence
:
417 tree
= read_sequence(s
);
419 case isl_schedule_key_set
:
422 case isl_schedule_key_schedule
:
423 case isl_schedule_key_coincident
:
424 case isl_schedule_key_permutable
:
427 case isl_schedule_key_child
:
428 isl_die(isl_stream_get_ctx(s
), isl_error_unsupported
,
429 "cannot identity node type", return NULL
);
430 case isl_schedule_key_error
:
434 if (isl_stream_yaml_read_end_mapping(s
) < 0) {
435 isl_stream_error(s
, NULL
, "unexpected extra elements");
436 return isl_schedule_tree_free(tree
);
442 /* Read an isl_schedule from "s".
444 __isl_give isl_schedule
*isl_stream_read_schedule(isl_stream
*s
)
447 isl_schedule_tree
*tree
;
452 ctx
= isl_stream_get_ctx(s
);
453 tree
= isl_stream_read_schedule_tree(s
);
454 return isl_schedule_from_schedule_tree(ctx
, tree
);
457 /* Read an isl_schedule from "input".
459 __isl_give isl_schedule
*isl_schedule_read_from_file(isl_ctx
*ctx
, FILE *input
)
461 struct isl_stream
*s
;
462 isl_schedule
*schedule
;
464 s
= isl_stream_new_file(ctx
, input
);
467 schedule
= isl_stream_read_schedule(s
);
473 /* Read an isl_schedule from "str".
475 __isl_give isl_schedule
*isl_schedule_read_from_str(isl_ctx
*ctx
,
478 struct isl_stream
*s
;
479 isl_schedule
*schedule
;
481 s
= isl_stream_new_str(ctx
, str
);
484 schedule
= isl_stream_read_schedule(s
);