745 lines · c
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 mapping9 * of a schedule.10 */11enum 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_end30};31 32/* Textual representations of the YAML keys for an isl_schedule object.33 */34static 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 KEY54#define KEY enum isl_schedule_key55#undef KEY_ERROR56#define KEY_ERROR isl_schedule_key_error57#undef KEY_END58#define KEY_END isl_schedule_key_end59#undef KEY_STR60#define KEY_STR key_str61#undef KEY_EXTRACT62#define KEY_EXTRACT extract_key63#undef KEY_GET64#define KEY_GET get_key65#include "extract_key.c"66 67static __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 */72static __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;116error:117 isl_set_free(context);118 return NULL;119}120 121/* Read a subtree with domain root node from "s".122 */123static __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;167error:168 isl_union_set_free(domain);169 return NULL;170}171 172/* Read a subtree with expansion root node from "s".173 */174static __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);240error: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 */249static __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;293error:294 isl_union_map_free(extension);295 return NULL;296}297 298/* Read a subtree with filter root node from "s".299 */300static __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;344error:345 isl_union_set_free(filter);346 return NULL;347}348 349/* Read a subtree with guard root node from "s".350 */351static __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;395error:396 isl_set_free(guard);397 return NULL;398}399 400/* Read a subtree with mark root node from "s".401 */402static __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;447error:448 isl_id_free(mark);449 return NULL;450}451 452#undef EL_BASE453#define EL_BASE val454 455#include <isl_list_read_yaml_templ.c>456 457/* Read a sequence of integers from "s" (representing the coincident458 * property of a band node).459 */460static __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 to466 * the (initial) elements of "coincident".467 */468static __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 */495static __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 else581 tree = isl_schedule_tree_from_band(band);582 583 return tree;584error: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_BASE593#define EL_BASE schedule_tree594 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 */600static __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 */617static __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 */624static __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 first632 * mapping key and then hand over to a function tailored to reading633 * nodes of this type.634 */635static __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 */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 */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_BASE743#define TYPE_BASE schedule744#include "isl_read_from_str_templ.c"745