xref: /llvm-project/polly/lib/External/isl/isl_schedule_read.c (revision a749e09e184b2b0b6dde71af01c82dd427b3e3e2)
1 #include <isl/id.h>
2 #include <isl/val.h>
3 #include <isl/schedule.h>
4 #include <isl/stream.h>
5 #include <isl_schedule_private.h>
6 #include <isl_schedule_tree.h>
7 
8 /* An enumeration of the various keys that may appear in a YAML mapping
9  * of a schedule.
10  */
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_extension,
20 	isl_schedule_key_filter,
21 	isl_schedule_key_guard,
22 	isl_schedule_key_leaf,
23 	isl_schedule_key_mark,
24 	isl_schedule_key_options,
25 	isl_schedule_key_permutable,
26 	isl_schedule_key_schedule,
27 	isl_schedule_key_sequence,
28 	isl_schedule_key_set,
29 	isl_schedule_key_end
30 };
31 
32 /* Textual representations of the YAML keys for an isl_schedule object.
33  */
34 static char *key_str[] = {
35 	[isl_schedule_key_child] = "child",
36 	[isl_schedule_key_coincident] = "coincident",
37 	[isl_schedule_key_context] = "context",
38 	[isl_schedule_key_contraction] = "contraction",
39 	[isl_schedule_key_domain] = "domain",
40 	[isl_schedule_key_expansion] = "expansion",
41 	[isl_schedule_key_extension] = "extension",
42 	[isl_schedule_key_filter] = "filter",
43 	[isl_schedule_key_guard] = "guard",
44 	[isl_schedule_key_leaf] = "leaf",
45 	[isl_schedule_key_mark] = "mark",
46 	[isl_schedule_key_options] = "options",
47 	[isl_schedule_key_permutable] = "permutable",
48 	[isl_schedule_key_schedule] = "schedule",
49 	[isl_schedule_key_sequence] = "sequence",
50 	[isl_schedule_key_set] = "set",
51 };
52 
53 #undef KEY
54 #define KEY enum isl_schedule_key
55 #undef KEY_ERROR
56 #define KEY_ERROR isl_schedule_key_error
57 #undef KEY_END
58 #define KEY_END isl_schedule_key_end
59 #undef KEY_STR
60 #define KEY_STR key_str
61 #undef KEY_EXTRACT
62 #define KEY_EXTRACT extract_key
63 #undef KEY_GET
64 #define KEY_GET get_key
65 #include "extract_key.c"
66 
67 static __isl_give isl_schedule_tree *isl_stream_read_schedule_tree(
68 	__isl_keep isl_stream *s);
69 
70 /* Read a subtree with context root node from "s".
71  */
read_context(__isl_keep isl_stream * s)72 static __isl_give isl_schedule_tree *read_context(__isl_keep isl_stream *s)
73 {
74 	isl_set *context = NULL;
75 	isl_schedule_tree *tree;
76 	isl_ctx *ctx;
77 	struct isl_token *tok;
78 	enum isl_schedule_key key;
79 	char *str;
80 	isl_bool more;
81 
82 	ctx = isl_stream_get_ctx(s);
83 
84 	key = get_key(s);
85 
86 	if (isl_stream_yaml_next(s) < 0)
87 		return NULL;
88 
89 	tok = isl_stream_next_token(s);
90 	if (!tok) {
91 		isl_stream_error(s, NULL, "unexpected EOF");
92 		return NULL;
93 	}
94 	str = isl_token_get_str(ctx, tok);
95 	context = isl_set_read_from_str(ctx, str);
96 	free(str);
97 	isl_token_free(tok);
98 
99 	more = isl_stream_yaml_next(s);
100 	if (more < 0)
101 		goto error;
102 	if (!more) {
103 		tree = isl_schedule_tree_from_context(context);
104 	} else {
105 		key = get_key(s);
106 		if (key != isl_schedule_key_child)
107 			isl_die(ctx, isl_error_invalid, "expecting child",
108 				goto error);
109 		if (isl_stream_yaml_next(s) < 0)
110 			goto error;
111 		tree = isl_stream_read_schedule_tree(s);
112 		tree = isl_schedule_tree_insert_context(tree, context);
113 	}
114 
115 	return tree;
116 error:
117 	isl_set_free(context);
118 	return NULL;
119 }
120 
121 /* Read a subtree with domain root node from "s".
122  */
read_domain(__isl_keep isl_stream * s)123 static __isl_give isl_schedule_tree *read_domain(__isl_keep isl_stream *s)
124 {
125 	isl_union_set *domain = NULL;
126 	isl_schedule_tree *tree;
127 	isl_ctx *ctx;
128 	struct isl_token *tok;
129 	enum isl_schedule_key key;
130 	char *str;
131 	isl_bool more;
132 
133 	ctx = isl_stream_get_ctx(s);
134 
135 	key = get_key(s);
136 
137 	if (isl_stream_yaml_next(s) < 0)
138 		return NULL;
139 
140 	tok = isl_stream_next_token(s);
141 	if (!tok) {
142 		isl_stream_error(s, NULL, "unexpected EOF");
143 		return NULL;
144 	}
145 	str = isl_token_get_str(ctx, tok);
146 	domain = isl_union_set_read_from_str(ctx, str);
147 	free(str);
148 	isl_token_free(tok);
149 
150 	more = isl_stream_yaml_next(s);
151 	if (more < 0)
152 		goto error;
153 	if (!more) {
154 		tree = isl_schedule_tree_from_domain(domain);
155 	} else {
156 		key = get_key(s);
157 		if (key != isl_schedule_key_child)
158 			isl_die(ctx, isl_error_invalid, "expecting child",
159 				goto error);
160 		if (isl_stream_yaml_next(s) < 0)
161 			goto error;
162 		tree = isl_stream_read_schedule_tree(s);
163 		tree = isl_schedule_tree_insert_domain(tree, domain);
164 	}
165 
166 	return tree;
167 error:
168 	isl_union_set_free(domain);
169 	return NULL;
170 }
171 
172 /* Read a subtree with expansion root node from "s".
173  */
read_expansion(isl_stream * s)174 static __isl_give isl_schedule_tree *read_expansion(isl_stream *s)
175 {
176 	isl_ctx *ctx;
177 	isl_union_pw_multi_aff *contraction = NULL;
178 	isl_union_map *expansion = NULL;
179 	isl_schedule_tree *tree = NULL;
180 	isl_bool more;
181 
182 	ctx = isl_stream_get_ctx(s);
183 
184 	do {
185 		struct isl_token *tok;
186 		enum isl_schedule_key key;
187 		char *str;
188 
189 		key = get_key(s);
190 		if (isl_stream_yaml_next(s) < 0)
191 			goto error;
192 
193 		switch (key) {
194 		case isl_schedule_key_contraction:
195 			isl_union_pw_multi_aff_free(contraction);
196 			tok = isl_stream_next_token(s);
197 			str = isl_token_get_str(ctx, tok);
198 			contraction = isl_union_pw_multi_aff_read_from_str(ctx,
199 									str);
200 			free(str);
201 			isl_token_free(tok);
202 			if (!contraction)
203 				goto error;
204 			break;
205 		case isl_schedule_key_expansion:
206 			isl_union_map_free(expansion);
207 			tok = isl_stream_next_token(s);
208 			str = isl_token_get_str(ctx, tok);
209 			expansion = isl_union_map_read_from_str(ctx, str);
210 			free(str);
211 			isl_token_free(tok);
212 			if (!expansion)
213 				goto error;
214 			break;
215 		case isl_schedule_key_child:
216 			isl_schedule_tree_free(tree);
217 			tree = isl_stream_read_schedule_tree(s);
218 			if (!tree)
219 				goto error;
220 			break;
221 		default:
222 			isl_die(ctx, isl_error_invalid, "unexpected key",
223 				goto error);
224 		}
225 	} while ((more = isl_stream_yaml_next(s)) == isl_bool_true);
226 
227 	if (more < 0)
228 		goto error;
229 
230 	if (!contraction)
231 		isl_die(ctx, isl_error_invalid, "missing contraction",
232 			goto error);
233 	if (!expansion)
234 		isl_die(ctx, isl_error_invalid, "missing expansion",
235 			goto error);
236 
237 	if (!tree)
238 		return isl_schedule_tree_from_expansion(contraction, expansion);
239 	return isl_schedule_tree_insert_expansion(tree, contraction, expansion);
240 error:
241 	isl_schedule_tree_free(tree);
242 	isl_union_pw_multi_aff_free(contraction);
243 	isl_union_map_free(expansion);
244 	return NULL;
245 }
246 
247 /* Read a subtree with extension root node from "s".
248  */
read_extension(isl_stream * s)249 static __isl_give isl_schedule_tree *read_extension(isl_stream *s)
250 {
251 	isl_union_map *extension = NULL;
252 	isl_schedule_tree *tree;
253 	isl_ctx *ctx;
254 	struct isl_token *tok;
255 	enum isl_schedule_key key;
256 	char *str;
257 	isl_bool more;
258 
259 	ctx = isl_stream_get_ctx(s);
260 
261 	key = get_key(s);
262 
263 	if (isl_stream_yaml_next(s) < 0)
264 		return NULL;
265 
266 	tok = isl_stream_next_token(s);
267 	if (!tok) {
268 		isl_stream_error(s, NULL, "unexpected EOF");
269 		return NULL;
270 	}
271 	str = isl_token_get_str(ctx, tok);
272 	extension = isl_union_map_read_from_str(ctx, str);
273 	free(str);
274 	isl_token_free(tok);
275 
276 	more = isl_stream_yaml_next(s);
277 	if (more < 0)
278 		goto error;
279 	if (!more) {
280 		tree = isl_schedule_tree_from_extension(extension);
281 	} else {
282 		key = get_key(s);
283 		if (key != isl_schedule_key_child)
284 			isl_die(ctx, isl_error_invalid, "expecting child",
285 				goto error);
286 		if (isl_stream_yaml_next(s) < 0)
287 			goto error;
288 		tree = isl_stream_read_schedule_tree(s);
289 		tree = isl_schedule_tree_insert_extension(tree, extension);
290 	}
291 
292 	return tree;
293 error:
294 	isl_union_map_free(extension);
295 	return NULL;
296 }
297 
298 /* Read a subtree with filter root node from "s".
299  */
read_filter(__isl_keep isl_stream * s)300 static __isl_give isl_schedule_tree *read_filter(__isl_keep isl_stream *s)
301 {
302 	isl_union_set *filter = NULL;
303 	isl_schedule_tree *tree;
304 	isl_ctx *ctx;
305 	struct isl_token *tok;
306 	enum isl_schedule_key key;
307 	char *str;
308 	isl_bool more;
309 
310 	ctx = isl_stream_get_ctx(s);
311 
312 	key = get_key(s);
313 
314 	if (isl_stream_yaml_next(s) < 0)
315 		return NULL;
316 
317 	tok = isl_stream_next_token(s);
318 	if (!tok) {
319 		isl_stream_error(s, NULL, "unexpected EOF");
320 		return NULL;
321 	}
322 	str = isl_token_get_str(ctx, tok);
323 	filter = isl_union_set_read_from_str(ctx, str);
324 	free(str);
325 	isl_token_free(tok);
326 
327 	more = isl_stream_yaml_next(s);
328 	if (more < 0)
329 		goto error;
330 	if (!more) {
331 		tree = isl_schedule_tree_from_filter(filter);
332 	} else {
333 		key = get_key(s);
334 		if (key != isl_schedule_key_child)
335 			isl_die(ctx, isl_error_invalid, "expecting child",
336 				goto error);
337 		if (isl_stream_yaml_next(s) < 0)
338 			goto error;
339 		tree = isl_stream_read_schedule_tree(s);
340 		tree = isl_schedule_tree_insert_filter(tree, filter);
341 	}
342 
343 	return tree;
344 error:
345 	isl_union_set_free(filter);
346 	return NULL;
347 }
348 
349 /* Read a subtree with guard root node from "s".
350  */
read_guard(isl_stream * s)351 static __isl_give isl_schedule_tree *read_guard(isl_stream *s)
352 {
353 	isl_set *guard = NULL;
354 	isl_schedule_tree *tree;
355 	isl_ctx *ctx;
356 	struct isl_token *tok;
357 	enum isl_schedule_key key;
358 	char *str;
359 	isl_bool more;
360 
361 	ctx = isl_stream_get_ctx(s);
362 
363 	key = get_key(s);
364 
365 	if (isl_stream_yaml_next(s) < 0)
366 		return NULL;
367 
368 	tok = isl_stream_next_token(s);
369 	if (!tok) {
370 		isl_stream_error(s, NULL, "unexpected EOF");
371 		return NULL;
372 	}
373 	str = isl_token_get_str(ctx, tok);
374 	guard = isl_set_read_from_str(ctx, str);
375 	free(str);
376 	isl_token_free(tok);
377 
378 	more = isl_stream_yaml_next(s);
379 	if (more < 0)
380 		goto error;
381 	if (!more) {
382 		tree = isl_schedule_tree_from_guard(guard);
383 	} else {
384 		key = get_key(s);
385 		if (key != isl_schedule_key_child)
386 			isl_die(ctx, isl_error_invalid, "expecting child",
387 				goto error);
388 		if (isl_stream_yaml_next(s) < 0)
389 			goto error;
390 		tree = isl_stream_read_schedule_tree(s);
391 		tree = isl_schedule_tree_insert_guard(tree, guard);
392 	}
393 
394 	return tree;
395 error:
396 	isl_set_free(guard);
397 	return NULL;
398 }
399 
400 /* Read a subtree with mark root node from "s".
401  */
read_mark(isl_stream * s)402 static __isl_give isl_schedule_tree *read_mark(isl_stream *s)
403 {
404 	isl_id *mark;
405 	isl_schedule_tree *tree;
406 	isl_ctx *ctx;
407 	struct isl_token *tok;
408 	enum isl_schedule_key key;
409 	char *str;
410 	isl_bool more;
411 
412 	ctx = isl_stream_get_ctx(s);
413 
414 	key = get_key(s);
415 
416 	if (isl_stream_yaml_next(s) < 0)
417 		return NULL;
418 
419 	tok = isl_stream_next_token(s);
420 	if (!tok) {
421 		isl_stream_error(s, NULL, "unexpected EOF");
422 		return NULL;
423 	}
424 	str = isl_token_get_str(ctx, tok);
425 	mark = isl_id_alloc(ctx, str, NULL);
426 	free(str);
427 	isl_token_free(tok);
428 
429 	more = isl_stream_yaml_next(s);
430 	if (more < 0)
431 		goto error;
432 	if (!more) {
433 		isl_die(ctx, isl_error_invalid, "expecting child",
434 			goto error);
435 	} else {
436 		key = get_key(s);
437 		if (key != isl_schedule_key_child)
438 			isl_die(ctx, isl_error_invalid, "expecting child",
439 				goto error);
440 		if (isl_stream_yaml_next(s) < 0)
441 			goto error;
442 		tree = isl_stream_read_schedule_tree(s);
443 		tree = isl_schedule_tree_insert_mark(tree, mark);
444 	}
445 
446 	return tree;
447 error:
448 	isl_id_free(mark);
449 	return NULL;
450 }
451 
452 #undef EL_BASE
453 #define EL_BASE val
454 
455 #include <isl_list_read_yaml_templ.c>
456 
457 /* Read a sequence of integers from "s" (representing the coincident
458  * property of a band node).
459  */
read_coincident(__isl_keep isl_stream * s)460 static __isl_give isl_val_list *read_coincident(__isl_keep isl_stream *s)
461 {
462 	return isl_stream_yaml_read_val_list(s);
463 }
464 
465 /* Set the (initial) coincident properties of "band" according to
466  * the (initial) elements of "coincident".
467  */
set_coincident(__isl_take isl_schedule_band * band,__isl_take isl_val_list * coincident)468 static __isl_give isl_schedule_band *set_coincident(
469 	__isl_take isl_schedule_band *band, __isl_take isl_val_list *coincident)
470 {
471 	int i;
472 	isl_size n, m;
473 
474 	n = isl_schedule_band_n_member(band);
475 	m = isl_val_list_n_val(coincident);
476 	if (n < 0 || m < 0)
477 		band = isl_schedule_band_free(band);
478 
479 	for (i = 0; i < n && i < m; ++i) {
480 		isl_val *v;
481 
482 		v = isl_val_list_get_val(coincident, i);
483 		if (!v)
484 			band = isl_schedule_band_free(band);
485 		band = isl_schedule_band_member_set_coincident(band, i,
486 							!isl_val_is_zero(v));
487 		isl_val_free(v);
488 	}
489 	isl_val_list_free(coincident);
490 	return band;
491 }
492 
493 /* Read a subtree with band root node from "s".
494  */
read_band(isl_stream * s)495 static __isl_give isl_schedule_tree *read_band(isl_stream *s)
496 {
497 	isl_multi_union_pw_aff *schedule = NULL;
498 	isl_schedule_tree *tree = NULL;
499 	isl_val_list *coincident = NULL;
500 	isl_union_set *options = NULL;
501 	isl_ctx *ctx;
502 	isl_schedule_band *band;
503 	int permutable = 0;
504 	isl_bool more;
505 
506 	ctx = isl_stream_get_ctx(s);
507 
508 	do {
509 		struct isl_token *tok;
510 		enum isl_schedule_key key;
511 		char *str;
512 		isl_val *v;
513 
514 		key = get_key(s);
515 		if (isl_stream_yaml_next(s) < 0)
516 			goto error;
517 
518 		switch (key) {
519 		case isl_schedule_key_schedule:
520 			schedule = isl_multi_union_pw_aff_free(schedule);
521 			tok = isl_stream_next_token(s);
522 			if (!tok) {
523 				isl_stream_error(s, NULL, "unexpected EOF");
524 				goto error;
525 			}
526 			str = isl_token_get_str(ctx, tok);
527 			schedule = isl_multi_union_pw_aff_read_from_str(ctx,
528 									str);
529 			free(str);
530 			isl_token_free(tok);
531 			if (!schedule)
532 				goto error;
533 			break;
534 		case isl_schedule_key_coincident:
535 			coincident = read_coincident(s);
536 			if (!coincident)
537 				goto error;
538 			break;
539 		case isl_schedule_key_permutable:
540 			v = isl_stream_read_val(s);
541 			permutable = !isl_val_is_zero(v);
542 			isl_val_free(v);
543 			break;
544 		case isl_schedule_key_options:
545 			isl_union_set_free(options);
546 			tok = isl_stream_next_token(s);
547 			str = isl_token_get_str(ctx, tok);
548 			options = isl_union_set_read_from_str(ctx, str);
549 			free(str);
550 			isl_token_free(tok);
551 			if (!options)
552 				goto error;
553 			break;
554 		case isl_schedule_key_child:
555 			isl_schedule_tree_free(tree);
556 			tree = isl_stream_read_schedule_tree(s);
557 			if (!tree)
558 				goto error;
559 			break;
560 		default:
561 			isl_die(ctx, isl_error_invalid, "unexpected key",
562 				goto error);
563 		}
564 	} while ((more = isl_stream_yaml_next(s)) == isl_bool_true);
565 
566 	if (more < 0)
567 		goto error;
568 
569 	if (!schedule)
570 		isl_die(ctx, isl_error_invalid, "missing schedule", goto error);
571 
572 	band = isl_schedule_band_from_multi_union_pw_aff(schedule);
573 	band = isl_schedule_band_set_permutable(band, permutable);
574 	if (coincident)
575 		band = set_coincident(band, coincident);
576 	if (options)
577 		band = isl_schedule_band_set_ast_build_options(band, options);
578 	if (tree)
579 		tree = isl_schedule_tree_insert_band(tree, band);
580 	else
581 		tree = isl_schedule_tree_from_band(band);
582 
583 	return tree;
584 error:
585 	isl_val_list_free(coincident);
586 	isl_union_set_free(options);
587 	isl_schedule_tree_free(tree);
588 	isl_multi_union_pw_aff_free(schedule);
589 	return NULL;
590 }
591 
592 #undef EL_BASE
593 #define EL_BASE schedule_tree
594 
595 #include <isl_list_read_yaml_templ.c>
596 
597 /* Read a subtree with root node of type "type" from "s".
598  * The node is represented by a sequence of children.
599  */
read_children(isl_stream * s,enum isl_schedule_node_type type)600 static __isl_give isl_schedule_tree *read_children(isl_stream *s,
601 	enum isl_schedule_node_type type)
602 {
603 	isl_schedule_tree_list *list;
604 
605 	isl_token_free(isl_stream_next_token(s));
606 
607 	if (isl_stream_yaml_next(s) < 0)
608 		return NULL;
609 
610 	list = isl_stream_yaml_read_schedule_tree_list(s);
611 
612 	return isl_schedule_tree_from_children(type, list);
613 }
614 
615 /* Read a subtree with sequence root node from "s".
616  */
read_sequence(isl_stream * s)617 static __isl_give isl_schedule_tree *read_sequence(isl_stream *s)
618 {
619 	return read_children(s, isl_schedule_node_sequence);
620 }
621 
622 /* Read a subtree with set root node from "s".
623  */
read_set(isl_stream * s)624 static __isl_give isl_schedule_tree *read_set(isl_stream *s)
625 {
626 	return read_children(s, isl_schedule_node_set);
627 }
628 
629 /* Read a schedule (sub)tree from "s".
630  *
631  * We first determine the type of the root node based on the first
632  * mapping key and then hand over to a function tailored to reading
633  * nodes of this type.
634  */
isl_stream_read_schedule_tree(struct isl_stream * s)635 static __isl_give isl_schedule_tree *isl_stream_read_schedule_tree(
636 	struct isl_stream *s)
637 {
638 	enum isl_schedule_key key;
639 	struct isl_token *tok;
640 	isl_schedule_tree *tree = NULL;
641 	isl_bool more;
642 
643 	if (isl_stream_yaml_read_start_mapping(s) < 0)
644 		return NULL;
645 	more = isl_stream_yaml_next(s);
646 	if (more < 0)
647 		return NULL;
648 	if (!more) {
649 		isl_stream_error(s, NULL, "missing key");
650 		return NULL;
651 	}
652 
653 	tok = isl_stream_next_token(s);
654 	key = extract_key(s, tok);
655 	isl_stream_push_token(s, tok);
656 	if (key < 0)
657 		return NULL;
658 	switch (key) {
659 	case isl_schedule_key_context:
660 		tree = read_context(s);
661 		break;
662 	case isl_schedule_key_domain:
663 		tree = read_domain(s);
664 		break;
665 	case isl_schedule_key_contraction:
666 	case isl_schedule_key_expansion:
667 		tree = read_expansion(s);
668 		break;
669 	case isl_schedule_key_extension:
670 		tree = read_extension(s);
671 		break;
672 	case isl_schedule_key_filter:
673 		tree = read_filter(s);
674 		break;
675 	case isl_schedule_key_guard:
676 		tree = read_guard(s);
677 		break;
678 	case isl_schedule_key_leaf:
679 		isl_token_free(isl_stream_next_token(s));
680 		tree = isl_schedule_tree_leaf(isl_stream_get_ctx(s));
681 		break;
682 	case isl_schedule_key_mark:
683 		tree = read_mark(s);
684 		break;
685 	case isl_schedule_key_sequence:
686 		tree = read_sequence(s);
687 		break;
688 	case isl_schedule_key_set:
689 		tree = read_set(s);
690 		break;
691 	case isl_schedule_key_schedule:
692 	case isl_schedule_key_coincident:
693 	case isl_schedule_key_options:
694 	case isl_schedule_key_permutable:
695 		tree = read_band(s);
696 		break;
697 	case isl_schedule_key_child:
698 		isl_die(isl_stream_get_ctx(s), isl_error_unsupported,
699 			"cannot identify node type", return NULL);
700 	case isl_schedule_key_end:
701 	case isl_schedule_key_error:
702 		return NULL;
703 	}
704 
705 	if (isl_stream_yaml_read_end_mapping(s) < 0)
706 		return isl_schedule_tree_free(tree);
707 
708 	return tree;
709 }
710 
711 /* Read an isl_schedule from "s".
712  */
isl_stream_read_schedule(isl_stream * s)713 __isl_give isl_schedule *isl_stream_read_schedule(isl_stream *s)
714 {
715 	isl_ctx *ctx;
716 	isl_schedule_tree *tree;
717 
718 	if (!s)
719 		return NULL;
720 
721 	ctx = isl_stream_get_ctx(s);
722 	tree = isl_stream_read_schedule_tree(s);
723 	return isl_schedule_from_schedule_tree(ctx, tree);
724 }
725 
726 /* Read an isl_schedule from "input".
727  */
isl_schedule_read_from_file(isl_ctx * ctx,FILE * input)728 __isl_give isl_schedule *isl_schedule_read_from_file(isl_ctx *ctx, FILE *input)
729 {
730 	struct isl_stream *s;
731 	isl_schedule *schedule;
732 
733 	s = isl_stream_new_file(ctx, input);
734 	if (!s)
735 		return NULL;
736 	schedule = isl_stream_read_schedule(s);
737 	isl_stream_free(s);
738 
739 	return schedule;
740 }
741 
742 #undef TYPE_BASE
743 #define TYPE_BASE	schedule
744 #include "isl_read_from_str_templ.c"
745