3941 lines · c
1/*2 * Copyright 2012-2013 Ecole Normale Superieure3 * Copyright 2022 Cerebras Systems4 *5 * Use of this software is governed by the MIT license6 *7 * Written by Sven Verdoolaege,8 * Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France9 * and Cerebras Systems, 1237 E Arques Ave, Sunnyvale, CA, USA10 */11 12#include <string.h>13 14#include <isl/id.h>15#include <isl/stream.h>16#include <isl/val.h>17#include <isl_ast_private.h>18 19#undef EL_BASE20#define EL_BASE ast_expr21 22#include <isl_list_templ.c>23 24#undef EL_BASE25#define EL_BASE ast_node26 27#include <isl_list_templ.c>28 29isl_ctx *isl_ast_print_options_get_ctx(30 __isl_keep isl_ast_print_options *options)31{32 return options ? options->ctx : NULL;33}34 35__isl_give isl_ast_print_options *isl_ast_print_options_alloc(isl_ctx *ctx)36{37 isl_ast_print_options *options;38 39 options = isl_calloc_type(ctx, isl_ast_print_options);40 if (!options)41 return NULL;42 43 options->ctx = ctx;44 isl_ctx_ref(ctx);45 options->ref = 1;46 47 return options;48}49 50__isl_give isl_ast_print_options *isl_ast_print_options_dup(51 __isl_keep isl_ast_print_options *options)52{53 isl_ctx *ctx;54 isl_ast_print_options *dup;55 56 if (!options)57 return NULL;58 59 ctx = isl_ast_print_options_get_ctx(options);60 dup = isl_ast_print_options_alloc(ctx);61 if (!dup)62 return NULL;63 64 dup->print_for = options->print_for;65 dup->print_for_user = options->print_for_user;66 dup->print_user = options->print_user;67 dup->print_user_user = options->print_user_user;68 69 return dup;70}71 72__isl_give isl_ast_print_options *isl_ast_print_options_cow(73 __isl_take isl_ast_print_options *options)74{75 if (!options)76 return NULL;77 78 if (options->ref == 1)79 return options;80 options->ref--;81 return isl_ast_print_options_dup(options);82}83 84__isl_give isl_ast_print_options *isl_ast_print_options_copy(85 __isl_keep isl_ast_print_options *options)86{87 if (!options)88 return NULL;89 90 options->ref++;91 return options;92}93 94__isl_null isl_ast_print_options *isl_ast_print_options_free(95 __isl_take isl_ast_print_options *options)96{97 if (!options)98 return NULL;99 100 if (--options->ref > 0)101 return NULL;102 103 isl_ctx_deref(options->ctx);104 105 free(options);106 return NULL;107}108 109/* Set the print_user callback of "options" to "print_user".110 *111 * If this callback is set, then it is used to print user nodes in the AST.112 * Otherwise, the expression associated to the user node is printed.113 */114__isl_give isl_ast_print_options *isl_ast_print_options_set_print_user(115 __isl_take isl_ast_print_options *options,116 __isl_give isl_printer *(*print_user)(__isl_take isl_printer *p,117 __isl_take isl_ast_print_options *options,118 __isl_keep isl_ast_node *node, void *user),119 void *user)120{121 options = isl_ast_print_options_cow(options);122 if (!options)123 return NULL;124 125 options->print_user = print_user;126 options->print_user_user = user;127 128 return options;129}130 131/* Set the print_for callback of "options" to "print_for".132 *133 * If this callback is set, then it used to print for nodes in the AST.134 */135__isl_give isl_ast_print_options *isl_ast_print_options_set_print_for(136 __isl_take isl_ast_print_options *options,137 __isl_give isl_printer *(*print_for)(__isl_take isl_printer *p,138 __isl_take isl_ast_print_options *options,139 __isl_keep isl_ast_node *node, void *user),140 void *user)141{142 options = isl_ast_print_options_cow(options);143 if (!options)144 return NULL;145 146 options->print_for = print_for;147 options->print_for_user = user;148 149 return options;150}151 152/* Create a new operation expression of operation type "op",153 * with arguments "args".154 */155static __isl_give isl_ast_expr *alloc_op(enum isl_ast_expr_op_type op,156 __isl_take isl_ast_expr_list *args)157{158 isl_ctx *ctx;159 isl_ast_expr *expr;160 161 if (!args)162 return NULL;163 164 ctx = isl_ast_expr_list_get_ctx(args);165 expr = isl_calloc_type(ctx, isl_ast_expr);166 if (!expr)167 goto error;168 169 expr->ctx = ctx;170 isl_ctx_ref(ctx);171 expr->ref = 1;172 expr->type = isl_ast_expr_op;173 expr->u.op.op = op;174 expr->u.op.args = args;175 176 return expr;177error:178 isl_ast_expr_list_free(args);179 return NULL;180}181 182/* Create a new operation expression of operation type "op",183 * which will end up having "n_arg" arguments.184 * The caller still needs to add those arguments.185 */186__isl_give isl_ast_expr *isl_ast_expr_alloc_op(isl_ctx *ctx,187 enum isl_ast_expr_op_type op, int n_arg)188{189 isl_ast_expr_list *args;190 191 args = isl_ast_expr_list_alloc(ctx, n_arg);192 return alloc_op(op, args);193}194 195__isl_give isl_ast_expr *isl_ast_expr_copy(__isl_keep isl_ast_expr *expr)196{197 if (!expr)198 return NULL;199 200 expr->ref++;201 return expr;202}203 204__isl_give isl_ast_expr *isl_ast_expr_dup(__isl_keep isl_ast_expr *expr)205{206 isl_ast_expr *dup;207 208 if (!expr)209 return NULL;210 211 switch (expr->type) {212 case isl_ast_expr_int:213 dup = isl_ast_expr_from_val(isl_val_copy(expr->u.v));214 break;215 case isl_ast_expr_id:216 dup = isl_ast_expr_from_id(isl_id_copy(expr->u.id));217 break;218 case isl_ast_expr_op:219 dup = alloc_op(expr->u.op.op,220 isl_ast_expr_list_copy(expr->u.op.args));221 break;222 case isl_ast_expr_error:223 dup = NULL;224 }225 226 if (!dup)227 return NULL;228 229 return dup;230}231 232__isl_give isl_ast_expr *isl_ast_expr_cow(__isl_take isl_ast_expr *expr)233{234 if (!expr)235 return NULL;236 237 if (expr->ref == 1)238 return expr;239 expr->ref--;240 return isl_ast_expr_dup(expr);241}242 243__isl_null isl_ast_expr *isl_ast_expr_free(__isl_take isl_ast_expr *expr)244{245 if (!expr)246 return NULL;247 248 if (--expr->ref > 0)249 return NULL;250 251 isl_ctx_deref(expr->ctx);252 253 switch (expr->type) {254 case isl_ast_expr_int:255 isl_val_free(expr->u.v);256 break;257 case isl_ast_expr_id:258 isl_id_free(expr->u.id);259 break;260 case isl_ast_expr_op:261 isl_ast_expr_list_free(expr->u.op.args);262 break;263 case isl_ast_expr_error:264 break;265 }266 267 free(expr);268 return NULL;269}270 271isl_ctx *isl_ast_expr_get_ctx(__isl_keep isl_ast_expr *expr)272{273 return expr ? expr->ctx : NULL;274}275 276enum isl_ast_expr_type isl_ast_expr_get_type(__isl_keep isl_ast_expr *expr)277{278 return expr ? expr->type : isl_ast_expr_error;279}280 281/* Return the integer value represented by "expr".282 */283__isl_give isl_val *isl_ast_expr_int_get_val(__isl_keep isl_ast_expr *expr)284{285 if (!expr)286 return NULL;287 if (expr->type != isl_ast_expr_int)288 isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,289 "expression not an int", return NULL);290 return isl_val_copy(expr->u.v);291}292 293/* This is an alternative name for the function above.294 */295__isl_give isl_val *isl_ast_expr_get_val(__isl_keep isl_ast_expr *expr)296{297 return isl_ast_expr_int_get_val(expr);298}299 300__isl_give isl_id *isl_ast_expr_id_get_id(__isl_keep isl_ast_expr *expr)301{302 if (!expr)303 return NULL;304 if (expr->type != isl_ast_expr_id)305 isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,306 "expression not an identifier", return NULL);307 308 return isl_id_copy(expr->u.id);309}310 311/* This is an alternative name for the function above.312 */313__isl_give isl_id *isl_ast_expr_get_id(__isl_keep isl_ast_expr *expr)314{315 return isl_ast_expr_id_get_id(expr);316}317 318/* Check that "expr" is of type isl_ast_expr_op.319 */320static isl_stat isl_ast_expr_check_op(__isl_keep isl_ast_expr *expr)321{322 if (!expr)323 return isl_stat_error;324 if (expr->type != isl_ast_expr_op)325 isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,326 "expression not an operation", return isl_stat_error);327 return isl_stat_ok;328}329 330/* Return the type of operation represented by "expr".331 */332enum isl_ast_expr_op_type isl_ast_expr_op_get_type(333 __isl_keep isl_ast_expr *expr)334{335 if (isl_ast_expr_check_op(expr) < 0)336 return isl_ast_expr_op_error;337 return expr->u.op.op;338}339 340/* This is an alternative name for the function above.341 */342enum isl_ast_expr_op_type isl_ast_expr_get_op_type(343 __isl_keep isl_ast_expr *expr)344{345 return isl_ast_expr_op_get_type(expr);346}347 348/* Return the number of arguments of the operation represented by "expr".349 */350isl_size isl_ast_expr_op_get_n_arg(__isl_keep isl_ast_expr *expr)351{352 if (isl_ast_expr_check_op(expr) < 0)353 return isl_size_error;354 return isl_ast_expr_list_size(expr->u.op.args);355}356 357/* This is an alternative name for the function above.358 */359isl_size isl_ast_expr_get_op_n_arg(__isl_keep isl_ast_expr *expr)360{361 return isl_ast_expr_op_get_n_arg(expr);362}363 364/* Return the argument at position "pos" of the operation represented by "expr".365 */366__isl_give isl_ast_expr *isl_ast_expr_op_get_arg(__isl_keep isl_ast_expr *expr,367 int pos)368{369 if (isl_ast_expr_check_op(expr) < 0)370 return NULL;371 372 return isl_ast_expr_list_get_at(expr->u.op.args, pos);373}374 375/* This is an alternative name for the function above.376 */377__isl_give isl_ast_expr *isl_ast_expr_get_op_arg(__isl_keep isl_ast_expr *expr,378 int pos)379{380 return isl_ast_expr_op_get_arg(expr, pos);381}382 383/* Return a copy of the arguments of the operation represented by "expr".384 */385static __isl_give isl_ast_expr_list *isl_ast_expr_op_get_args(386 __isl_keep isl_ast_expr *expr)387{388 if (isl_ast_expr_check_op(expr) < 0)389 return NULL;390 return isl_ast_expr_list_copy(expr->u.op.args);391}392 393/* Return the arguments of the operation expression "expr".394 * This may be either a copy or the arguments themselves395 * if there is only one reference to "expr".396 * This allows the arguments to be modified inplace397 * if both "expr" and its arguments have only a single reference.398 * The caller is not allowed to modify "expr" between this call and399 * the subsequent call to isl_ast_expr_op_restore_args.400 * The only exception is that isl_ast_expr_free can be called instead.401 */402static __isl_give isl_ast_expr_list *isl_ast_expr_op_take_args(403 __isl_keep isl_ast_expr *expr)404{405 isl_ast_expr_list *args;406 407 if (isl_ast_expr_check_op(expr) < 0)408 return NULL;409 if (expr->ref != 1)410 return isl_ast_expr_op_get_args(expr);411 args = expr->u.op.args;412 expr->u.op.args = NULL;413 return args;414}415 416/* Set the arguments of the operation expression "expr" to "args",417 * where the arguments of "args" may be missing418 * due to a preceding call to isl_ast_expr_op_take_args.419 * However, in this case, "expr" only has a single reference and420 * then the call to isl_ast_expr_cow has no effect.421 */422static __isl_give isl_ast_expr *isl_ast_expr_op_restore_args(423 __isl_take isl_ast_expr *expr, __isl_take isl_ast_expr_list *args)424{425 if (isl_ast_expr_check_op(expr) < 0 || !args)426 goto error;427 if (expr->u.op.args == args) {428 isl_ast_expr_list_free(args);429 return expr;430 }431 432 expr = isl_ast_expr_cow(expr);433 if (!expr)434 goto error;435 436 isl_ast_expr_list_free(expr->u.op.args);437 expr->u.op.args = args;438 439 return expr;440error:441 isl_ast_expr_free(expr);442 isl_ast_expr_list_free(args);443 return NULL;444}445 446/* Add "arg" to the arguments of the operation expression "expr".447 */448__isl_give isl_ast_expr *isl_ast_expr_op_add_arg(__isl_take isl_ast_expr *expr,449 __isl_take isl_ast_expr *arg)450{451 isl_ast_expr_list *args;452 453 args = isl_ast_expr_op_take_args(expr);454 args = isl_ast_expr_list_add(args, arg);455 expr = isl_ast_expr_op_restore_args(expr, args);456 457 return expr;458}459 460/* Replace the argument at position "pos" of "expr" by "arg".461 */462__isl_give isl_ast_expr *isl_ast_expr_set_op_arg(__isl_take isl_ast_expr *expr,463 int pos, __isl_take isl_ast_expr *arg)464{465 isl_ast_expr_list *args;466 467 args = isl_ast_expr_op_take_args(expr);468 args = isl_ast_expr_list_set_at(args, pos, arg);469 expr = isl_ast_expr_op_restore_args(expr, args);470 471 return expr;472}473 474/* Are the lists of AST expressions "list1" and "list2" the same?475 */476static isl_bool isl_ast_expr_list_is_equal(__isl_keep isl_ast_expr_list *list1,477 __isl_keep isl_ast_expr_list *list2)478{479 int i;480 isl_size n1, n2;481 482 if (!list1 || !list2)483 return isl_bool_error;484 if (list1 == list2)485 return isl_bool_true;486 487 n1 = isl_ast_expr_list_size(list1);488 n2 = isl_ast_expr_list_size(list2);489 if (n1 < 0 || n2 < 0)490 return isl_bool_error;491 if (n1 != n2)492 return isl_bool_false;493 for (i = 0; i < n1; ++i) {494 isl_ast_expr *expr1, *expr2;495 isl_bool equal;496 497 expr1 = isl_ast_expr_list_get_at(list1, i);498 expr2 = isl_ast_expr_list_get_at(list2, i);499 equal = isl_ast_expr_is_equal(expr1, expr2);500 isl_ast_expr_free(expr1);501 isl_ast_expr_free(expr2);502 if (equal < 0 || !equal)503 return equal;504 }505 506 return isl_bool_true;507}508 509/* Is "expr1" equal to "expr2"?510 */511isl_bool isl_ast_expr_is_equal(__isl_keep isl_ast_expr *expr1,512 __isl_keep isl_ast_expr *expr2)513{514 if (!expr1 || !expr2)515 return isl_bool_error;516 517 if (expr1 == expr2)518 return isl_bool_true;519 if (expr1->type != expr2->type)520 return isl_bool_false;521 switch (expr1->type) {522 case isl_ast_expr_int:523 return isl_val_eq(expr1->u.v, expr2->u.v);524 case isl_ast_expr_id:525 return isl_bool_ok(expr1->u.id == expr2->u.id);526 case isl_ast_expr_op:527 if (expr1->u.op.op != expr2->u.op.op)528 return isl_bool_false;529 return isl_ast_expr_list_is_equal(expr1->u.op.args,530 expr2->u.op.args);531 case isl_ast_expr_error:532 return isl_bool_error;533 }534 535 isl_die(isl_ast_expr_get_ctx(expr1), isl_error_internal,536 "unhandled case", return isl_bool_error);537}538 539/* Create a new id expression representing "id".540 */541__isl_give isl_ast_expr *isl_ast_expr_from_id(__isl_take isl_id *id)542{543 isl_ctx *ctx;544 isl_ast_expr *expr;545 546 if (!id)547 return NULL;548 549 ctx = isl_id_get_ctx(id);550 expr = isl_calloc_type(ctx, isl_ast_expr);551 if (!expr)552 goto error;553 554 expr->ctx = ctx;555 isl_ctx_ref(ctx);556 expr->ref = 1;557 expr->type = isl_ast_expr_id;558 expr->u.id = id;559 560 return expr;561error:562 isl_id_free(id);563 return NULL;564}565 566/* Create a new integer expression representing "i".567 */568__isl_give isl_ast_expr *isl_ast_expr_alloc_int_si(isl_ctx *ctx, int i)569{570 isl_ast_expr *expr;571 572 expr = isl_calloc_type(ctx, isl_ast_expr);573 if (!expr)574 return NULL;575 576 expr->ctx = ctx;577 isl_ctx_ref(ctx);578 expr->ref = 1;579 expr->type = isl_ast_expr_int;580 expr->u.v = isl_val_int_from_si(ctx, i);581 if (!expr->u.v)582 return isl_ast_expr_free(expr);583 584 return expr;585}586 587/* Create a new integer expression representing "v".588 */589__isl_give isl_ast_expr *isl_ast_expr_from_val(__isl_take isl_val *v)590{591 isl_ctx *ctx;592 isl_ast_expr *expr;593 594 if (!v)595 return NULL;596 if (!isl_val_is_int(v))597 isl_die(isl_val_get_ctx(v), isl_error_invalid,598 "expecting integer value", goto error);599 600 ctx = isl_val_get_ctx(v);601 expr = isl_calloc_type(ctx, isl_ast_expr);602 if (!expr)603 goto error;604 605 expr->ctx = ctx;606 isl_ctx_ref(ctx);607 expr->ref = 1;608 expr->type = isl_ast_expr_int;609 expr->u.v = v;610 611 return expr;612error:613 isl_val_free(v);614 return NULL;615}616 617/* Create an expression representing the unary operation "type" applied to618 * "arg".619 */620__isl_give isl_ast_expr *isl_ast_expr_alloc_unary(621 enum isl_ast_expr_op_type type, __isl_take isl_ast_expr *arg)622{623 isl_ctx *ctx;624 isl_ast_expr *expr = NULL;625 isl_ast_expr_list *args;626 627 if (!arg)628 return NULL;629 630 ctx = isl_ast_expr_get_ctx(arg);631 expr = isl_ast_expr_alloc_op(ctx, type, 1);632 633 args = isl_ast_expr_op_take_args(expr);634 args = isl_ast_expr_list_add(args, arg);635 expr = isl_ast_expr_op_restore_args(expr, args);636 637 return expr;638}639 640/* Create an expression representing the negation of "arg".641 */642__isl_give isl_ast_expr *isl_ast_expr_neg(__isl_take isl_ast_expr *arg)643{644 return isl_ast_expr_alloc_unary(isl_ast_expr_op_minus, arg);645}646 647/* Create an expression representing the address of "expr".648 */649__isl_give isl_ast_expr *isl_ast_expr_address_of(__isl_take isl_ast_expr *expr)650{651 if (!expr)652 return NULL;653 654 if (isl_ast_expr_get_type(expr) != isl_ast_expr_op ||655 isl_ast_expr_get_op_type(expr) != isl_ast_expr_op_access)656 isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,657 "can only take address of access expressions",658 return isl_ast_expr_free(expr));659 660 return isl_ast_expr_alloc_unary(isl_ast_expr_op_address_of, expr);661}662 663/* Create an expression representing the binary operation "type"664 * applied to "expr1" and "expr2".665 */666__isl_give isl_ast_expr *isl_ast_expr_alloc_binary(667 enum isl_ast_expr_op_type type,668 __isl_take isl_ast_expr *expr1, __isl_take isl_ast_expr *expr2)669{670 isl_ctx *ctx;671 isl_ast_expr *expr = NULL;672 isl_ast_expr_list *args;673 674 if (!expr1 || !expr2)675 goto error;676 677 ctx = isl_ast_expr_get_ctx(expr1);678 expr = isl_ast_expr_alloc_op(ctx, type, 2);679 680 args = isl_ast_expr_op_take_args(expr);681 args = isl_ast_expr_list_add(args, expr1);682 args = isl_ast_expr_list_add(args, expr2);683 expr = isl_ast_expr_op_restore_args(expr, args);684 685 return expr;686error:687 isl_ast_expr_free(expr1);688 isl_ast_expr_free(expr2);689 return NULL;690}691 692/* Create an expression representing the sum of "expr1" and "expr2".693 */694__isl_give isl_ast_expr *isl_ast_expr_add(__isl_take isl_ast_expr *expr1,695 __isl_take isl_ast_expr *expr2)696{697 return isl_ast_expr_alloc_binary(isl_ast_expr_op_add, expr1, expr2);698}699 700/* Create an expression representing the difference of "expr1" and "expr2".701 */702__isl_give isl_ast_expr *isl_ast_expr_sub(__isl_take isl_ast_expr *expr1,703 __isl_take isl_ast_expr *expr2)704{705 return isl_ast_expr_alloc_binary(isl_ast_expr_op_sub, expr1, expr2);706}707 708/* Create an expression representing the product of "expr1" and "expr2".709 */710__isl_give isl_ast_expr *isl_ast_expr_mul(__isl_take isl_ast_expr *expr1,711 __isl_take isl_ast_expr *expr2)712{713 return isl_ast_expr_alloc_binary(isl_ast_expr_op_mul, expr1, expr2);714}715 716/* Create an expression representing the quotient of "expr1" and "expr2".717 */718__isl_give isl_ast_expr *isl_ast_expr_div(__isl_take isl_ast_expr *expr1,719 __isl_take isl_ast_expr *expr2)720{721 return isl_ast_expr_alloc_binary(isl_ast_expr_op_div, expr1, expr2);722}723 724/* Create an expression representing the quotient of the integer725 * division of "expr1" by "expr2", where "expr1" is known to be726 * non-negative.727 */728__isl_give isl_ast_expr *isl_ast_expr_pdiv_q(__isl_take isl_ast_expr *expr1,729 __isl_take isl_ast_expr *expr2)730{731 return isl_ast_expr_alloc_binary(isl_ast_expr_op_pdiv_q, expr1, expr2);732}733 734/* Create an expression representing the remainder of the integer735 * division of "expr1" by "expr2", where "expr1" is known to be736 * non-negative.737 */738__isl_give isl_ast_expr *isl_ast_expr_pdiv_r(__isl_take isl_ast_expr *expr1,739 __isl_take isl_ast_expr *expr2)740{741 return isl_ast_expr_alloc_binary(isl_ast_expr_op_pdiv_r, expr1, expr2);742}743 744/* Create an expression representing the conjunction of "expr1" and "expr2".745 */746__isl_give isl_ast_expr *isl_ast_expr_and(__isl_take isl_ast_expr *expr1,747 __isl_take isl_ast_expr *expr2)748{749 return isl_ast_expr_alloc_binary(isl_ast_expr_op_and, expr1, expr2);750}751 752/* Create an expression representing the conjunction of "expr1" and "expr2",753 * where "expr2" is evaluated only if "expr1" is evaluated to true.754 */755__isl_give isl_ast_expr *isl_ast_expr_and_then(__isl_take isl_ast_expr *expr1,756 __isl_take isl_ast_expr *expr2)757{758 return isl_ast_expr_alloc_binary(isl_ast_expr_op_and_then, expr1, expr2);759}760 761/* Create an expression representing the disjunction of "expr1" and "expr2".762 */763__isl_give isl_ast_expr *isl_ast_expr_or(__isl_take isl_ast_expr *expr1,764 __isl_take isl_ast_expr *expr2)765{766 return isl_ast_expr_alloc_binary(isl_ast_expr_op_or, expr1, expr2);767}768 769/* Create an expression representing the disjunction of "expr1" and "expr2",770 * where "expr2" is evaluated only if "expr1" is evaluated to false.771 */772__isl_give isl_ast_expr *isl_ast_expr_or_else(__isl_take isl_ast_expr *expr1,773 __isl_take isl_ast_expr *expr2)774{775 return isl_ast_expr_alloc_binary(isl_ast_expr_op_or_else, expr1, expr2);776}777 778/* Create an expression representing "expr1" less than or equal to "expr2".779 */780__isl_give isl_ast_expr *isl_ast_expr_le(__isl_take isl_ast_expr *expr1,781 __isl_take isl_ast_expr *expr2)782{783 return isl_ast_expr_alloc_binary(isl_ast_expr_op_le, expr1, expr2);784}785 786/* Create an expression representing "expr1" less than "expr2".787 */788__isl_give isl_ast_expr *isl_ast_expr_lt(__isl_take isl_ast_expr *expr1,789 __isl_take isl_ast_expr *expr2)790{791 return isl_ast_expr_alloc_binary(isl_ast_expr_op_lt, expr1, expr2);792}793 794/* Create an expression representing "expr1" greater than or equal to "expr2".795 */796__isl_give isl_ast_expr *isl_ast_expr_ge(__isl_take isl_ast_expr *expr1,797 __isl_take isl_ast_expr *expr2)798{799 return isl_ast_expr_alloc_binary(isl_ast_expr_op_ge, expr1, expr2);800}801 802/* Create an expression representing "expr1" greater than "expr2".803 */804__isl_give isl_ast_expr *isl_ast_expr_gt(__isl_take isl_ast_expr *expr1,805 __isl_take isl_ast_expr *expr2)806{807 return isl_ast_expr_alloc_binary(isl_ast_expr_op_gt, expr1, expr2);808}809 810/* Create an expression representing "expr1" equal to "expr2".811 */812__isl_give isl_ast_expr *isl_ast_expr_eq(__isl_take isl_ast_expr *expr1,813 __isl_take isl_ast_expr *expr2)814{815 return isl_ast_expr_alloc_binary(isl_ast_expr_op_eq, expr1, expr2);816}817 818/* Create an expression of type "type" with as arguments "arg0" followed819 * by "arguments".820 */821static __isl_give isl_ast_expr *ast_expr_with_arguments(822 enum isl_ast_expr_op_type type, __isl_take isl_ast_expr *arg0,823 __isl_take isl_ast_expr_list *arguments)824{825 arguments = isl_ast_expr_list_insert(arguments, 0, arg0);826 return alloc_op(type, arguments);827}828 829/* Create an expression representing an access to "array" with index830 * expressions "indices".831 */832__isl_give isl_ast_expr *isl_ast_expr_access(__isl_take isl_ast_expr *array,833 __isl_take isl_ast_expr_list *indices)834{835 return ast_expr_with_arguments(isl_ast_expr_op_access, array, indices);836}837 838/* Create an expression representing a call to "function" with argument839 * expressions "arguments".840 */841__isl_give isl_ast_expr *isl_ast_expr_call(__isl_take isl_ast_expr *function,842 __isl_take isl_ast_expr_list *arguments)843{844 return ast_expr_with_arguments(isl_ast_expr_op_call, function, arguments);845}846 847/* Wrapper around isl_ast_expr_substitute_ids for use848 * as an isl_ast_expr_list_map callback.849 */850static __isl_give isl_ast_expr *substitute_ids(__isl_take isl_ast_expr *expr,851 void *user)852{853 isl_id_to_ast_expr *id2expr = user;854 855 return isl_ast_expr_substitute_ids(expr,856 isl_id_to_ast_expr_copy(id2expr));857}858 859/* For each subexpression of "expr" of type isl_ast_expr_id,860 * if it appears in "id2expr", then replace it by the corresponding861 * expression.862 */863__isl_give isl_ast_expr *isl_ast_expr_substitute_ids(864 __isl_take isl_ast_expr *expr, __isl_take isl_id_to_ast_expr *id2expr)865{866 isl_maybe_isl_ast_expr m;867 isl_ast_expr_list *args;868 869 if (!expr || !id2expr)870 goto error;871 872 switch (expr->type) {873 case isl_ast_expr_int:874 break;875 case isl_ast_expr_id:876 m = isl_id_to_ast_expr_try_get(id2expr, expr->u.id);877 if (m.valid < 0)878 goto error;879 if (!m.valid)880 break;881 isl_ast_expr_free(expr);882 expr = m.value;883 break;884 case isl_ast_expr_op:885 args = isl_ast_expr_op_take_args(expr);886 args = isl_ast_expr_list_map(args, &substitute_ids, id2expr);887 expr = isl_ast_expr_op_restore_args(expr, args);888 break;889 case isl_ast_expr_error:890 expr = isl_ast_expr_free(expr);891 break;892 }893 894 isl_id_to_ast_expr_free(id2expr);895 return expr;896error:897 isl_ast_expr_free(expr);898 isl_id_to_ast_expr_free(id2expr);899 return NULL;900}901 902isl_ctx *isl_ast_node_get_ctx(__isl_keep isl_ast_node *node)903{904 return node ? node->ctx : NULL;905}906 907enum isl_ast_node_type isl_ast_node_get_type(__isl_keep isl_ast_node *node)908{909 return node ? node->type : isl_ast_node_error;910}911 912__isl_give isl_ast_node *isl_ast_node_alloc(isl_ctx *ctx,913 enum isl_ast_node_type type)914{915 isl_ast_node *node;916 917 node = isl_calloc_type(ctx, isl_ast_node);918 if (!node)919 return NULL;920 921 node->ctx = ctx;922 isl_ctx_ref(ctx);923 node->ref = 1;924 node->type = type;925 926 return node;927}928 929/* Create an if node with the given guard.930 *931 * The then body needs to be filled in later.932 */933__isl_give isl_ast_node *isl_ast_node_alloc_if(__isl_take isl_ast_expr *guard)934{935 isl_ast_node *node;936 937 if (!guard)938 return NULL;939 940 node = isl_ast_node_alloc(isl_ast_expr_get_ctx(guard), isl_ast_node_if);941 if (!node)942 goto error;943 node->u.i.guard = guard;944 945 return node;946error:947 isl_ast_expr_free(guard);948 return NULL;949}950 951/* Create a for node with the given iterator.952 *953 * The remaining fields need to be filled in later.954 */955__isl_give isl_ast_node *isl_ast_node_alloc_for(__isl_take isl_id *id)956{957 isl_ast_node *node;958 isl_ctx *ctx;959 960 if (!id)961 return NULL;962 963 ctx = isl_id_get_ctx(id);964 node = isl_ast_node_alloc(ctx, isl_ast_node_for);965 if (!node)966 goto error;967 968 node->u.f.iterator = isl_ast_expr_from_id(id);969 if (!node->u.f.iterator)970 return isl_ast_node_free(node);971 972 return node;973error:974 isl_id_free(id);975 return NULL;976}977 978/* Create a mark node, marking "node" with "id".979 */980__isl_give isl_ast_node *isl_ast_node_alloc_mark(__isl_take isl_id *id,981 __isl_take isl_ast_node *node)982{983 isl_ctx *ctx;984 isl_ast_node *mark;985 986 if (!id || !node)987 goto error;988 989 ctx = isl_id_get_ctx(id);990 mark = isl_ast_node_alloc(ctx, isl_ast_node_mark);991 if (!mark)992 goto error;993 994 mark->u.m.mark = id;995 mark->u.m.node = node;996 997 return mark;998error:999 isl_id_free(id);1000 isl_ast_node_free(node);1001 return NULL;1002}1003 1004/* Create a user node evaluating "expr".1005 */1006__isl_give isl_ast_node *isl_ast_node_user_from_expr(1007 __isl_take isl_ast_expr *expr)1008{1009 isl_ctx *ctx;1010 isl_ast_node *node;1011 1012 if (!expr)1013 return NULL;1014 1015 ctx = isl_ast_expr_get_ctx(expr);1016 node = isl_ast_node_alloc(ctx, isl_ast_node_user);1017 if (!node)1018 goto error;1019 1020 node->u.e.expr = expr;1021 1022 return node;1023error:1024 isl_ast_expr_free(expr);1025 return NULL;1026}1027 1028/* This is an alternative name for the function above.1029 */1030__isl_give isl_ast_node *isl_ast_node_alloc_user(__isl_take isl_ast_expr *expr)1031{1032 return isl_ast_node_user_from_expr(expr);1033}1034 1035/* Create a block node with the given children.1036 */1037__isl_give isl_ast_node *isl_ast_node_block_from_children(1038 __isl_take isl_ast_node_list *list)1039{1040 isl_ast_node *node;1041 isl_ctx *ctx;1042 1043 if (!list)1044 return NULL;1045 1046 ctx = isl_ast_node_list_get_ctx(list);1047 node = isl_ast_node_alloc(ctx, isl_ast_node_block);1048 if (!node)1049 goto error;1050 1051 node->u.b.children = list;1052 1053 return node;1054error:1055 isl_ast_node_list_free(list);1056 return NULL;1057}1058 1059/* This is an alternative name for the function above.1060 */1061__isl_give isl_ast_node *isl_ast_node_alloc_block(1062 __isl_take isl_ast_node_list *list)1063{1064 return isl_ast_node_block_from_children(list);1065}1066 1067/* Represent the given list of nodes as a single node, either by1068 * extract the node from a single element list or by creating1069 * a block node with the list of nodes as children.1070 */1071__isl_give isl_ast_node *isl_ast_node_from_ast_node_list(1072 __isl_take isl_ast_node_list *list)1073{1074 isl_size n;1075 isl_ast_node *node;1076 1077 n = isl_ast_node_list_n_ast_node(list);1078 if (n < 0)1079 goto error;1080 if (n != 1)1081 return isl_ast_node_alloc_block(list);1082 1083 node = isl_ast_node_list_get_ast_node(list, 0);1084 isl_ast_node_list_free(list);1085 1086 return node;1087error:1088 isl_ast_node_list_free(list);1089 return NULL;1090}1091 1092__isl_give isl_ast_node *isl_ast_node_copy(__isl_keep isl_ast_node *node)1093{1094 if (!node)1095 return NULL;1096 1097 node->ref++;1098 return node;1099}1100 1101/* Return a fresh copy of "node".1102 *1103 * In the case of a degenerate for node, take into account1104 * that "cond" and "inc" are NULL.1105 */1106__isl_give isl_ast_node *isl_ast_node_dup(__isl_keep isl_ast_node *node)1107{1108 isl_ast_node *dup;1109 1110 if (!node)1111 return NULL;1112 1113 dup = isl_ast_node_alloc(isl_ast_node_get_ctx(node), node->type);1114 if (!dup)1115 return NULL;1116 1117 switch (node->type) {1118 case isl_ast_node_if:1119 dup->u.i.guard = isl_ast_expr_copy(node->u.i.guard);1120 dup->u.i.then = isl_ast_node_copy(node->u.i.then);1121 dup->u.i.else_node = isl_ast_node_copy(node->u.i.else_node);1122 if (!dup->u.i.guard || !dup->u.i.then ||1123 (node->u.i.else_node && !dup->u.i.else_node))1124 return isl_ast_node_free(dup);1125 break;1126 case isl_ast_node_for:1127 dup->u.f.degenerate = node->u.f.degenerate;1128 dup->u.f.iterator = isl_ast_expr_copy(node->u.f.iterator);1129 dup->u.f.init = isl_ast_expr_copy(node->u.f.init);1130 dup->u.f.body = isl_ast_node_copy(node->u.f.body);1131 if (!dup->u.f.iterator || !dup->u.f.init || !dup->u.f.body)1132 return isl_ast_node_free(dup);1133 if (node->u.f.degenerate)1134 break;1135 dup->u.f.cond = isl_ast_expr_copy(node->u.f.cond);1136 dup->u.f.inc = isl_ast_expr_copy(node->u.f.inc);1137 if (!dup->u.f.cond || !dup->u.f.inc)1138 return isl_ast_node_free(dup);1139 break;1140 case isl_ast_node_block:1141 dup->u.b.children = isl_ast_node_list_copy(node->u.b.children);1142 if (!dup->u.b.children)1143 return isl_ast_node_free(dup);1144 break;1145 case isl_ast_node_mark:1146 dup->u.m.mark = isl_id_copy(node->u.m.mark);1147 dup->u.m.node = isl_ast_node_copy(node->u.m.node);1148 if (!dup->u.m.mark || !dup->u.m.node)1149 return isl_ast_node_free(dup);1150 break;1151 case isl_ast_node_user:1152 dup->u.e.expr = isl_ast_expr_copy(node->u.e.expr);1153 if (!dup->u.e.expr)1154 return isl_ast_node_free(dup);1155 break;1156 case isl_ast_node_error:1157 break;1158 }1159 1160 if (!node->annotation)1161 return dup;1162 dup->annotation = isl_id_copy(node->annotation);1163 if (!dup->annotation)1164 return isl_ast_node_free(dup);1165 1166 return dup;1167}1168 1169__isl_give isl_ast_node *isl_ast_node_cow(__isl_take isl_ast_node *node)1170{1171 if (!node)1172 return NULL;1173 1174 if (node->ref == 1)1175 return node;1176 node->ref--;1177 return isl_ast_node_dup(node);1178}1179 1180__isl_null isl_ast_node *isl_ast_node_free(__isl_take isl_ast_node *node)1181{1182 if (!node)1183 return NULL;1184 1185 if (--node->ref > 0)1186 return NULL;1187 1188 switch (node->type) {1189 case isl_ast_node_if:1190 isl_ast_expr_free(node->u.i.guard);1191 isl_ast_node_free(node->u.i.then);1192 isl_ast_node_free(node->u.i.else_node);1193 break;1194 case isl_ast_node_for:1195 isl_ast_expr_free(node->u.f.iterator);1196 isl_ast_expr_free(node->u.f.init);1197 isl_ast_expr_free(node->u.f.cond);1198 isl_ast_expr_free(node->u.f.inc);1199 isl_ast_node_free(node->u.f.body);1200 break;1201 case isl_ast_node_block:1202 isl_ast_node_list_free(node->u.b.children);1203 break;1204 case isl_ast_node_mark:1205 isl_id_free(node->u.m.mark);1206 isl_ast_node_free(node->u.m.node);1207 break;1208 case isl_ast_node_user:1209 isl_ast_expr_free(node->u.e.expr);1210 break;1211 case isl_ast_node_error:1212 break;1213 }1214 1215 isl_id_free(node->annotation);1216 isl_ctx_deref(node->ctx);1217 free(node);1218 1219 return NULL;1220}1221 1222/* Check that "node" is of type "type", printing "msg" if not.1223 */1224static isl_stat isl_ast_node_check_type(__isl_keep isl_ast_node *node,1225 enum isl_ast_node_type type, const char *msg)1226{1227 if (!node)1228 return isl_stat_error;1229 if (node->type != type)1230 isl_die(isl_ast_node_get_ctx(node), isl_error_invalid, msg,1231 return isl_stat_error);1232 return isl_stat_ok;1233}1234 1235/* Check that "node" is of type isl_ast_node_block.1236 */1237static isl_stat isl_ast_node_check_block(__isl_keep isl_ast_node *node)1238{1239 return isl_ast_node_check_type(node, isl_ast_node_block,1240 "not a block node");1241}1242 1243/* Check that "node" is of type isl_ast_node_if.1244 */1245static isl_stat isl_ast_node_check_if(__isl_keep isl_ast_node *node)1246{1247 return isl_ast_node_check_type(node, isl_ast_node_if, "not an if node");1248}1249 1250/* Check that "node" is of type isl_ast_node_for.1251 */1252static isl_stat isl_ast_node_check_for(__isl_keep isl_ast_node *node)1253{1254 return isl_ast_node_check_type(node, isl_ast_node_for,1255 "not a for node");1256}1257 1258/* Check that "node" is of type isl_ast_node_mark.1259 */1260static isl_stat isl_ast_node_check_mark(__isl_keep isl_ast_node *node)1261{1262 return isl_ast_node_check_type(node, isl_ast_node_mark,1263 "not a mark node");1264}1265 1266/* Check that "node" is of type isl_ast_node_user.1267 */1268static isl_stat isl_ast_node_check_user(__isl_keep isl_ast_node *node)1269{1270 return isl_ast_node_check_type(node, isl_ast_node_user,1271 "not a user node");1272}1273 1274#undef NODE_TYPE1275#define NODE_TYPE for1276#undef FIELD_NAME1277#define FIELD_NAME init1278#undef FIELD_TYPE1279#define FIELD_TYPE isl_ast_expr1280#undef FIELD1281#define FIELD u.f.init1282#include "isl_ast_node_set_field_templ.c"1283 1284#undef NODE_TYPE1285#define NODE_TYPE for1286#undef FIELD_NAME1287#define FIELD_NAME cond1288#undef FIELD_TYPE1289#define FIELD_TYPE isl_ast_expr1290#undef FIELD1291#define FIELD u.f.cond1292#include "isl_ast_node_set_field_templ.c"1293 1294#undef NODE_TYPE1295#define NODE_TYPE for1296#undef FIELD_NAME1297#define FIELD_NAME inc1298#undef FIELD_TYPE1299#define FIELD_TYPE isl_ast_expr1300#undef FIELD1301#define FIELD u.f.inc1302#include "isl_ast_node_set_field_templ.c"1303 1304#undef NODE_TYPE1305#define NODE_TYPE for1306#undef FIELD_NAME1307#define FIELD_NAME body1308#undef FIELD_TYPE1309#define FIELD_TYPE isl_ast_node1310#undef FIELD1311#define FIELD u.f.body1312#include "isl_ast_node_set_field_templ.c"1313 1314/* Return the body of the for-node "node",1315 * This may be either a copy or the body itself1316 * if there is only one reference to "node".1317 * This allows the body to be modified inplace1318 * if both "node" and its body have only a single reference.1319 * The caller is not allowed to modify "node" between this call and1320 * the subsequent call to isl_ast_node_for_restore_body.1321 * The only exception is that isl_ast_node_free can be called instead.1322 */1323static __isl_give isl_ast_node *isl_ast_node_for_take_body(1324 __isl_keep isl_ast_node *node)1325{1326 isl_ast_node *body;1327 1328 if (isl_ast_node_check_for(node) < 0)1329 return NULL;1330 if (node->ref != 1)1331 return isl_ast_node_for_get_body(node);1332 body = node->u.f.body;1333 node->u.f.body = NULL;1334 return body;1335}1336 1337/* Set the body of the for-node "node" to "body",1338 * where the body of "node" may be missing1339 * due to a preceding call to isl_ast_node_for_take_body.1340 * However, in this case, "node" only has a single reference.1341 */1342static __isl_give isl_ast_node *isl_ast_node_for_restore_body(1343 __isl_take isl_ast_node *node, __isl_take isl_ast_node *body)1344{1345 return isl_ast_node_for_set_body(node, body);1346}1347 1348__isl_give isl_ast_node *isl_ast_node_for_get_body(1349 __isl_keep isl_ast_node *node)1350{1351 if (isl_ast_node_check_for(node) < 0)1352 return NULL;1353 return isl_ast_node_copy(node->u.f.body);1354}1355 1356/* Mark the given for node as being degenerate.1357 */1358__isl_give isl_ast_node *isl_ast_node_for_mark_degenerate(1359 __isl_take isl_ast_node *node)1360{1361 node = isl_ast_node_cow(node);1362 if (!node)1363 return NULL;1364 node->u.f.degenerate = 1;1365 return node;1366}1367 1368isl_bool isl_ast_node_for_is_degenerate(__isl_keep isl_ast_node *node)1369{1370 if (isl_ast_node_check_for(node) < 0)1371 return isl_bool_error;1372 return isl_bool_ok(node->u.f.degenerate);1373}1374 1375__isl_give isl_ast_expr *isl_ast_node_for_get_iterator(1376 __isl_keep isl_ast_node *node)1377{1378 if (isl_ast_node_check_for(node) < 0)1379 return NULL;1380 return isl_ast_expr_copy(node->u.f.iterator);1381}1382 1383__isl_give isl_ast_expr *isl_ast_node_for_get_init(1384 __isl_keep isl_ast_node *node)1385{1386 if (isl_ast_node_check_for(node) < 0)1387 return NULL;1388 return isl_ast_expr_copy(node->u.f.init);1389}1390 1391/* Return the condition expression of the given for node.1392 *1393 * If the for node is degenerate, then the condition is not explicitly1394 * stored in the node. Instead, it is constructed as1395 *1396 * iterator <= init1397 */1398__isl_give isl_ast_expr *isl_ast_node_for_get_cond(1399 __isl_keep isl_ast_node *node)1400{1401 if (isl_ast_node_check_for(node) < 0)1402 return NULL;1403 if (!node->u.f.degenerate)1404 return isl_ast_expr_copy(node->u.f.cond);1405 1406 return isl_ast_expr_alloc_binary(isl_ast_expr_op_le,1407 isl_ast_expr_copy(node->u.f.iterator),1408 isl_ast_expr_copy(node->u.f.init));1409}1410 1411/* Return the increment of the given for node.1412 *1413 * If the for node is degenerate, then the increment is not explicitly1414 * stored in the node. We simply return "1".1415 */1416__isl_give isl_ast_expr *isl_ast_node_for_get_inc(1417 __isl_keep isl_ast_node *node)1418{1419 if (isl_ast_node_check_for(node) < 0)1420 return NULL;1421 if (!node->u.f.degenerate)1422 return isl_ast_expr_copy(node->u.f.inc);1423 return isl_ast_expr_alloc_int_si(isl_ast_node_get_ctx(node), 1);1424}1425 1426#undef NODE_TYPE1427#define NODE_TYPE if1428#undef FIELD_NAME1429#define FIELD_NAME then1430#undef FIELD_TYPE1431#define FIELD_TYPE isl_ast_node1432#undef FIELD1433#define FIELD u.i.then1434#include "isl_ast_node_set_field_templ.c"1435 1436/* Return the then-branch of the if-node "node",1437 * This may be either a copy or the branch itself1438 * if there is only one reference to "node".1439 * This allows the branch to be modified inplace1440 * if both "node" and its then-branch have only a single reference.1441 * The caller is not allowed to modify "node" between this call and1442 * the subsequent call to isl_ast_node_if_restore_then_node.1443 * The only exception is that isl_ast_node_free can be called instead.1444 */1445static __isl_give isl_ast_node *isl_ast_node_if_take_then_node(1446 __isl_keep isl_ast_node *node)1447{1448 isl_ast_node *then_node;1449 1450 if (isl_ast_node_check_if(node) < 0)1451 return NULL;1452 if (node->ref != 1)1453 return isl_ast_node_if_get_then_node(node);1454 then_node = node->u.i.then;1455 node->u.i.then = NULL;1456 return then_node;1457}1458 1459/* Set the then-branch of the if-node "node" to "child",1460 * where the then-branch of "node" may be missing1461 * due to a preceding call to isl_ast_node_if_take_then_node.1462 * However, in this case, "node" only has a single reference.1463 */1464static __isl_give isl_ast_node *isl_ast_node_if_restore_then_node(1465 __isl_take isl_ast_node *node, __isl_take isl_ast_node *child)1466{1467 return isl_ast_node_if_set_then(node, child);1468}1469 1470/* Return the then-node of the given if-node.1471 */1472__isl_give isl_ast_node *isl_ast_node_if_get_then_node(1473 __isl_keep isl_ast_node *node)1474{1475 if (isl_ast_node_check_if(node) < 0)1476 return NULL;1477 return isl_ast_node_copy(node->u.i.then);1478}1479 1480/* This is an alternative name for the function above.1481 */1482__isl_give isl_ast_node *isl_ast_node_if_get_then(1483 __isl_keep isl_ast_node *node)1484{1485 return isl_ast_node_if_get_then_node(node);1486}1487 1488/* Does the given if-node have an else-node?1489 */1490isl_bool isl_ast_node_if_has_else_node(__isl_keep isl_ast_node *node)1491{1492 if (isl_ast_node_check_if(node) < 0)1493 return isl_bool_error;1494 return isl_bool_ok(node->u.i.else_node != NULL);1495}1496 1497/* This is an alternative name for the function above.1498 */1499isl_bool isl_ast_node_if_has_else(__isl_keep isl_ast_node *node)1500{1501 return isl_ast_node_if_has_else_node(node);1502}1503 1504/* Return the else-node of the given if-node,1505 * assuming there is one.1506 */1507__isl_give isl_ast_node *isl_ast_node_if_get_else_node(1508 __isl_keep isl_ast_node *node)1509{1510 if (isl_ast_node_check_if(node) < 0)1511 return NULL;1512 return isl_ast_node_copy(node->u.i.else_node);1513}1514 1515/* This is an alternative name for the function above.1516 */1517__isl_give isl_ast_node *isl_ast_node_if_get_else(1518 __isl_keep isl_ast_node *node)1519{1520 return isl_ast_node_if_get_else_node(node);1521}1522 1523#undef NODE_TYPE1524#define NODE_TYPE if1525#undef FIELD_NAME1526#define FIELD_NAME else_node1527#undef FIELD_TYPE1528#define FIELD_TYPE isl_ast_node1529#undef FIELD1530#define FIELD u.i.else_node1531static1532#include "isl_ast_node_set_field_templ.c"1533 1534/* Return the else-branch of the if-node "node",1535 * This may be either a copy or the branch itself1536 * if there is only one reference to "node".1537 * This allows the branch to be modified inplace1538 * if both "node" and its else-branch have only a single reference.1539 * The caller is not allowed to modify "node" between this call and1540 * the subsequent call to isl_ast_node_if_restore_else_node.1541 * The only exception is that isl_ast_node_free can be called instead.1542 */1543static __isl_give isl_ast_node *isl_ast_node_if_take_else_node(1544 __isl_keep isl_ast_node *node)1545{1546 isl_ast_node *else_node;1547 1548 if (isl_ast_node_check_if(node) < 0)1549 return NULL;1550 if (node->ref != 1)1551 return isl_ast_node_if_get_else_node(node);1552 else_node = node->u.i.else_node;1553 node->u.i.else_node = NULL;1554 return else_node;1555}1556 1557/* Set the else-branch of the if-node "node" to "child",1558 * where the else-branch of "node" may be missing1559 * due to a preceding call to isl_ast_node_if_take_else_node.1560 * However, in this case, "node" only has a single reference.1561 */1562static __isl_give isl_ast_node *isl_ast_node_if_restore_else_node(1563 __isl_take isl_ast_node *node, __isl_take isl_ast_node *child)1564{1565 return isl_ast_node_if_set_else_node(node, child);1566}1567 1568__isl_give isl_ast_expr *isl_ast_node_if_get_cond(1569 __isl_keep isl_ast_node *node)1570{1571 if (isl_ast_node_check_if(node) < 0)1572 return NULL;1573 return isl_ast_expr_copy(node->u.i.guard);1574}1575 1576__isl_give isl_ast_node_list *isl_ast_node_block_get_children(1577 __isl_keep isl_ast_node *node)1578{1579 if (isl_ast_node_check_block(node) < 0)1580 return NULL;1581 return isl_ast_node_list_copy(node->u.b.children);1582}1583 1584#undef NODE_TYPE1585#define NODE_TYPE block1586#undef FIELD_NAME1587#define FIELD_NAME children1588#undef FIELD_TYPE1589#define FIELD_TYPE isl_ast_node_list1590#undef FIELD1591#define FIELD u.b.children1592static1593#include "isl_ast_node_set_field_templ.c"1594 1595/* Return the children of the block-node "node",1596 * This may be either a copy or the children themselves1597 * if there is only one reference to "node".1598 * This allows the children to be modified inplace1599 * if both "node" and its children have only a single reference.1600 * The caller is not allowed to modify "node" between this call and1601 * the subsequent call to isl_ast_node_block_restore_children.1602 * The only exception is that isl_ast_node_free can be called instead.1603 */1604static __isl_give isl_ast_node_list *isl_ast_node_block_take_children(1605 __isl_keep isl_ast_node *node)1606{1607 isl_ast_node_list *children;1608 1609 if (isl_ast_node_check_block(node) < 0)1610 return NULL;1611 if (node->ref != 1)1612 return isl_ast_node_block_get_children(node);1613 children = node->u.b.children;1614 node->u.b.children = NULL;1615 return children;1616}1617 1618/* Set the children of the block-node "node" to "children",1619 * where the children of "node" may be missing1620 * due to a preceding call to isl_ast_node_block_take_children.1621 * However, in this case, "node" only has a single reference.1622 */1623static __isl_give isl_ast_node *isl_ast_node_block_restore_children(1624 __isl_take isl_ast_node *node, __isl_take isl_ast_node_list *children)1625{1626 return isl_ast_node_block_set_children(node, children);1627}1628 1629__isl_give isl_ast_expr *isl_ast_node_user_get_expr(1630 __isl_keep isl_ast_node *node)1631{1632 if (isl_ast_node_check_user(node) < 0)1633 return NULL;1634 1635 return isl_ast_expr_copy(node->u.e.expr);1636}1637 1638/* Return the mark identifier of the mark node "node".1639 */1640__isl_give isl_id *isl_ast_node_mark_get_id(__isl_keep isl_ast_node *node)1641{1642 if (isl_ast_node_check_mark(node) < 0)1643 return NULL;1644 1645 return isl_id_copy(node->u.m.mark);1646}1647 1648/* Return the node marked by mark node "node".1649 */1650__isl_give isl_ast_node *isl_ast_node_mark_get_node(1651 __isl_keep isl_ast_node *node)1652{1653 if (isl_ast_node_check_mark(node) < 0)1654 return NULL;1655 1656 return isl_ast_node_copy(node->u.m.node);1657}1658 1659#undef NODE_TYPE1660#define NODE_TYPE mark1661#undef FIELD_NAME1662#define FIELD_NAME node1663#undef FIELD_TYPE1664#define FIELD_TYPE isl_ast_node1665#undef FIELD1666#define FIELD u.m.node1667static1668#include "isl_ast_node_set_field_templ.c"1669 1670/* Return the child of the mark-node "node",1671 * This may be either a copy or the child itself1672 * if there is only one reference to "node".1673 * This allows the child to be modified inplace1674 * if both "node" and its child have only a single reference.1675 * The caller is not allowed to modify "node" between this call and1676 * the subsequent call to isl_ast_node_mark_restore_node.1677 * The only exception is that isl_ast_node_free can be called instead.1678 */1679static __isl_give isl_ast_node *isl_ast_node_mark_take_node(1680 __isl_keep isl_ast_node *node)1681{1682 isl_ast_node *child;1683 1684 if (isl_ast_node_check_mark(node) < 0)1685 return NULL;1686 if (node->ref != 1)1687 return isl_ast_node_mark_get_node(node);1688 child = node->u.m.node;1689 node->u.m.node = NULL;1690 return child;1691}1692 1693/* Set the child of the mark-node "node" to "child",1694 * where the child of "node" may be missing1695 * due to a preceding call to isl_ast_node_mark_take_node.1696 * However, in this case, "node" only has a single reference.1697 */1698static __isl_give isl_ast_node *isl_ast_node_mark_restore_node(1699 __isl_take isl_ast_node *node, __isl_take isl_ast_node *child)1700{1701 return isl_ast_node_mark_set_node(node, child);1702}1703 1704__isl_give isl_id *isl_ast_node_get_annotation(__isl_keep isl_ast_node *node)1705{1706 return node ? isl_id_copy(node->annotation) : NULL;1707}1708 1709/* Check that "node" is of any type.1710 * That is, simply check that it is a valid node.1711 */1712static isl_stat isl_ast_node_check_any(__isl_keep isl_ast_node *node)1713{1714 return isl_stat_non_null(node);1715}1716 1717#undef NODE_TYPE1718#define NODE_TYPE any1719#undef FIELD_NAME1720#define FIELD_NAME annotation1721#undef FIELD_TYPE1722#define FIELD_TYPE isl_id1723#undef FIELD1724#define FIELD annotation1725static1726#include "isl_ast_node_set_field_templ.c"1727 1728/* Replace node->annotation by "annotation".1729 */1730__isl_give isl_ast_node *isl_ast_node_set_annotation(1731 __isl_take isl_ast_node *node, __isl_take isl_id *annotation)1732{1733 return isl_ast_node_any_set_annotation(node, annotation);1734}1735 1736static __isl_give isl_ast_node *traverse(__isl_take isl_ast_node *node,1737 __isl_give isl_ast_node *(*enter)(__isl_take isl_ast_node *node,1738 int *more, void *user),1739 __isl_give isl_ast_node *(*leave)(__isl_take isl_ast_node *node,1740 void *user),1741 void *user);1742 1743/* Traverse the elements of "list" and all their descendants1744 * in depth first preorder. Call "enter" whenever a node is entered and "leave"1745 * whenever a node is left.1746 *1747 * Return the updated node.1748 */1749static __isl_give isl_ast_node_list *traverse_list(1750 __isl_take isl_ast_node_list *list,1751 __isl_give isl_ast_node *(*enter)(__isl_take isl_ast_node *node,1752 int *more, void *user),1753 __isl_give isl_ast_node *(*leave)(__isl_take isl_ast_node *node,1754 void *user),1755 void *user)1756{1757 int i;1758 isl_size n;1759 1760 n = isl_ast_node_list_size(list);1761 if (n < 0)1762 return isl_ast_node_list_free(list);1763 1764 for (i = 0; i < n; ++i) {1765 isl_ast_node *node;1766 1767 node = isl_ast_node_list_get_at(list, i);1768 node = traverse(node, enter, leave, user);1769 list = isl_ast_node_list_set_at(list, i, node);1770 }1771 1772 return list;1773}1774 1775/* Traverse the descendants of "node" (including the node itself)1776 * in depth first preorder. Call "enter" whenever a node is entered and "leave"1777 * whenever a node is left.1778 *1779 * If "enter" sets the "more" argument to zero, then the subtree rooted1780 * at the given node is skipped.1781 *1782 * Return the updated node.1783 */1784static __isl_give isl_ast_node *traverse(__isl_take isl_ast_node *node,1785 __isl_give isl_ast_node *(*enter)(__isl_take isl_ast_node *node,1786 int *more, void *user),1787 __isl_give isl_ast_node *(*leave)(__isl_take isl_ast_node *node,1788 void *user),1789 void *user)1790{1791 int more;1792 isl_bool has_else;1793 isl_ast_node *child;1794 isl_ast_node_list *children;1795 1796 node = enter(node, &more, user);1797 if (!node)1798 return NULL;1799 if (!more)1800 return node;1801 1802 switch (node->type) {1803 case isl_ast_node_for:1804 child = isl_ast_node_for_take_body(node);1805 child = traverse(child, enter, leave, user);1806 node = isl_ast_node_for_restore_body(node, child);1807 return leave(node, user);1808 case isl_ast_node_if:1809 child = isl_ast_node_if_take_then_node(node);1810 child = traverse(child, enter, leave, user);1811 node = isl_ast_node_if_restore_then_node(node, child);1812 has_else = isl_ast_node_if_has_else_node(node);1813 if (has_else < 0)1814 return isl_ast_node_free(node);1815 if (!has_else)1816 return leave(node, user);1817 child = isl_ast_node_if_take_else_node(node);1818 child = traverse(child, enter, leave, user);1819 node = isl_ast_node_if_restore_else_node(node, child);1820 return leave(node, user);1821 case isl_ast_node_block:1822 children = isl_ast_node_block_take_children(node);1823 children = traverse_list(children, enter, leave, user);1824 node = isl_ast_node_block_restore_children(node, children);1825 return leave(node, user);1826 case isl_ast_node_mark:1827 child = isl_ast_node_mark_take_node(node);1828 child = traverse(child, enter, leave, user);1829 node = isl_ast_node_mark_restore_node(node, child);1830 return leave(node, user);1831 case isl_ast_node_user:1832 return leave(node, user);1833 case isl_ast_node_error:1834 return isl_ast_node_free(node);1835 }1836 1837 return node;1838}1839 1840/* Internal data structure storing the arguments of1841 * isl_ast_node_foreach_descendant_top_down.1842 */1843struct isl_ast_node_preorder_data {1844 isl_bool (*fn)(__isl_keep isl_ast_node *node, void *user);1845 void *user;1846};1847 1848/* Enter "node" and set *more to continue traversing its descendants.1849 *1850 * In the case of a depth first preorder traversal, call data->fn and1851 * let it decide whether to continue.1852 */1853static __isl_give isl_ast_node *preorder_enter(__isl_take isl_ast_node *node,1854 int *more, void *user)1855{1856 struct isl_ast_node_preorder_data *data = user;1857 isl_bool m;1858 1859 if (!node)1860 return NULL;1861 m = data->fn(node, data->user);1862 if (m < 0)1863 return isl_ast_node_free(node);1864 *more = m;1865 return node;1866}1867 1868/* Leave "node".1869 *1870 * In the case of a depth first preorder traversal, nothing needs to be done.1871 */1872static __isl_give isl_ast_node *preorder_leave(__isl_take isl_ast_node *node,1873 void *user)1874{1875 return node;1876}1877 1878/* Traverse the descendants of "node" (including the node itself)1879 * in depth first preorder.1880 *1881 * If "fn" returns isl_bool_error on any of the nodes, then the traversal1882 * is aborted.1883 * If "fn" returns isl_bool_false on any of the nodes, then the subtree rooted1884 * at that node is skipped.1885 *1886 * Return isl_stat_ok on success and isl_stat_error on failure.1887 */1888isl_stat isl_ast_node_foreach_descendant_top_down(1889 __isl_keep isl_ast_node *node,1890 isl_bool (*fn)(__isl_keep isl_ast_node *node, void *user), void *user)1891{1892 struct isl_ast_node_preorder_data data = { fn, user };1893 1894 node = isl_ast_node_copy(node);1895 node = traverse(node, &preorder_enter, &preorder_leave, &data);1896 isl_ast_node_free(node);1897 1898 return isl_stat_non_null(node);1899}1900 1901/* Internal data structure storing the arguments of1902 * isl_ast_node_map_descendant_bottom_up.1903 */1904struct isl_ast_node_postorder_data {1905 __isl_give isl_ast_node *(*fn)(__isl_take isl_ast_node *node,1906 void *user);1907 void *user;1908};1909 1910/* Enter "node" and set *more to continue traversing its descendants.1911 *1912 * In the case of a depth-first post-order traversal,1913 * nothing needs to be done and traversal always continues.1914 */1915static __isl_give isl_ast_node *postorder_enter(__isl_take isl_ast_node *node,1916 int *more, void *user)1917{1918 *more = 1;1919 return node;1920}1921 1922/* Leave "node".1923 *1924 * In the case of a depth-first post-order traversal, call data->fn.1925 */1926static __isl_give isl_ast_node *postorder_leave(__isl_take isl_ast_node *node,1927 void *user)1928{1929 struct isl_ast_node_postorder_data *data = user;1930 1931 if (!node)1932 return NULL;1933 1934 node = data->fn(node, data->user);1935 return node;1936}1937 1938/* Traverse the descendants of "node" (including the node itself)1939 * in depth-first post-order, where the user callback is allowed to modify the1940 * visited node.1941 *1942 * Return the updated node.1943 */1944__isl_give isl_ast_node *isl_ast_node_map_descendant_bottom_up(1945 __isl_take isl_ast_node *node,1946 __isl_give isl_ast_node *(*fn)(__isl_take isl_ast_node *node,1947 void *user), void *user)1948{1949 struct isl_ast_node_postorder_data data = { fn, user };1950 1951 return traverse(node, &postorder_enter, &postorder_leave, &data);1952}1953 1954/* Textual C representation of the various operators.1955 */1956static char *op_str_c[] = {1957 [isl_ast_expr_op_and] = "&&",1958 [isl_ast_expr_op_and_then] = "&&",1959 [isl_ast_expr_op_or] = "||",1960 [isl_ast_expr_op_or_else] = "||",1961 [isl_ast_expr_op_max] = "max",1962 [isl_ast_expr_op_min] = "min",1963 [isl_ast_expr_op_minus] = "-",1964 [isl_ast_expr_op_add] = "+",1965 [isl_ast_expr_op_sub] = "-",1966 [isl_ast_expr_op_mul] = "*",1967 [isl_ast_expr_op_fdiv_q] = "floord",1968 [isl_ast_expr_op_pdiv_q] = "/",1969 [isl_ast_expr_op_pdiv_r] = "%",1970 [isl_ast_expr_op_zdiv_r] = "%",1971 [isl_ast_expr_op_div] = "/",1972 [isl_ast_expr_op_eq] = "==",1973 [isl_ast_expr_op_le] = "<=",1974 [isl_ast_expr_op_ge] = ">=",1975 [isl_ast_expr_op_lt] = "<",1976 [isl_ast_expr_op_gt] = ">",1977 [isl_ast_expr_op_member] = ".",1978 [isl_ast_expr_op_address_of] = "&"1979};1980 1981/* Precedence in C of the various operators.1982 * Based on http://en.wikipedia.org/wiki/Operators_in_C_and_C++1983 * Lowest value means highest precedence.1984 */1985static int op_prec[] = {1986 [isl_ast_expr_op_and] = 13,1987 [isl_ast_expr_op_and_then] = 13,1988 [isl_ast_expr_op_or] = 14,1989 [isl_ast_expr_op_or_else] = 14,1990 [isl_ast_expr_op_max] = 2,1991 [isl_ast_expr_op_min] = 2,1992 [isl_ast_expr_op_minus] = 3,1993 [isl_ast_expr_op_add] = 6,1994 [isl_ast_expr_op_sub] = 6,1995 [isl_ast_expr_op_mul] = 5,1996 [isl_ast_expr_op_div] = 5,1997 [isl_ast_expr_op_fdiv_q] = 2,1998 [isl_ast_expr_op_pdiv_q] = 5,1999 [isl_ast_expr_op_pdiv_r] = 5,2000 [isl_ast_expr_op_zdiv_r] = 5,2001 [isl_ast_expr_op_cond] = 15,2002 [isl_ast_expr_op_select] = 15,2003 [isl_ast_expr_op_eq] = 9,2004 [isl_ast_expr_op_le] = 8,2005 [isl_ast_expr_op_ge] = 8,2006 [isl_ast_expr_op_lt] = 8,2007 [isl_ast_expr_op_gt] = 8,2008 [isl_ast_expr_op_call] = 2,2009 [isl_ast_expr_op_access] = 2,2010 [isl_ast_expr_op_member] = 2,2011 [isl_ast_expr_op_address_of] = 32012};2013 2014/* Is the operator left-to-right associative?2015 */2016static int op_left[] = {2017 [isl_ast_expr_op_and] = 1,2018 [isl_ast_expr_op_and_then] = 1,2019 [isl_ast_expr_op_or] = 1,2020 [isl_ast_expr_op_or_else] = 1,2021 [isl_ast_expr_op_max] = 1,2022 [isl_ast_expr_op_min] = 1,2023 [isl_ast_expr_op_minus] = 0,2024 [isl_ast_expr_op_add] = 1,2025 [isl_ast_expr_op_sub] = 1,2026 [isl_ast_expr_op_mul] = 1,2027 [isl_ast_expr_op_div] = 1,2028 [isl_ast_expr_op_fdiv_q] = 1,2029 [isl_ast_expr_op_pdiv_q] = 1,2030 [isl_ast_expr_op_pdiv_r] = 1,2031 [isl_ast_expr_op_zdiv_r] = 1,2032 [isl_ast_expr_op_cond] = 0,2033 [isl_ast_expr_op_select] = 0,2034 [isl_ast_expr_op_eq] = 1,2035 [isl_ast_expr_op_le] = 1,2036 [isl_ast_expr_op_ge] = 1,2037 [isl_ast_expr_op_lt] = 1,2038 [isl_ast_expr_op_gt] = 1,2039 [isl_ast_expr_op_call] = 1,2040 [isl_ast_expr_op_access] = 1,2041 [isl_ast_expr_op_member] = 1,2042 [isl_ast_expr_op_address_of] = 02043};2044 2045static int is_and(enum isl_ast_expr_op_type op)2046{2047 return op == isl_ast_expr_op_and || op == isl_ast_expr_op_and_then;2048}2049 2050static int is_or(enum isl_ast_expr_op_type op)2051{2052 return op == isl_ast_expr_op_or || op == isl_ast_expr_op_or_else;2053}2054 2055static int is_add_sub(enum isl_ast_expr_op_type op)2056{2057 return op == isl_ast_expr_op_add || op == isl_ast_expr_op_sub;2058}2059 2060static int is_div_mod(enum isl_ast_expr_op_type op)2061{2062 return op == isl_ast_expr_op_div ||2063 op == isl_ast_expr_op_pdiv_r ||2064 op == isl_ast_expr_op_zdiv_r;2065}2066 2067static __isl_give isl_printer *print_ast_expr_c(__isl_take isl_printer *p,2068 __isl_keep isl_ast_expr *expr);2069 2070/* Do we need/want parentheses around "expr" as a subexpression of2071 * an "op" operation? If "left" is set, then "expr" is the left-most2072 * operand.2073 *2074 * We only need parentheses if "expr" represents an operation.2075 *2076 * If op has a higher precedence than expr->u.op.op, then we need2077 * parentheses.2078 * If op and expr->u.op.op have the same precedence, but the operations2079 * are performed in an order that is different from the associativity,2080 * then we need parentheses.2081 *2082 * An and inside an or technically does not require parentheses,2083 * but some compilers complain about that, so we add them anyway.2084 *2085 * Computations such as "a / b * c" and "a % b + c" can be somewhat2086 * difficult to read, so we add parentheses for those as well.2087 */2088static int sub_expr_need_parens(enum isl_ast_expr_op_type op,2089 __isl_keep isl_ast_expr *expr, int left)2090{2091 if (expr->type != isl_ast_expr_op)2092 return 0;2093 2094 if (op_prec[expr->u.op.op] > op_prec[op])2095 return 1;2096 if (op_prec[expr->u.op.op] == op_prec[op] && left != op_left[op])2097 return 1;2098 2099 if (is_or(op) && is_and(expr->u.op.op))2100 return 1;2101 if (op == isl_ast_expr_op_mul && expr->u.op.op != isl_ast_expr_op_mul &&2102 op_prec[expr->u.op.op] == op_prec[op])2103 return 1;2104 if (is_add_sub(op) && is_div_mod(expr->u.op.op))2105 return 1;2106 2107 return 0;2108}2109 2110/* Print the subexpression at position "pos" of operation expression "expr"2111 * in C format.2112 * If "left" is set, then "expr" is the left-most operand.2113 */2114static __isl_give isl_printer *print_sub_expr_c(__isl_take isl_printer *p,2115 __isl_keep isl_ast_expr *expr, int pos, int left)2116{2117 int need_parens;2118 isl_ast_expr *arg;2119 2120 if (!expr)2121 return isl_printer_free(p);2122 2123 arg = isl_ast_expr_list_get_at(expr->u.op.args, pos);2124 need_parens = sub_expr_need_parens(expr->u.op.op, arg, left);2125 2126 if (need_parens)2127 p = isl_printer_print_str(p, "(");2128 p = print_ast_expr_c(p, arg);2129 if (need_parens)2130 p = isl_printer_print_str(p, ")");2131 2132 isl_ast_expr_free(arg);2133 2134 return p;2135}2136 2137#define isl_ast_expr_op_last isl_ast_expr_op_address_of2138 2139/* Data structure that holds the user-specified textual2140 * representations for the operators in C format.2141 * The entries are either NULL or copies of strings.2142 * A NULL entry means that the default name should be used.2143 */2144struct isl_ast_expr_op_names {2145 char *op_str[isl_ast_expr_op_last + 1];2146};2147 2148/* Create an empty struct isl_ast_expr_op_names.2149 */2150static void *create_names(isl_ctx *ctx)2151{2152 return isl_calloc_type(ctx, struct isl_ast_expr_op_names);2153}2154 2155/* Free a struct isl_ast_expr_op_names along with all memory2156 * owned by the struct.2157 */2158static void free_names(void *user)2159{2160 int i;2161 struct isl_ast_expr_op_names *names = user;2162 2163 if (!user)2164 return;2165 2166 for (i = 0; i <= isl_ast_expr_op_last; ++i)2167 free(names->op_str[i]);2168 free(user);2169}2170 2171/* Create an identifier that is used to store2172 * an isl_ast_expr_op_names note.2173 */2174static __isl_give isl_id *names_id(isl_ctx *ctx)2175{2176 return isl_id_alloc(ctx, "isl_ast_expr_op_type_names", NULL);2177}2178 2179/* Ensure that "p" has a note identified by "id".2180 * If there is no such note yet, then it is created by "note_create" and2181 * scheduled do be freed by "note_free".2182 */2183static __isl_give isl_printer *alloc_note(__isl_take isl_printer *p,2184 __isl_keep isl_id *id, void *(*note_create)(isl_ctx *),2185 void (*note_free)(void *))2186{2187 isl_ctx *ctx;2188 isl_id *note_id;2189 isl_bool has_note;2190 void *note;2191 2192 has_note = isl_printer_has_note(p, id);2193 if (has_note < 0)2194 return isl_printer_free(p);2195 if (has_note)2196 return p;2197 2198 ctx = isl_printer_get_ctx(p);2199 note = note_create(ctx);2200 if (!note)2201 return isl_printer_free(p);2202 note_id = isl_id_alloc(ctx, NULL, note);2203 if (!note_id)2204 note_free(note);2205 else2206 note_id = isl_id_set_free_user(note_id, note_free);2207 2208 p = isl_printer_set_note(p, isl_id_copy(id), note_id);2209 2210 return p;2211}2212 2213/* Ensure that "p" has an isl_ast_expr_op_names note identified by "id".2214 */2215static __isl_give isl_printer *alloc_names(__isl_take isl_printer *p,2216 __isl_keep isl_id *id)2217{2218 return alloc_note(p, id, &create_names, &free_names);2219}2220 2221/* Retrieve the note identified by "id" from "p".2222 * The note is assumed to exist.2223 */2224static void *get_note(__isl_keep isl_printer *p, __isl_keep isl_id *id)2225{2226 void *note;2227 2228 id = isl_printer_get_note(p, isl_id_copy(id));2229 note = isl_id_get_user(id);2230 isl_id_free(id);2231 2232 return note;2233}2234 2235/* Use "name" to print operations of type "type" to "p".2236 *2237 * Store the name in an isl_ast_expr_op_names note attached to "p", such that2238 * it can be retrieved by get_op_str.2239 */2240__isl_give isl_printer *isl_ast_expr_op_type_set_print_name(2241 __isl_take isl_printer *p, enum isl_ast_expr_op_type type,2242 __isl_keep const char *name)2243{2244 isl_id *id;2245 struct isl_ast_expr_op_names *names;2246 2247 if (!p)2248 return NULL;2249 if (type > isl_ast_expr_op_last)2250 isl_die(isl_printer_get_ctx(p), isl_error_invalid,2251 "invalid type", return isl_printer_free(p));2252 2253 id = names_id(isl_printer_get_ctx(p));2254 p = alloc_names(p, id);2255 names = get_note(p, id);2256 isl_id_free(id);2257 if (!names)2258 return isl_printer_free(p);2259 free(names->op_str[type]);2260 names->op_str[type] = strdup(name);2261 2262 return p;2263}2264 2265/* This is an alternative name for the function above.2266 */2267__isl_give isl_printer *isl_ast_op_type_set_print_name(2268 __isl_take isl_printer *p, enum isl_ast_expr_op_type type,2269 __isl_keep const char *name)2270{2271 return isl_ast_expr_op_type_set_print_name(p, type, name);2272}2273 2274/* Return the textual representation of "type" in C format.2275 *2276 * If there is a user-specified name in an isl_ast_expr_op_names note2277 * associated to "p", then return that.2278 * Otherwise, return the default name in op_str_c.2279 */2280static const char *get_op_str_c(__isl_keep isl_printer *p,2281 enum isl_ast_expr_op_type type)2282{2283 isl_id *id;2284 isl_bool has_names;2285 struct isl_ast_expr_op_names *names = NULL;2286 2287 id = names_id(isl_printer_get_ctx(p));2288 has_names = isl_printer_has_note(p, id);2289 if (has_names >= 0 && has_names)2290 names = get_note(p, id);2291 isl_id_free(id);2292 if (names && names->op_str[type])2293 return names->op_str[type];2294 return op_str_c[type];2295}2296 2297/* Print the expression at position "pos" in "list" in C format.2298 */2299static __isl_give isl_printer *print_at_c(__isl_take isl_printer *p,2300 __isl_keep isl_ast_expr_list *list, int pos)2301{2302 isl_ast_expr *expr;2303 2304 expr = isl_ast_expr_list_get_at(list, pos);2305 p = print_ast_expr_c(p, expr);2306 isl_ast_expr_free(expr);2307 2308 return p;2309}2310 2311/* Print a min or max reduction "expr" in C format.2312 */2313static __isl_give isl_printer *print_min_max_c(__isl_take isl_printer *p,2314 __isl_keep isl_ast_expr *expr)2315{2316 int i = 0;2317 isl_size n;2318 2319 n = isl_ast_expr_list_size(expr->u.op.args);2320 if (n < 0)2321 return isl_printer_free(p);2322 2323 for (i = 1; i < n; ++i) {2324 p = isl_printer_print_str(p, get_op_str_c(p, expr->u.op.op));2325 p = isl_printer_print_str(p, "(");2326 }2327 p = print_at_c(p, expr->u.op.args, 0);2328 for (i = 1; i < n; ++i) {2329 p = isl_printer_print_str(p, ", ");2330 p = print_at_c(p, expr->u.op.args, i);2331 p = isl_printer_print_str(p, ")");2332 }2333 2334 return p;2335}2336 2337/* Print a function call "expr" in C format.2338 *2339 * The first argument represents the function to be called.2340 */2341static __isl_give isl_printer *print_call_c(__isl_take isl_printer *p,2342 __isl_keep isl_ast_expr *expr)2343{2344 int i = 0;2345 isl_size n;2346 2347 n = isl_ast_expr_list_size(expr->u.op.args);2348 if (n < 0)2349 return isl_printer_free(p);2350 2351 p = print_at_c(p, expr->u.op.args, 0);2352 p = isl_printer_print_str(p, "(");2353 for (i = 1; i < n; ++i) {2354 if (i != 1)2355 p = isl_printer_print_str(p, ", ");2356 p = print_at_c(p, expr->u.op.args, i);2357 }2358 p = isl_printer_print_str(p, ")");2359 2360 return p;2361}2362 2363/* Print an array access "expr" in C format.2364 *2365 * The first argument represents the array being accessed.2366 */2367static __isl_give isl_printer *print_access_c(__isl_take isl_printer *p,2368 __isl_keep isl_ast_expr *expr)2369{2370 int i = 0;2371 isl_size n;2372 2373 n = isl_ast_expr_list_size(expr->u.op.args);2374 if (n < 0)2375 return isl_printer_free(p);2376 2377 p = print_at_c(p, expr->u.op.args, 0);2378 for (i = 1; i < n; ++i) {2379 p = isl_printer_print_str(p, "[");2380 p = print_at_c(p, expr->u.op.args, i);2381 p = isl_printer_print_str(p, "]");2382 }2383 2384 return p;2385}2386 2387/* Print "expr" to "p" in C format.2388 */2389static __isl_give isl_printer *print_ast_expr_c(__isl_take isl_printer *p,2390 __isl_keep isl_ast_expr *expr)2391{2392 isl_size n;2393 2394 if (!p)2395 return NULL;2396 if (!expr)2397 return isl_printer_free(p);2398 2399 switch (expr->type) {2400 case isl_ast_expr_op:2401 if (expr->u.op.op == isl_ast_expr_op_call) {2402 p = print_call_c(p, expr);2403 break;2404 }2405 if (expr->u.op.op == isl_ast_expr_op_access) {2406 p = print_access_c(p, expr);2407 break;2408 }2409 n = isl_ast_expr_list_size(expr->u.op.args);2410 if (n < 0)2411 return isl_printer_free(p);2412 if (n == 1) {2413 p = isl_printer_print_str(p,2414 get_op_str_c(p, expr->u.op.op));2415 p = print_sub_expr_c(p, expr, 0, 0);2416 break;2417 }2418 if (expr->u.op.op == isl_ast_expr_op_fdiv_q) {2419 const char *name;2420 2421 name = get_op_str_c(p, isl_ast_expr_op_fdiv_q);2422 p = isl_printer_print_str(p, name);2423 p = isl_printer_print_str(p, "(");2424 p = print_at_c(p, expr->u.op.args, 0);2425 p = isl_printer_print_str(p, ", ");2426 p = print_at_c(p, expr->u.op.args, 1);2427 p = isl_printer_print_str(p, ")");2428 break;2429 }2430 if (expr->u.op.op == isl_ast_expr_op_max ||2431 expr->u.op.op == isl_ast_expr_op_min) {2432 p = print_min_max_c(p, expr);2433 break;2434 }2435 if (expr->u.op.op == isl_ast_expr_op_cond ||2436 expr->u.op.op == isl_ast_expr_op_select) {2437 p = print_at_c(p, expr->u.op.args, 0);2438 p = isl_printer_print_str(p, " ? ");2439 p = print_at_c(p, expr->u.op.args, 1);2440 p = isl_printer_print_str(p, " : ");2441 p = print_at_c(p, expr->u.op.args, 2);2442 break;2443 }2444 if (n != 2)2445 isl_die(isl_printer_get_ctx(p), isl_error_internal,2446 "operation should have two arguments",2447 return isl_printer_free(p));2448 p = print_sub_expr_c(p, expr, 0, 1);2449 if (expr->u.op.op != isl_ast_expr_op_member)2450 p = isl_printer_print_str(p, " ");2451 p = isl_printer_print_str(p, get_op_str_c(p, expr->u.op.op));2452 if (expr->u.op.op != isl_ast_expr_op_member)2453 p = isl_printer_print_str(p, " ");2454 p = print_sub_expr_c(p, expr, 1, 0);2455 break;2456 case isl_ast_expr_id:2457 p = isl_printer_print_str(p, isl_id_get_name(expr->u.id));2458 break;2459 case isl_ast_expr_int:2460 p = isl_printer_print_val(p, expr->u.v);2461 break;2462 case isl_ast_expr_error:2463 break;2464 }2465 2466 return p;2467}2468 2469/* Textual representation of the isl_ast_expr_op_type elements2470 * for use in a YAML representation of an isl_ast_expr.2471 */2472static char *op_str[] = {2473 [isl_ast_expr_op_and] = "and",2474 [isl_ast_expr_op_and_then] = "and_then",2475 [isl_ast_expr_op_or] = "or",2476 [isl_ast_expr_op_or_else] = "or_else",2477 [isl_ast_expr_op_max] = "max",2478 [isl_ast_expr_op_min] = "min",2479 [isl_ast_expr_op_minus] = "minus",2480 [isl_ast_expr_op_add] = "add",2481 [isl_ast_expr_op_sub] = "sub",2482 [isl_ast_expr_op_mul] = "mul",2483 [isl_ast_expr_op_div] = "div",2484 [isl_ast_expr_op_fdiv_q] = "fdiv_q",2485 [isl_ast_expr_op_pdiv_q] = "pdiv_q",2486 [isl_ast_expr_op_pdiv_r] = "pdiv_r",2487 [isl_ast_expr_op_zdiv_r] = "zdiv_r",2488 [isl_ast_expr_op_cond] = "cond",2489 [isl_ast_expr_op_select] = "select",2490 [isl_ast_expr_op_eq] = "eq",2491 [isl_ast_expr_op_le] = "le",2492 [isl_ast_expr_op_lt] = "lt",2493 [isl_ast_expr_op_ge] = "ge",2494 [isl_ast_expr_op_gt] = "gt",2495 [isl_ast_expr_op_call] = "call",2496 [isl_ast_expr_op_access] = "access",2497 [isl_ast_expr_op_member] = "member",2498 [isl_ast_expr_op_address_of] = "address_of"2499};2500 2501static __isl_give isl_printer *print_ast_expr_isl(__isl_take isl_printer *p,2502 __isl_keep isl_ast_expr *expr);2503 2504/* Print the arguments of "expr" to "p" in isl format.2505 *2506 * If there are no arguments, then nothing needs to be printed.2507 * Otherwise add an "args" key to the current mapping with as value2508 * the list of arguments of "expr".2509 */2510static __isl_give isl_printer *print_arguments(__isl_take isl_printer *p,2511 __isl_keep isl_ast_expr *expr)2512{2513 int i;2514 isl_size n;2515 2516 n = isl_ast_expr_get_op_n_arg(expr);2517 if (n < 0)2518 return isl_printer_free(p);2519 if (n == 0)2520 return p;2521 2522 p = isl_printer_print_str(p, "args");2523 p = isl_printer_yaml_next(p);2524 p = isl_printer_yaml_start_sequence(p);2525 for (i = 0; i < n; ++i) {2526 isl_ast_expr *arg;2527 2528 arg = isl_ast_expr_get_op_arg(expr, i);2529 p = print_ast_expr_isl(p, arg);2530 isl_ast_expr_free(arg);2531 p = isl_printer_yaml_next(p);2532 }2533 p = isl_printer_yaml_end_sequence(p);2534 2535 return p;2536}2537 2538/* Textual representations of the YAML keys for an isl_ast_expr object.2539 */2540static char *expr_str[] = {2541 [isl_ast_expr_op] = "op",2542 [isl_ast_expr_id] = "id",2543 [isl_ast_expr_int] = "val",2544};2545 2546/* Print "expr" to "p" in isl format.2547 *2548 * In particular, print the isl_ast_expr as a YAML document.2549 */2550static __isl_give isl_printer *print_ast_expr_isl(__isl_take isl_printer *p,2551 __isl_keep isl_ast_expr *expr)2552{2553 enum isl_ast_expr_type type;2554 enum isl_ast_expr_op_type op;2555 isl_id *id;2556 isl_val *v;2557 2558 if (!expr)2559 return isl_printer_free(p);2560 2561 p = isl_printer_yaml_start_mapping(p);2562 type = isl_ast_expr_get_type(expr);2563 switch (type) {2564 case isl_ast_expr_error:2565 return isl_printer_free(p);2566 case isl_ast_expr_op:2567 op = isl_ast_expr_get_op_type(expr);2568 if (op == isl_ast_expr_op_error)2569 return isl_printer_free(p);2570 p = isl_printer_print_str(p, expr_str[type]);2571 p = isl_printer_yaml_next(p);2572 p = isl_printer_print_str(p, op_str[op]);2573 p = isl_printer_yaml_next(p);2574 p = print_arguments(p, expr);2575 break;2576 case isl_ast_expr_id:2577 p = isl_printer_print_str(p, expr_str[type]);2578 p = isl_printer_yaml_next(p);2579 id = isl_ast_expr_get_id(expr);2580 p = isl_printer_print_id(p, id);2581 isl_id_free(id);2582 break;2583 case isl_ast_expr_int:2584 p = isl_printer_print_str(p, expr_str[type]);2585 p = isl_printer_yaml_next(p);2586 v = isl_ast_expr_get_val(expr);2587 p = isl_printer_print_val(p, v);2588 isl_val_free(v);2589 break;2590 }2591 p = isl_printer_yaml_end_mapping(p);2592 2593 return p;2594}2595 2596/* Print "expr" to "p".2597 *2598 * Only an isl and a C format are supported.2599 */2600__isl_give isl_printer *isl_printer_print_ast_expr(__isl_take isl_printer *p,2601 __isl_keep isl_ast_expr *expr)2602{2603 int format;2604 2605 if (!p)2606 return NULL;2607 2608 format = isl_printer_get_output_format(p);2609 switch (format) {2610 case ISL_FORMAT_ISL:2611 p = print_ast_expr_isl(p, expr);2612 break;2613 case ISL_FORMAT_C:2614 p = print_ast_expr_c(p, expr);2615 break;2616 default:2617 isl_die(isl_printer_get_ctx(p), isl_error_unsupported,2618 "output format not supported for ast_expr",2619 return isl_printer_free(p));2620 }2621 2622 return p;2623}2624 2625#undef KEY2626#define KEY enum isl_ast_expr_op_type2627#undef KEY_ERROR2628#define KEY_ERROR isl_ast_expr_op_error2629#undef KEY_END2630#define KEY_END (isl_ast_expr_op_address_of + 1)2631#undef KEY_STR2632#define KEY_STR op_str2633#undef KEY_EXTRACT2634#define KEY_EXTRACT extract_op_type2635#undef KEY_GET2636#define KEY_GET get_op_type2637#include "extract_key.c"2638 2639/* Return the next token, which is assumed to be a key in a YAML mapping,2640 * from "s" as a string.2641 */2642static __isl_give char *next_key(__isl_keep isl_stream *s)2643{2644 struct isl_token *tok;2645 char *str;2646 isl_ctx *ctx;2647 2648 if (!s)2649 return NULL;2650 tok = isl_stream_next_token(s);2651 if (!tok) {2652 isl_stream_error(s, NULL, "unexpected EOF");2653 return NULL;2654 }2655 ctx = isl_stream_get_ctx(s);2656 str = isl_token_get_str(ctx, tok);2657 isl_token_free(tok);2658 return str;2659}2660 2661/* Remove the next token, which is assumed to be the key "expected"2662 * in a YAML mapping, from "s" and move to the corresponding value.2663 */2664static isl_stat eat_key(__isl_keep isl_stream *s, const char *expected)2665{2666 char *str;2667 int ok;2668 2669 str = next_key(s);2670 if (!str)2671 return isl_stat_error;2672 ok = !strcmp(str, expected);2673 free(str);2674 2675 if (!ok) {2676 isl_stream_error(s, NULL, "expecting different key");2677 return isl_stat_error;2678 }2679 2680 if (isl_stream_yaml_next(s) < 0)2681 return isl_stat_error;2682 2683 return isl_stat_ok;2684}2685 2686#undef EL_BASE2687#define EL_BASE ast_expr2688 2689#include <isl_list_read_yaml_templ.c>2690 2691/* Read an isl_ast_expr object of type isl_ast_expr_op from "s",2692 * where the "op" key has already been read by the caller.2693 *2694 * Read the operation type and the arguments and2695 * return the corresponding isl_ast_expr object.2696 */2697static __isl_give isl_ast_expr *read_op(__isl_keep isl_stream *s)2698{2699 enum isl_ast_expr_op_type op;2700 isl_ast_expr_list *list;2701 2702 op = get_op_type(s);2703 if (op < 0)2704 return NULL;2705 if (isl_stream_yaml_next(s) < 0)2706 return NULL;2707 if (eat_key(s, "args") < 0)2708 return NULL;2709 2710 list = isl_stream_yaml_read_ast_expr_list(s);2711 2712 return alloc_op(op, list);2713}2714 2715/* Read an isl_ast_expr object of type isl_ast_expr_id from "s",2716 * where the "id" key has already been read by the caller.2717 */2718static __isl_give isl_ast_expr *read_id(__isl_keep isl_stream *s)2719{2720 return isl_ast_expr_from_id(isl_stream_read_id(s));2721}2722 2723/* Read an isl_ast_expr object of type isl_ast_expr_int from "s",2724 * where the "val" key has already been read by the caller.2725 */2726static __isl_give isl_ast_expr *read_int(__isl_keep isl_stream *s)2727{2728 return isl_ast_expr_from_val(isl_stream_read_val(s));2729}2730 2731#undef KEY2732#define KEY enum isl_ast_expr_type2733#undef KEY_ERROR2734#define KEY_ERROR isl_ast_expr_error2735#undef KEY_END2736#define KEY_END (isl_ast_expr_int + 1)2737#undef KEY_STR2738#define KEY_STR expr_str2739#undef KEY_EXTRACT2740#define KEY_EXTRACT extract_expr_type2741#undef KEY_GET2742#define KEY_GET get_expr_type2743#include "extract_key.c"2744 2745/* Read an isl_ast_expr object from "s".2746 *2747 * The keys in the YAML mapping are assumed to appear2748 * in the same order as the one in which they are printed2749 * by print_ast_expr_isl.2750 * In particular, the isl_ast_expr_op type, which is the only one2751 * with more than one element, is identified by the "op" key and2752 * not by the "args" key.2753 */2754__isl_give isl_ast_expr *isl_stream_read_ast_expr(__isl_keep isl_stream *s)2755{2756 enum isl_ast_expr_type type;2757 isl_bool more;2758 isl_ast_expr *expr;2759 2760 if (isl_stream_yaml_read_start_mapping(s))2761 return NULL;2762 more = isl_stream_yaml_next(s);2763 if (more < 0)2764 return NULL;2765 if (!more) {2766 isl_stream_error(s, NULL, "missing key");2767 return NULL;2768 }2769 2770 type = get_expr_type(s);2771 if (type < 0)2772 return NULL;2773 if (isl_stream_yaml_next(s) < 0)2774 return NULL;2775 switch (type) {2776 case isl_ast_expr_op:2777 expr = read_op(s);2778 break;2779 case isl_ast_expr_id:2780 expr = read_id(s);2781 break;2782 case isl_ast_expr_int:2783 expr = read_int(s);2784 break;2785 case isl_ast_expr_error:2786 return NULL;2787 }2788 2789 if (isl_stream_yaml_read_end_mapping(s) < 0)2790 return isl_ast_expr_free(expr);2791 2792 return expr;2793}2794 2795static __isl_give isl_printer *print_ast_node_isl(__isl_take isl_printer *p,2796 __isl_keep isl_ast_node *node);2797 2798/* Print a YAML sequence containing the entries in "list" to "p".2799 */2800static __isl_give isl_printer *print_ast_node_list(__isl_take isl_printer *p,2801 __isl_keep isl_ast_node_list *list)2802{2803 int i;2804 isl_size n;2805 2806 n = isl_ast_node_list_n_ast_node(list);2807 if (n < 0)2808 return isl_printer_free(p);2809 2810 p = isl_printer_yaml_start_sequence(p);2811 for (i = 0; i < n; ++i) {2812 isl_ast_node *node;2813 2814 node = isl_ast_node_list_get_ast_node(list, i);2815 p = print_ast_node_isl(p, node);2816 isl_ast_node_free(node);2817 p = isl_printer_yaml_next(p);2818 }2819 p = isl_printer_yaml_end_sequence(p);2820 2821 return p;2822}2823 2824/* Print "node" to "p" in "isl format".2825 *2826 * In particular, print the isl_ast_node as a YAML document.2827 */2828static __isl_give isl_printer *print_ast_node_isl(__isl_take isl_printer *p,2829 __isl_keep isl_ast_node *node)2830{2831 switch (node->type) {2832 case isl_ast_node_for:2833 p = isl_printer_yaml_start_mapping(p);2834 p = isl_printer_print_str(p, "iterator");2835 p = isl_printer_yaml_next(p);2836 p = isl_printer_print_ast_expr(p, node->u.f.iterator);2837 p = isl_printer_yaml_next(p);2838 if (node->u.f.degenerate) {2839 p = isl_printer_print_str(p, "value");2840 p = isl_printer_yaml_next(p);2841 p = isl_printer_print_ast_expr(p, node->u.f.init);2842 p = isl_printer_yaml_next(p);2843 } else {2844 p = isl_printer_print_str(p, "init");2845 p = isl_printer_yaml_next(p);2846 p = isl_printer_print_ast_expr(p, node->u.f.init);2847 p = isl_printer_yaml_next(p);2848 p = isl_printer_print_str(p, "cond");2849 p = isl_printer_yaml_next(p);2850 p = isl_printer_print_ast_expr(p, node->u.f.cond);2851 p = isl_printer_yaml_next(p);2852 p = isl_printer_print_str(p, "inc");2853 p = isl_printer_yaml_next(p);2854 p = isl_printer_print_ast_expr(p, node->u.f.inc);2855 p = isl_printer_yaml_next(p);2856 }2857 if (node->u.f.body) {2858 p = isl_printer_print_str(p, "body");2859 p = isl_printer_yaml_next(p);2860 p = isl_printer_print_ast_node(p, node->u.f.body);2861 p = isl_printer_yaml_next(p);2862 }2863 p = isl_printer_yaml_end_mapping(p);2864 break;2865 case isl_ast_node_mark:2866 p = isl_printer_yaml_start_mapping(p);2867 p = isl_printer_print_str(p, "mark");2868 p = isl_printer_yaml_next(p);2869 p = isl_printer_print_id(p, node->u.m.mark);2870 p = isl_printer_yaml_next(p);2871 p = isl_printer_print_str(p, "node");2872 p = isl_printer_yaml_next(p);2873 p = isl_printer_print_ast_node(p, node->u.m.node);2874 p = isl_printer_yaml_end_mapping(p);2875 break;2876 case isl_ast_node_user:2877 p = isl_printer_yaml_start_mapping(p);2878 p = isl_printer_print_str(p, "user");2879 p = isl_printer_yaml_next(p);2880 p = isl_printer_print_ast_expr(p, node->u.e.expr);2881 p = isl_printer_yaml_end_mapping(p);2882 break;2883 case isl_ast_node_if:2884 p = isl_printer_yaml_start_mapping(p);2885 p = isl_printer_print_str(p, "guard");2886 p = isl_printer_yaml_next(p);2887 p = isl_printer_print_ast_expr(p, node->u.i.guard);2888 p = isl_printer_yaml_next(p);2889 if (node->u.i.then) {2890 p = isl_printer_print_str(p, "then");2891 p = isl_printer_yaml_next(p);2892 p = isl_printer_print_ast_node(p, node->u.i.then);2893 p = isl_printer_yaml_next(p);2894 }2895 if (node->u.i.else_node) {2896 p = isl_printer_print_str(p, "else");2897 p = isl_printer_yaml_next(p);2898 p = isl_printer_print_ast_node(p, node->u.i.else_node);2899 }2900 p = isl_printer_yaml_end_mapping(p);2901 break;2902 case isl_ast_node_block:2903 p = print_ast_node_list(p, node->u.b.children);2904 break;2905 case isl_ast_node_error:2906 break;2907 }2908 return p;2909}2910 2911/* Do we need to print a block around the body "node" of a for or if node?2912 *2913 * If the node is a block, then we need to print a block.2914 * Also if the node is a degenerate for then we will print it as2915 * an assignment followed by the body of the for loop, so we need a block2916 * as well.2917 * If the node is an if node with an else, then we print a block2918 * to avoid spurious dangling else warnings emitted by some compilers.2919 * If the node is a mark, then in principle, we would have to check2920 * the child of the mark node. However, even if the child would not2921 * require us to print a block, for readability it is probably best2922 * to print a block anyway.2923 * If the ast_always_print_block option has been set, then we print a block.2924 */2925static int need_block(__isl_keep isl_ast_node *node)2926{2927 isl_ctx *ctx;2928 2929 if (node->type == isl_ast_node_block)2930 return 1;2931 if (node->type == isl_ast_node_for && node->u.f.degenerate)2932 return 1;2933 if (node->type == isl_ast_node_if && node->u.i.else_node)2934 return 1;2935 if (node->type == isl_ast_node_mark)2936 return 1;2937 2938 ctx = isl_ast_node_get_ctx(node);2939 return isl_options_get_ast_always_print_block(ctx);2940}2941 2942static __isl_give isl_printer *print_ast_node_c(__isl_take isl_printer *p,2943 __isl_keep isl_ast_node *node,2944 __isl_keep isl_ast_print_options *options, int in_block, int in_list);2945static __isl_give isl_printer *print_if_c(__isl_take isl_printer *p,2946 __isl_keep isl_ast_node *node,2947 __isl_keep isl_ast_print_options *options, int new_line,2948 int force_block);2949 2950/* Print the body "node" of a for or if node.2951 * If "else_node" is set, then it is printed as well.2952 * If "force_block" is set, then print out the body as a block.2953 *2954 * We first check if we need to print out a block.2955 * We always print out a block if there is an else node to make2956 * sure that the else node is matched to the correct if node.2957 * For consistency, the corresponding else node is also printed as a block.2958 *2959 * If the else node is itself an if, then we print it as2960 *2961 * } else if (..) {2962 * }2963 *2964 * Otherwise the else node is printed as2965 *2966 * } else {2967 * node2968 * }2969 */2970static __isl_give isl_printer *print_body_c(__isl_take isl_printer *p,2971 __isl_keep isl_ast_node *node, __isl_keep isl_ast_node *else_node,2972 __isl_keep isl_ast_print_options *options, int force_block)2973{2974 if (!node)2975 return isl_printer_free(p);2976 2977 if (!force_block && !else_node && !need_block(node)) {2978 p = isl_printer_end_line(p);2979 p = isl_printer_indent(p, 2);2980 p = isl_ast_node_print(node, p,2981 isl_ast_print_options_copy(options));2982 p = isl_printer_indent(p, -2);2983 return p;2984 }2985 2986 p = isl_printer_print_str(p, " {");2987 p = isl_printer_end_line(p);2988 p = isl_printer_indent(p, 2);2989 p = print_ast_node_c(p, node, options, 1, 0);2990 p = isl_printer_indent(p, -2);2991 p = isl_printer_start_line(p);2992 p = isl_printer_print_str(p, "}");2993 if (else_node) {2994 if (else_node->type == isl_ast_node_if) {2995 p = isl_printer_print_str(p, " else ");2996 p = print_if_c(p, else_node, options, 0, 1);2997 } else {2998 p = isl_printer_print_str(p, " else");2999 p = print_body_c(p, else_node, NULL, options, 1);3000 }3001 } else3002 p = isl_printer_end_line(p);3003 3004 return p;3005}3006 3007/* Print the start of a compound statement.3008 */3009static __isl_give isl_printer *start_block(__isl_take isl_printer *p)3010{3011 p = isl_printer_start_line(p);3012 p = isl_printer_print_str(p, "{");3013 p = isl_printer_end_line(p);3014 p = isl_printer_indent(p, 2);3015 3016 return p;3017}3018 3019/* Print the end of a compound statement.3020 */3021static __isl_give isl_printer *end_block(__isl_take isl_printer *p)3022{3023 p = isl_printer_indent(p, -2);3024 p = isl_printer_start_line(p);3025 p = isl_printer_print_str(p, "}");3026 p = isl_printer_end_line(p);3027 3028 return p;3029}3030 3031/* Print the for node "node".3032 *3033 * If the for node is degenerate, it is printed as3034 *3035 * type iterator = init;3036 * body3037 *3038 * Otherwise, it is printed as3039 *3040 * for (type iterator = init; cond; iterator += inc)3041 * body3042 *3043 * "in_block" is set if we are currently inside a block.3044 * "in_list" is set if the current node is not alone in the block.3045 * If we are not in a block or if the current not is not alone in the block3046 * then we print a block around a degenerate for loop such that the variable3047 * declaration will not conflict with any potential other declaration3048 * of the same variable.3049 */3050static __isl_give isl_printer *print_for_c(__isl_take isl_printer *p,3051 __isl_keep isl_ast_node *node,3052 __isl_keep isl_ast_print_options *options, int in_block, int in_list)3053{3054 isl_id *id;3055 const char *name;3056 const char *type;3057 3058 type = isl_options_get_ast_iterator_type(isl_printer_get_ctx(p));3059 if (!node->u.f.degenerate) {3060 id = isl_ast_expr_get_id(node->u.f.iterator);3061 name = isl_id_get_name(id);3062 isl_id_free(id);3063 p = isl_printer_start_line(p);3064 p = isl_printer_print_str(p, "for (");3065 p = isl_printer_print_str(p, type);3066 p = isl_printer_print_str(p, " ");3067 p = isl_printer_print_str(p, name);3068 p = isl_printer_print_str(p, " = ");3069 p = isl_printer_print_ast_expr(p, node->u.f.init);3070 p = isl_printer_print_str(p, "; ");3071 p = isl_printer_print_ast_expr(p, node->u.f.cond);3072 p = isl_printer_print_str(p, "; ");3073 p = isl_printer_print_str(p, name);3074 p = isl_printer_print_str(p, " += ");3075 p = isl_printer_print_ast_expr(p, node->u.f.inc);3076 p = isl_printer_print_str(p, ")");3077 p = print_body_c(p, node->u.f.body, NULL, options, 0);3078 } else {3079 id = isl_ast_expr_get_id(node->u.f.iterator);3080 name = isl_id_get_name(id);3081 isl_id_free(id);3082 if (!in_block || in_list)3083 p = start_block(p);3084 p = isl_printer_start_line(p);3085 p = isl_printer_print_str(p, type);3086 p = isl_printer_print_str(p, " ");3087 p = isl_printer_print_str(p, name);3088 p = isl_printer_print_str(p, " = ");3089 p = isl_printer_print_ast_expr(p, node->u.f.init);3090 p = isl_printer_print_str(p, ";");3091 p = isl_printer_end_line(p);3092 p = print_ast_node_c(p, node->u.f.body, options, 1, 0);3093 if (!in_block || in_list)3094 p = end_block(p);3095 }3096 3097 return p;3098}3099 3100/* Print the if node "node".3101 * If "new_line" is set then the if node should be printed on a new line.3102 * If "force_block" is set, then print out the body as a block.3103 */3104static __isl_give isl_printer *print_if_c(__isl_take isl_printer *p,3105 __isl_keep isl_ast_node *node,3106 __isl_keep isl_ast_print_options *options, int new_line,3107 int force_block)3108{3109 if (new_line)3110 p = isl_printer_start_line(p);3111 p = isl_printer_print_str(p, "if (");3112 p = isl_printer_print_ast_expr(p, node->u.i.guard);3113 p = isl_printer_print_str(p, ")");3114 p = print_body_c(p, node->u.i.then, node->u.i.else_node, options,3115 force_block);3116 3117 return p;3118}3119 3120/* Print the "node" to "p".3121 *3122 * "in_block" is set if we are currently inside a block.3123 * If so, we do not print a block around the children of a block node.3124 * We do this to avoid an extra block around the body of a degenerate3125 * for node.3126 *3127 * "in_list" is set if the current node is not alone in the block.3128 */3129static __isl_give isl_printer *print_ast_node_c(__isl_take isl_printer *p,3130 __isl_keep isl_ast_node *node,3131 __isl_keep isl_ast_print_options *options, int in_block, int in_list)3132{3133 switch (node->type) {3134 case isl_ast_node_for:3135 if (options->print_for)3136 return options->print_for(p,3137 isl_ast_print_options_copy(options),3138 node, options->print_for_user);3139 p = print_for_c(p, node, options, in_block, in_list);3140 break;3141 case isl_ast_node_if:3142 p = print_if_c(p, node, options, 1, 0);3143 break;3144 case isl_ast_node_block:3145 if (!in_block)3146 p = start_block(p);3147 p = isl_ast_node_list_print(node->u.b.children, p, options);3148 if (!in_block)3149 p = end_block(p);3150 break;3151 case isl_ast_node_mark:3152 p = isl_printer_start_line(p);3153 p = isl_printer_print_str(p, "// ");3154 p = isl_printer_print_str(p, isl_id_get_name(node->u.m.mark));3155 p = isl_printer_end_line(p);3156 p = print_ast_node_c(p, node->u.m.node, options, 0, in_list);3157 break;3158 case isl_ast_node_user:3159 if (options->print_user)3160 return options->print_user(p,3161 isl_ast_print_options_copy(options),3162 node, options->print_user_user);3163 p = isl_printer_start_line(p);3164 p = isl_printer_print_ast_expr(p, node->u.e.expr);3165 p = isl_printer_print_str(p, ";");3166 p = isl_printer_end_line(p);3167 break;3168 case isl_ast_node_error:3169 break;3170 }3171 return p;3172}3173 3174/* Print the for node "node" to "p".3175 */3176__isl_give isl_printer *isl_ast_node_for_print(__isl_keep isl_ast_node *node,3177 __isl_take isl_printer *p, __isl_take isl_ast_print_options *options)3178{3179 if (isl_ast_node_check_for(node) < 0 || !options)3180 goto error;3181 p = print_for_c(p, node, options, 0, 0);3182 isl_ast_print_options_free(options);3183 return p;3184error:3185 isl_ast_print_options_free(options);3186 isl_printer_free(p);3187 return NULL;3188}3189 3190/* Print the if node "node" to "p".3191 */3192__isl_give isl_printer *isl_ast_node_if_print(__isl_keep isl_ast_node *node,3193 __isl_take isl_printer *p, __isl_take isl_ast_print_options *options)3194{3195 if (isl_ast_node_check_if(node) < 0 || !options)3196 goto error;3197 p = print_if_c(p, node, options, 1, 0);3198 isl_ast_print_options_free(options);3199 return p;3200error:3201 isl_ast_print_options_free(options);3202 isl_printer_free(p);3203 return NULL;3204}3205 3206/* Print "node" to "p".3207 *3208 * "node" is assumed to be either the outermost node in an AST or3209 * a node that is known not to be a block.3210 * If "node" is a block (and is therefore outermost) and3211 * if the ast_print_outermost_block options is not set,3212 * then act as if the printing occurs inside a block, such3213 * that no "extra" block will get printed.3214 */3215__isl_give isl_printer *isl_ast_node_print(__isl_keep isl_ast_node *node,3216 __isl_take isl_printer *p, __isl_take isl_ast_print_options *options)3217{3218 int in_block = 0;3219 3220 if (!options || !node)3221 goto error;3222 if (node->type == isl_ast_node_block) {3223 isl_ctx *ctx;3224 3225 ctx = isl_ast_node_get_ctx(node);3226 in_block = !isl_options_get_ast_print_outermost_block(ctx);3227 }3228 p = print_ast_node_c(p, node, options, in_block, 0);3229 isl_ast_print_options_free(options);3230 return p;3231error:3232 isl_ast_print_options_free(options);3233 isl_printer_free(p);3234 return NULL;3235}3236 3237/* Print "node" to "p".3238 */3239__isl_give isl_printer *isl_printer_print_ast_node(__isl_take isl_printer *p,3240 __isl_keep isl_ast_node *node)3241{3242 int format;3243 isl_ast_print_options *options;3244 3245 if (!p)3246 return NULL;3247 3248 format = isl_printer_get_output_format(p);3249 switch (format) {3250 case ISL_FORMAT_ISL:3251 p = print_ast_node_isl(p, node);3252 break;3253 case ISL_FORMAT_C:3254 options = isl_ast_print_options_alloc(isl_printer_get_ctx(p));3255 p = isl_ast_node_print(node, p, options);3256 break;3257 default:3258 isl_die(isl_printer_get_ctx(p), isl_error_unsupported,3259 "output format not supported for ast_node",3260 return isl_printer_free(p));3261 }3262 3263 return p;3264}3265 3266/* Print the list of nodes "list" to "p".3267 */3268__isl_give isl_printer *isl_ast_node_list_print(3269 __isl_keep isl_ast_node_list *list, __isl_take isl_printer *p,3270 __isl_keep isl_ast_print_options *options)3271{3272 int i;3273 3274 if (!p || !list || !options)3275 return isl_printer_free(p);3276 3277 for (i = 0; i < list->n; ++i)3278 p = print_ast_node_c(p, list->p[i], options, 1, 1);3279 3280 return p;3281}3282 3283/* Is the next token on "s" the start of a YAML sequence3284 * (rather than a YAML mapping)?3285 *3286 * A YAML sequence starts with either a '[' or a '-', depending on the format.3287 */3288static isl_bool next_is_sequence(__isl_keep isl_stream *s)3289{3290 struct isl_token *tok;3291 int type;3292 int seq;3293 3294 tok = isl_stream_next_token(s);3295 if (!tok)3296 return isl_bool_error;3297 type = isl_token_get_type(tok);3298 seq = type == '[' || type == '-';3299 isl_stream_push_token(s, tok);3300 3301 return isl_bool_ok(seq);3302}3303 3304#undef EL_BASE3305#define EL_BASE ast_node3306 3307#include <isl_list_read_yaml_templ.c>3308 3309/* Read an isl_ast_node object of type isl_ast_node_block from "s".3310 */3311static __isl_give isl_ast_node *read_block(__isl_keep isl_stream *s)3312{3313 isl_ast_node_list *children;3314 3315 children = isl_stream_yaml_read_ast_node_list(s);3316 return isl_ast_node_block_from_children(children);3317}3318 3319/* Textual representation of the first YAML key used3320 * while printing an isl_ast_node of a given type.3321 *3322 * An isl_ast_node of type isl_ast_node_block is not printed3323 * as a YAML mapping and is therefore assigned a dummy key.3324 */3325static char *node_first_str[] = {3326 [isl_ast_node_for] = "iterator",3327 [isl_ast_node_mark] = "mark",3328 [isl_ast_node_user] = "user",3329 [isl_ast_node_if] = "guard",3330 [isl_ast_node_block] = "",3331};3332 3333#undef KEY3334#define KEY enum isl_ast_node_type3335#undef KEY_ERROR3336#define KEY_ERROR isl_ast_node_error3337#undef KEY_END3338#define KEY_END (isl_ast_node_user + 1)3339#undef KEY_STR3340#define KEY_STR node_first_str3341#undef KEY_EXTRACT3342#define KEY_EXTRACT extract_node_type3343#undef KEY_GET3344#define KEY_GET get_node_type3345#include "extract_key.c"3346 3347static __isl_give isl_ast_node *read_body(__isl_keep isl_stream *s,3348 __isl_take isl_ast_node *node)3349{3350 if (eat_key(s, "body") < 0)3351 return isl_ast_node_free(node);3352 node = isl_ast_node_for_set_body(node, isl_stream_read_ast_node(s));3353 if (isl_stream_yaml_next(s) < 0)3354 return isl_ast_node_free(node);3355 return node;3356}3357 3358/* Read an isl_ast_node object of type isl_ast_node_for from "s",3359 * where the initial "iterator" key has already been read by the caller.3360 *3361 * If the initial value is printed as the value of the key "value",3362 * then the for-loop is degenerate and can at most have3363 * a further "body" element.3364 * Otherwise, the for-loop also has "cond" and "inc" elements.3365 */3366static __isl_give isl_ast_node *read_for(__isl_keep isl_stream *s)3367{3368 isl_id *id;3369 isl_ast_expr *expr;3370 isl_ast_node *node;3371 char *key;3372 isl_bool more;3373 int is_value, is_init;3374 3375 expr = isl_stream_read_ast_expr(s);3376 id = isl_ast_expr_id_get_id(expr);3377 isl_ast_expr_free(expr);3378 if (!id)3379 return NULL;3380 if (isl_stream_yaml_next(s) < 0)3381 id = isl_id_free(id);3382 3383 node = isl_ast_node_alloc_for(id);3384 3385 key = next_key(s);3386 if (!key)3387 return isl_ast_node_free(node);3388 is_value = !strcmp(key, "value");3389 is_init = !strcmp(key, "init");3390 free(key);3391 if (!is_value && !is_init)3392 isl_die(isl_stream_get_ctx(s), isl_error_invalid,3393 "unexpected key", return isl_ast_node_free(node));3394 if (isl_stream_yaml_next(s) < 0)3395 return isl_ast_node_free(node);3396 node = isl_ast_node_for_set_init(node, isl_stream_read_ast_expr(s));3397 if ((more = isl_stream_yaml_next(s)) < 0)3398 return isl_ast_node_free(node);3399 if (is_value) {3400 node = isl_ast_node_for_mark_degenerate(node);3401 if (more)3402 node = read_body(s, node);3403 return node;3404 }3405 3406 if (eat_key(s, "cond") < 0)3407 return isl_ast_node_free(node);3408 node = isl_ast_node_for_set_cond(node, isl_stream_read_ast_expr(s));3409 if (isl_stream_yaml_next(s) < 0)3410 return isl_ast_node_free(node);3411 if (eat_key(s, "inc") < 0)3412 return isl_ast_node_free(node);3413 node = isl_ast_node_for_set_inc(node, isl_stream_read_ast_expr(s));3414 if ((more = isl_stream_yaml_next(s)) < 0)3415 return isl_ast_node_free(node);3416 3417 if (more)3418 node = read_body(s, node);3419 3420 return node;3421}3422 3423/* Read an isl_ast_node object of type isl_ast_node_mark from "s",3424 * where the initial "mark" key has already been read by the caller.3425 */3426static __isl_give isl_ast_node *read_mark(__isl_keep isl_stream *s)3427{3428 isl_id *id;3429 isl_ast_node *node;3430 3431 id = isl_stream_read_id(s);3432 if (!id)3433 return NULL;3434 if (isl_stream_yaml_next(s) < 0)3435 goto error;3436 if (eat_key(s, "node") < 0)3437 goto error;3438 node = isl_stream_read_ast_node(s);3439 node = isl_ast_node_alloc_mark(id, node);3440 if (isl_stream_yaml_next(s) < 0)3441 return isl_ast_node_free(node);3442 return node;3443error:3444 isl_id_free(id);3445 return NULL;3446}3447 3448/* Read an isl_ast_node object of type isl_ast_node_user from "s",3449 * where the "user" key has already been read by the caller.3450 */3451static __isl_give isl_ast_node *read_user(__isl_keep isl_stream *s)3452{3453 isl_ast_node *node;3454 3455 node = isl_ast_node_alloc_user(isl_stream_read_ast_expr(s));3456 if (isl_stream_yaml_next(s) < 0)3457 return isl_ast_node_free(node);3458 return node;3459}3460 3461/* Read an isl_ast_node object of type isl_ast_node_if from "s",3462 * where the initial "guard" key has already been read by the caller.3463 */3464static __isl_give isl_ast_node *read_if(__isl_keep isl_stream *s)3465{3466 isl_bool more;3467 isl_ast_node *node;3468 3469 node = isl_ast_node_alloc_if(isl_stream_read_ast_expr(s));3470 if ((more = isl_stream_yaml_next(s)) < 0)3471 return isl_ast_node_free(node);3472 if (!more)3473 return node;3474 3475 if (eat_key(s, "then") < 0)3476 return isl_ast_node_free(node);3477 node = isl_ast_node_if_set_then(node, isl_stream_read_ast_node(s));3478 if ((more = isl_stream_yaml_next(s)) < 0)3479 return isl_ast_node_free(node);3480 if (!more)3481 return node;3482 3483 if (eat_key(s, "else") < 0)3484 return isl_ast_node_free(node);3485 node = isl_ast_node_if_set_else_node(node, isl_stream_read_ast_node(s));3486 if (isl_stream_yaml_next(s) < 0)3487 return isl_ast_node_free(node);3488 3489 return node;3490}3491 3492/* Read an isl_ast_node object from "s".3493 *3494 * A block node is printed as a YAML sequence by print_ast_node_isl.3495 * Every other node type is printed as a YAML mapping.3496 *3497 * First check if the next element is a sequence and if so,3498 * read a block node.3499 * Otherwise, read a node based on the first mapping key3500 * that is used to print a node type.3501 * Note that the keys in the YAML mapping are assumed to appear3502 * in the same order as the one in which they are printed3503 * by print_ast_node_isl.3504 */3505__isl_give isl_ast_node *isl_stream_read_ast_node(__isl_keep isl_stream *s)3506{3507 enum isl_ast_node_type type;3508 isl_bool more;3509 isl_bool seq;3510 isl_ast_node *node;3511 3512 seq = next_is_sequence(s);3513 if (seq < 0)3514 return NULL;3515 if (seq)3516 return read_block(s);3517 3518 if (isl_stream_yaml_read_start_mapping(s))3519 return NULL;3520 more = isl_stream_yaml_next(s);3521 if (more < 0)3522 return NULL;3523 if (!more) {3524 isl_stream_error(s, NULL, "missing key");3525 return NULL;3526 }3527 3528 type = get_node_type(s);3529 if (type < 0)3530 return NULL;3531 if (isl_stream_yaml_next(s) < 0)3532 return NULL;3533 3534 switch (type) {3535 case isl_ast_node_block:3536 isl_die(isl_stream_get_ctx(s), isl_error_internal,3537 "block cannot be detected as mapping",3538 return NULL);3539 case isl_ast_node_for:3540 node = read_for(s);3541 break;3542 case isl_ast_node_mark:3543 node = read_mark(s);3544 break;3545 case isl_ast_node_user:3546 node = read_user(s);3547 break;3548 case isl_ast_node_if:3549 node = read_if(s);3550 break;3551 case isl_ast_node_error:3552 return NULL;3553 }3554 3555 if (isl_stream_yaml_read_end_mapping(s) < 0)3556 return isl_ast_node_free(node);3557 3558 return node;3559}3560 3561#define ISL_AST_MACRO_FDIV_Q (1 << 0)3562#define ISL_AST_MACRO_MIN (1 << 1)3563#define ISL_AST_MACRO_MAX (1 << 2)3564#define ISL_AST_MACRO_ALL (ISL_AST_MACRO_FDIV_Q | \3565 ISL_AST_MACRO_MIN | \3566 ISL_AST_MACRO_MAX)3567 3568static int ast_expr_required_macros(__isl_keep isl_ast_expr *expr, int macros);3569 3570/* Wrapper around ast_expr_required_macros for use3571 * as an isl_ast_expr_list_foreach callback.3572 */3573static isl_stat entry_required_macros(__isl_take isl_ast_expr *expr, void *user)3574{3575 int *macros = user;3576 3577 *macros = ast_expr_required_macros(expr, *macros);3578 isl_ast_expr_free(expr);3579 3580 return isl_stat_ok;3581}3582 3583/* If "expr" contains an isl_ast_expr_op_min, isl_ast_expr_op_max or3584 * isl_ast_expr_op_fdiv_q then set the corresponding bit in "macros".3585 */3586static int ast_expr_required_macros(__isl_keep isl_ast_expr *expr, int macros)3587{3588 if (macros == ISL_AST_MACRO_ALL)3589 return macros;3590 3591 if (expr->type != isl_ast_expr_op)3592 return macros;3593 3594 if (expr->u.op.op == isl_ast_expr_op_min)3595 macros |= ISL_AST_MACRO_MIN;3596 if (expr->u.op.op == isl_ast_expr_op_max)3597 macros |= ISL_AST_MACRO_MAX;3598 if (expr->u.op.op == isl_ast_expr_op_fdiv_q)3599 macros |= ISL_AST_MACRO_FDIV_Q;3600 3601 isl_ast_expr_list_foreach(expr->u.op.args,3602 &entry_required_macros, ¯os);3603 3604 return macros;3605}3606 3607static int ast_node_list_required_macros(__isl_keep isl_ast_node_list *list,3608 int macros);3609 3610/* If "node" contains an isl_ast_expr_op_min, isl_ast_expr_op_max or3611 * isl_ast_expr_op_fdiv_q then set the corresponding bit in "macros".3612 */3613static int ast_node_required_macros(__isl_keep isl_ast_node *node, int macros)3614{3615 if (macros == ISL_AST_MACRO_ALL)3616 return macros;3617 3618 switch (node->type) {3619 case isl_ast_node_for:3620 macros = ast_expr_required_macros(node->u.f.init, macros);3621 if (!node->u.f.degenerate) {3622 macros = ast_expr_required_macros(node->u.f.cond,3623 macros);3624 macros = ast_expr_required_macros(node->u.f.inc,3625 macros);3626 }3627 macros = ast_node_required_macros(node->u.f.body, macros);3628 break;3629 case isl_ast_node_if:3630 macros = ast_expr_required_macros(node->u.i.guard, macros);3631 macros = ast_node_required_macros(node->u.i.then, macros);3632 if (node->u.i.else_node)3633 macros = ast_node_required_macros(node->u.i.else_node,3634 macros);3635 break;3636 case isl_ast_node_block:3637 macros = ast_node_list_required_macros(node->u.b.children,3638 macros);3639 break;3640 case isl_ast_node_mark:3641 macros = ast_node_required_macros(node->u.m.node, macros);3642 break;3643 case isl_ast_node_user:3644 macros = ast_expr_required_macros(node->u.e.expr, macros);3645 break;3646 case isl_ast_node_error:3647 break;3648 }3649 3650 return macros;3651}3652 3653/* If "list" contains an isl_ast_expr_op_min, isl_ast_expr_op_max or3654 * isl_ast_expr_op_fdiv_q then set the corresponding bit in "macros".3655 */3656static int ast_node_list_required_macros(__isl_keep isl_ast_node_list *list,3657 int macros)3658{3659 int i;3660 3661 for (i = 0; i < list->n; ++i)3662 macros = ast_node_required_macros(list->p[i], macros);3663 3664 return macros;3665}3666 3667/* Data structure for keeping track of whether a macro definition3668 * for a given type has already been printed.3669 * The value is zero if no definition has been printed and non-zero otherwise.3670 */3671struct isl_ast_expr_op_printed {3672 char printed[isl_ast_expr_op_last + 1];3673};3674 3675/* Create an empty struct isl_ast_expr_op_printed.3676 */3677static void *create_printed(isl_ctx *ctx)3678{3679 return isl_calloc_type(ctx, struct isl_ast_expr_op_printed);3680}3681 3682/* Free a struct isl_ast_expr_op_printed.3683 */3684static void free_printed(void *user)3685{3686 free(user);3687}3688 3689/* Ensure that "p" has an isl_ast_expr_op_printed note identified by "id".3690 */3691static __isl_give isl_printer *alloc_printed(__isl_take isl_printer *p,3692 __isl_keep isl_id *id)3693{3694 return alloc_note(p, id, &create_printed, &free_printed);3695}3696 3697/* Create an identifier that is used to store3698 * an isl_ast_expr_op_printed note.3699 */3700static __isl_give isl_id *printed_id(isl_ctx *ctx)3701{3702 return isl_id_alloc(ctx, "isl_ast_expr_op_type_printed", NULL);3703}3704 3705/* Did the user specify that a macro definition should only be3706 * printed once and has a macro definition for "type" already3707 * been printed to "p"?3708 * If definitions should only be printed once, but a definition3709 * for "p" has not yet been printed, then mark it as having been3710 * printed so that it will not printed again.3711 * The actual printing is taken care of by the caller.3712 */3713static isl_bool already_printed_once(__isl_keep isl_printer *p,3714 enum isl_ast_expr_op_type type)3715{3716 isl_ctx *ctx;3717 isl_id *id;3718 struct isl_ast_expr_op_printed *printed;3719 3720 if (!p)3721 return isl_bool_error;3722 3723 ctx = isl_printer_get_ctx(p);3724 if (!isl_options_get_ast_print_macro_once(ctx))3725 return isl_bool_false;3726 3727 if (type > isl_ast_expr_op_last)3728 isl_die(isl_printer_get_ctx(p), isl_error_invalid,3729 "invalid type", return isl_bool_error);3730 3731 id = printed_id(isl_printer_get_ctx(p));3732 p = alloc_printed(p, id);3733 printed = get_note(p, id);3734 isl_id_free(id);3735 if (!printed)3736 return isl_bool_error;3737 3738 if (printed->printed[type])3739 return isl_bool_true;3740 3741 printed->printed[type] = 1;3742 return isl_bool_false;3743}3744 3745/* Print a macro definition for the operator "type".3746 *3747 * If the user has specified that a macro definition should3748 * only be printed once to any given printer and if the macro definition3749 * has already been printed to "p", then do not print the definition.3750 */3751__isl_give isl_printer *isl_ast_expr_op_type_print_macro(3752 enum isl_ast_expr_op_type type, __isl_take isl_printer *p)3753{3754 isl_bool skip;3755 3756 skip = already_printed_once(p, type);3757 if (skip < 0)3758 return isl_printer_free(p);3759 if (skip)3760 return p;3761 3762 switch (type) {3763 case isl_ast_expr_op_min:3764 p = isl_printer_start_line(p);3765 p = isl_printer_print_str(p, "#define ");3766 p = isl_printer_print_str(p, get_op_str_c(p, type));3767 p = isl_printer_print_str(p,3768 "(x,y) ((x) < (y) ? (x) : (y))");3769 p = isl_printer_end_line(p);3770 break;3771 case isl_ast_expr_op_max:3772 p = isl_printer_start_line(p);3773 p = isl_printer_print_str(p, "#define ");3774 p = isl_printer_print_str(p, get_op_str_c(p, type));3775 p = isl_printer_print_str(p,3776 "(x,y) ((x) > (y) ? (x) : (y))");3777 p = isl_printer_end_line(p);3778 break;3779 case isl_ast_expr_op_fdiv_q:3780 p = isl_printer_start_line(p);3781 p = isl_printer_print_str(p, "#define ");3782 p = isl_printer_print_str(p, get_op_str_c(p, type));3783 p = isl_printer_print_str(p,3784 "(n,d) "3785 "(((n)<0) ? -((-(n)+(d)-1)/(d)) : (n)/(d))");3786 p = isl_printer_end_line(p);3787 break;3788 default:3789 break;3790 }3791 3792 return p;3793}3794 3795/* This is an alternative name for the function above.3796 */3797__isl_give isl_printer *isl_ast_op_type_print_macro(3798 enum isl_ast_expr_op_type type, __isl_take isl_printer *p)3799{3800 return isl_ast_expr_op_type_print_macro(type, p);3801}3802 3803/* Call "fn" for each type of operation represented in the "macros"3804 * bit vector.3805 */3806static isl_stat foreach_ast_expr_op_type(int macros,3807 isl_stat (*fn)(enum isl_ast_expr_op_type type, void *user), void *user)3808{3809 if (macros & ISL_AST_MACRO_MIN && fn(isl_ast_expr_op_min, user) < 0)3810 return isl_stat_error;3811 if (macros & ISL_AST_MACRO_MAX && fn(isl_ast_expr_op_max, user) < 0)3812 return isl_stat_error;3813 if (macros & ISL_AST_MACRO_FDIV_Q &&3814 fn(isl_ast_expr_op_fdiv_q, user) < 0)3815 return isl_stat_error;3816 3817 return isl_stat_ok;3818}3819 3820/* Call "fn" for each type of operation that appears in "expr"3821 * and that requires a macro definition.3822 */3823isl_stat isl_ast_expr_foreach_ast_expr_op_type(__isl_keep isl_ast_expr *expr,3824 isl_stat (*fn)(enum isl_ast_expr_op_type type, void *user), void *user)3825{3826 int macros;3827 3828 if (!expr)3829 return isl_stat_error;3830 3831 macros = ast_expr_required_macros(expr, 0);3832 return foreach_ast_expr_op_type(macros, fn, user);3833}3834 3835/* This is an alternative name for the function above.3836 */3837isl_stat isl_ast_expr_foreach_ast_op_type(__isl_keep isl_ast_expr *expr,3838 isl_stat (*fn)(enum isl_ast_expr_op_type type, void *user), void *user)3839{3840 return isl_ast_expr_foreach_ast_expr_op_type(expr, fn, user);3841}3842 3843/* Call "fn" for each type of operation that appears in "node"3844 * and that requires a macro definition.3845 */3846isl_stat isl_ast_node_foreach_ast_expr_op_type(__isl_keep isl_ast_node *node,3847 isl_stat (*fn)(enum isl_ast_expr_op_type type, void *user), void *user)3848{3849 int macros;3850 3851 if (!node)3852 return isl_stat_error;3853 3854 macros = ast_node_required_macros(node, 0);3855 return foreach_ast_expr_op_type(macros, fn, user);3856}3857 3858/* This is an alternative name for the function above.3859 */3860isl_stat isl_ast_node_foreach_ast_op_type(__isl_keep isl_ast_node *node,3861 isl_stat (*fn)(enum isl_ast_expr_op_type type, void *user), void *user)3862{3863 return isl_ast_node_foreach_ast_expr_op_type(node, fn, user);3864}3865 3866static isl_stat ast_op_type_print_macro(enum isl_ast_expr_op_type type,3867 void *user)3868{3869 isl_printer **p = user;3870 3871 *p = isl_ast_expr_op_type_print_macro(type, *p);3872 3873 return isl_stat_ok;3874}3875 3876/* Print macro definitions for all the macros used in the result3877 * of printing "expr".3878 */3879__isl_give isl_printer *isl_ast_expr_print_macros(3880 __isl_keep isl_ast_expr *expr, __isl_take isl_printer *p)3881{3882 if (isl_ast_expr_foreach_ast_expr_op_type(expr,3883 &ast_op_type_print_macro, &p) < 0)3884 return isl_printer_free(p);3885 return p;3886}3887 3888/* Print macro definitions for all the macros used in the result3889 * of printing "node".3890 */3891__isl_give isl_printer *isl_ast_node_print_macros(3892 __isl_keep isl_ast_node *node, __isl_take isl_printer *p)3893{3894 if (isl_ast_node_foreach_ast_expr_op_type(node,3895 &ast_op_type_print_macro, &p) < 0)3896 return isl_printer_free(p);3897 return p;3898}3899 3900/* Return a string containing C code representing this isl_ast_expr.3901 */3902__isl_give char *isl_ast_expr_to_C_str(__isl_keep isl_ast_expr *expr)3903{3904 isl_printer *p;3905 char *str;3906 3907 if (!expr)3908 return NULL;3909 3910 p = isl_printer_to_str(isl_ast_expr_get_ctx(expr));3911 p = isl_printer_set_output_format(p, ISL_FORMAT_C);3912 p = isl_printer_print_ast_expr(p, expr);3913 3914 str = isl_printer_get_str(p);3915 3916 isl_printer_free(p);3917 3918 return str;3919}3920 3921/* Return a string containing C code representing this isl_ast_node.3922 */3923__isl_give char *isl_ast_node_to_C_str(__isl_keep isl_ast_node *node)3924{3925 isl_printer *p;3926 char *str;3927 3928 if (!node)3929 return NULL;3930 3931 p = isl_printer_to_str(isl_ast_node_get_ctx(node));3932 p = isl_printer_set_output_format(p, ISL_FORMAT_C);3933 p = isl_printer_print_ast_node(p, node);3934 3935 str = isl_printer_get_str(p);3936 3937 isl_printer_free(p);3938 3939 return str;3940}3941