link against isl libraries first
[pet.git] / print.c
blob3456c72eaabd7e5fd9094ab5365d4cf669d453b5
1 /*
2 * Copyright 2011 Leiden University. All rights reserved.
3 * Copyright 2012-2014 Ecole Normale Superieure. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials provided
15 * with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY LEIDEN UNIVERSITY ''AS IS'' AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL LEIDEN UNIVERSITY OR
21 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
24 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 * The views and conclusions contained in the software and documentation
30 * are those of the authors and should not be interpreted as
31 * representing official policies, either expressed or implied, of
32 * Leiden University.
35 #include <isl/id.h>
36 #include <isl/space.h>
37 #include <isl/local_space.h>
38 #include <isl/aff.h>
39 #include <isl/ast.h>
40 #include <isl/ast_build.h>
41 #include <isl/printer.h>
42 #include <isl/val.h>
43 #include <pet.h>
44 #include "expr.h"
45 #include "print.h"
46 #include "scop.h"
48 /* Return the dimension of the domain of the embedded map
49 * in the domain of "mpa".
51 static int domain_domain_dim(__isl_keep isl_multi_pw_aff *mpa)
53 int dim;
54 isl_space *space;
56 space = isl_multi_pw_aff_get_space(mpa);
57 space = isl_space_unwrap(isl_space_domain(space));
58 dim = isl_space_dim(space, isl_dim_in);
59 isl_space_free(space);
61 return dim;
64 /* Given an access expression, check if any of the arguments
65 * for which an isl_ast_expr would be constructed by
66 * pet_expr_build_nested_ast_exprs are not themselves access expressions.
67 * If so, set *found and abort the search.
69 static int depends_on_expressions(__isl_keep pet_expr *expr, void *user)
71 int i, dim;
72 int *found = user;
74 if (expr->n_arg == 0)
75 return 0;
77 dim = domain_domain_dim(expr->acc.index);
79 for (i = 0; i < expr->n_arg; ++i) {
80 if (!isl_multi_pw_aff_involves_dims(expr->acc.index,
81 isl_dim_in, dim + i, 1))
82 continue;
83 if (expr->args[i]->type != pet_expr_access) {
84 *found = 1;
85 return -1;
89 return 0;
92 /* pet_stmt_build_ast_exprs is currently limited to only handle
93 * some forms of data dependent accesses.
94 * If pet_stmt_can_build_ast_exprs returns 1, then pet_stmt_build_ast_exprs
95 * can safely be called on "stmt".
97 int pet_stmt_can_build_ast_exprs(struct pet_stmt *stmt)
99 int r;
100 int found = 0;
102 if (!stmt)
103 return -1;
105 r = pet_tree_foreach_access_expr(stmt->body,
106 &depends_on_expressions, &found);
107 if (r < 0 && !found)
108 return -1;
110 return !found;
113 /* pet_stmt_build_ast_exprs is currently limited to only handle
114 * some forms of data dependent accesses.
115 * If pet_scop_can_build_ast_exprs returns 1, then pet_stmt_build_ast_exprs
116 * can safely be called on all statements in the scop.
118 int pet_scop_can_build_ast_exprs(struct pet_scop *scop)
120 int i;
122 if (!scop)
123 return -1;
125 for (i = 0; i < scop->n_stmt; ++i) {
126 int ok = pet_stmt_can_build_ast_exprs(scop->stmts[i]);
127 if (ok < 0 || !ok)
128 return ok;
131 return 1;
134 /* Internal data structure for pet_stmt_build_ast_exprs.
136 * "build" is used to construct an AST expression from an index expression.
137 * "fn_index" is used to transform the index expression prior to
138 * the construction of the AST expression.
139 * "fn_expr" is used to transform the constructed AST expression.
140 * "ref2expr" collects the results.
142 struct pet_build_ast_expr_data {
143 isl_ast_build *build;
144 __isl_give isl_multi_pw_aff *(*fn_index)(
145 __isl_take isl_multi_pw_aff *mpa, __isl_keep isl_id *id,
146 void *user);
147 void *user_index;
148 __isl_give isl_ast_expr *(*fn_expr)(__isl_take isl_ast_expr *expr,
149 __isl_keep isl_id *id, void *user);
150 void *user_expr;
151 isl_id_to_ast_expr *ref2expr;
154 /* Given an index expression "index" with nested expressions, replace
155 * those nested expressions by parameters. The identifiers
156 * of those parameters reference the corresponding arguments
157 * of "expr". The same identifiers are used in
158 * pet_expr_build_nested_ast_exprs.
160 * In particular, if "index" is of the form
162 * { [domain -> [e_1, ..., e_n]] -> array[f(e_1, ..., e_n)] }
164 * then we construct the expression
166 * [p_1, ..., p_n] -> { domain -> array[f(p_1, ..., p_n)] }
169 static __isl_give isl_multi_pw_aff *parametrize_nested_exprs(
170 __isl_take isl_multi_pw_aff *index, __isl_keep pet_expr *expr)
172 int i;
173 isl_ctx *ctx;
174 isl_space *space, *space2;
175 isl_local_space *ls;
176 isl_multi_aff *ma, *ma2;
178 ctx = isl_multi_pw_aff_get_ctx(index);
179 space = isl_multi_pw_aff_get_domain_space(index);
180 space = isl_space_unwrap(space);
182 space2 = isl_space_domain(isl_space_copy(space));
183 ma = isl_multi_aff_identity(isl_space_map_from_set(space2));
185 space = isl_space_insert_dims(space, isl_dim_param, 0,
186 expr->n_arg);
187 for (i = 0; i < expr->n_arg; ++i) {
188 isl_id *id = isl_id_alloc(ctx, NULL, expr->args[i]);
190 space = isl_space_set_dim_id(space, isl_dim_param, i, id);
192 space2 = isl_space_domain(isl_space_copy(space));
193 ls = isl_local_space_from_space(space2);
194 ma2 = isl_multi_aff_zero(space);
195 for (i = 0; i < expr->n_arg; ++i) {
196 isl_aff *aff;
197 aff = isl_aff_var_on_domain(isl_local_space_copy(ls),
198 isl_dim_param, i);
199 ma2 = isl_multi_aff_set_aff(ma2, i, aff);
201 isl_local_space_free(ls);
203 ma = isl_multi_aff_range_product(ma, ma2);
205 return isl_multi_pw_aff_pullback_multi_aff(index, ma);
208 static __isl_give isl_ast_expr *pet_expr_build_ast_expr(
209 __isl_keep pet_expr *expr, struct pet_build_ast_expr_data *data);
211 /* Construct an associative array from identifiers for the nested
212 * expressions of "expr" to the corresponding isl_ast_expr.
213 * The identifiers reference the corresponding arguments of "expr".
214 * The same identifiers are used in parametrize_nested_exprs.
215 * Note that we only need to construct isl_ast_expr objects for
216 * those arguments that actually appear in the index expression of "expr".
218 static __isl_give isl_id_to_ast_expr *pet_expr_build_nested_ast_exprs(
219 __isl_keep pet_expr *expr, struct pet_build_ast_expr_data *data)
221 int i, dim;
222 isl_ctx *ctx = isl_ast_build_get_ctx(data->build);
223 isl_id_to_ast_expr *id2expr;
225 dim = domain_domain_dim(expr->acc.index);
226 id2expr = isl_id_to_ast_expr_alloc(ctx, expr->n_arg);
228 for (i = 0; i < expr->n_arg; ++i) {
229 isl_id *id;
230 isl_ast_expr *ast_expr;
232 if (!isl_multi_pw_aff_involves_dims(expr->acc.index,
233 isl_dim_in, dim + i, 1))
234 continue;
236 id = isl_id_alloc(ctx, NULL, expr->args[i]);
237 ast_expr = pet_expr_build_ast_expr(expr->args[i], data);
238 id2expr = isl_id_to_ast_expr_set(id2expr, id, ast_expr);
241 return id2expr;
244 /* Construct an AST expression from an access expression.
246 * If the expression has any arguments, we first convert those
247 * to AST expressions and replace the references to those arguments
248 * in the index expression by parameters.
250 * Then we apply the index transformation if any was provided by the user.
252 * If the "access" is actually an affine expression, we print is as such.
253 * Otherwise, we print a proper access.
255 * If the original expression had any arguments, then they are plugged in now.
257 * Finally, we apply an AST transformation on the result, if any was provided
258 * by the user.
260 static __isl_give isl_ast_expr *pet_expr_access_build_ast_expr(
261 __isl_keep pet_expr *expr, struct pet_build_ast_expr_data *data)
263 isl_pw_aff *pa;
264 isl_multi_pw_aff *mpa;
265 isl_ast_expr *ast_expr;
266 isl_id_to_ast_expr *id2expr;
267 isl_ast_build *build = data->build;
269 if (!expr)
270 return NULL;
271 if (expr->type != pet_expr_access)
272 isl_die(isl_ast_build_get_ctx(build), isl_error_invalid,
273 "not an access expression", return NULL);
275 mpa = isl_multi_pw_aff_copy(expr->acc.index);
277 if (expr->n_arg > 0) {
278 mpa = parametrize_nested_exprs(mpa, expr);
279 id2expr = pet_expr_build_nested_ast_exprs(expr, data);
282 if (data->fn_index)
283 mpa = data->fn_index(mpa, expr->acc.ref_id, data->user_index);
284 mpa = isl_multi_pw_aff_coalesce(mpa);
286 if (!pet_expr_is_affine(expr)) {
287 ast_expr = isl_ast_build_access_from_multi_pw_aff(build, mpa);
288 } else {
289 pa = isl_multi_pw_aff_get_pw_aff(mpa, 0);
290 ast_expr = isl_ast_build_expr_from_pw_aff(build, pa);
291 isl_multi_pw_aff_free(mpa);
293 if (expr->n_arg > 0)
294 ast_expr = isl_ast_expr_substitute_ids(ast_expr, id2expr);
295 if (data->fn_expr)
296 ast_expr = data->fn_expr(ast_expr, expr->acc.ref_id,
297 data->user_index);
299 return ast_expr;
302 /* A type representing a binary operation on objects of type isl_ast_expr.
304 typedef __isl_give isl_ast_expr *(*binary_ast_op_t)(
305 __isl_take isl_ast_expr *expr1, __isl_take isl_ast_expr *expr2);
307 /* For the supported binary operations, the corresponding function
308 * performing the operation on objects of type isl_ast_expr.
310 static binary_ast_op_t binary_ast_op[] = {
311 [pet_op_add] = &isl_ast_expr_add,
312 [pet_op_sub] = &isl_ast_expr_sub,
313 [pet_op_last] = NULL,
316 /* Try and construct an AST expression from an operation expression.
318 * Only some binary operations are currently supported.
320 static __isl_give isl_ast_expr *pet_expr_op_build_ast_expr(
321 __isl_keep pet_expr *expr, struct pet_build_ast_expr_data *data)
323 isl_ast_expr *lhs, *rhs;
324 binary_ast_op_t ast_op;
326 if (!expr)
327 return NULL;
328 if (expr->type != pet_expr_op)
329 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
330 "not an operation expression", return NULL);
332 ast_op = binary_ast_op[expr->op];
333 if (!ast_op)
334 isl_die(pet_expr_get_ctx(expr), isl_error_unsupported,
335 "unsupported operation type", return NULL);
337 lhs = pet_expr_build_ast_expr(expr->args[pet_bin_lhs], data);
338 rhs = pet_expr_build_ast_expr(expr->args[pet_bin_rhs], data);
339 return ast_op(lhs, rhs);
342 /* Try and construct an AST expression from an expression.
344 * Only some types of expressions are currently supported,
345 * - integer values
346 * - access expressions
347 * - (some) operation expressions.
349 static __isl_give isl_ast_expr *pet_expr_build_ast_expr(
350 __isl_keep pet_expr *expr, struct pet_build_ast_expr_data *data)
352 if (!expr)
353 return NULL;
355 switch (expr->type) {
356 case pet_expr_error:
357 return NULL;
358 case pet_expr_int:
359 return isl_ast_expr_from_val(isl_val_copy(expr->i));
360 case pet_expr_double:
361 isl_die(pet_expr_get_ctx(expr), isl_error_unsupported,
362 "unsupported expression type", return NULL);
363 case pet_expr_access:
364 return pet_expr_access_build_ast_expr(expr, data);
365 case pet_expr_op:
366 return pet_expr_op_build_ast_expr(expr, data);
367 case pet_expr_call:
368 isl_die(pet_expr_get_ctx(expr), isl_error_unsupported,
369 "unsupported expression type", return NULL);
370 case pet_expr_cast:
371 isl_die(pet_expr_get_ctx(expr), isl_error_unsupported,
372 "unsupported expression type", return NULL);
375 return NULL;
378 /* Construct an AST expression from the access expression "expr" and
379 * add the mapping from reference identifier to AST expression to
380 * data->ref2expr.
382 static int add_access(__isl_keep pet_expr *expr, void *user)
384 struct pet_build_ast_expr_data *data = user;
385 isl_id *id;
386 isl_ast_expr *ast_expr;
388 ast_expr = pet_expr_access_build_ast_expr(expr, data);
390 id = isl_id_copy(expr->acc.ref_id);
391 data->ref2expr = isl_id_to_ast_expr_set(data->ref2expr, id, ast_expr);
393 return 0;
396 /* Construct an associative array from reference identifiers of
397 * access expressions in "stmt" to the corresponding isl_ast_expr.
398 * Each index expression is first transformed through "fn_index"
399 * (if not NULL). Then an AST expression is generated using "build".
400 * Finally, the AST expression is transformed using "fn_expr"
401 * (if not NULL).
403 __isl_give isl_id_to_ast_expr *pet_stmt_build_ast_exprs(struct pet_stmt *stmt,
404 __isl_keep isl_ast_build *build,
405 __isl_give isl_multi_pw_aff *(*fn_index)(
406 __isl_take isl_multi_pw_aff *mpa, __isl_keep isl_id *id,
407 void *user), void *user_index,
408 __isl_give isl_ast_expr *(*fn_expr)(__isl_take isl_ast_expr *expr,
409 __isl_keep isl_id *id, void *user), void *user_expr)
411 struct pet_build_ast_expr_data data =
412 { build, fn_index, user_index, fn_expr, user_expr };
413 isl_ctx *ctx;
415 if (!stmt || !build)
416 return NULL;
418 ctx = isl_ast_build_get_ctx(build);
419 data.ref2expr = isl_id_to_ast_expr_alloc(ctx, 0);
420 if (pet_tree_foreach_access_expr(stmt->body, &add_access, &data) < 0)
421 data.ref2expr = isl_id_to_ast_expr_free(data.ref2expr);
423 return data.ref2expr;
426 /* Print the access expression "expr" to "p".
428 * We look up the corresponding isl_ast_expr in "ref2expr"
429 * and print that to "p".
431 static __isl_give isl_printer *print_access(__isl_take isl_printer *p,
432 __isl_keep pet_expr *expr, __isl_keep isl_id_to_ast_expr *ref2expr)
434 isl_ast_expr *ast_expr;
435 int is_access;
437 if (!isl_id_to_ast_expr_has(ref2expr, expr->acc.ref_id))
438 isl_die(isl_printer_get_ctx(p), isl_error_internal,
439 "missing expression", return isl_printer_free(p));
441 ast_expr = isl_id_to_ast_expr_get(ref2expr,
442 isl_id_copy(expr->acc.ref_id));
443 is_access = isl_ast_expr_get_type(ast_expr) == isl_ast_expr_op &&
444 isl_ast_expr_get_op_type(ast_expr) == isl_ast_op_access;
445 if (!is_access)
446 p = isl_printer_print_str(p, "(");
447 p = isl_printer_print_ast_expr(p, ast_expr);
448 if (!is_access)
449 p = isl_printer_print_str(p, ")");
450 isl_ast_expr_free(ast_expr);
452 return p;
455 /* Is "op" a postfix operator?
457 static int is_postfix(enum pet_op_type op)
459 switch (op) {
460 case pet_op_post_inc:
461 case pet_op_post_dec:
462 return 1;
463 default:
464 return 0;
468 static __isl_give isl_printer *print_pet_expr(__isl_take isl_printer *p,
469 __isl_keep pet_expr *expr, int outer,
470 __isl_keep isl_id_to_ast_expr *ref2expr);
472 /* Print operation expression "expr" to "p".
474 * The access subexpressions are replaced by the isl_ast_expr
475 * associated to its reference identifier in "ref2expr".
477 static __isl_give isl_printer *print_op(__isl_take isl_printer *p,
478 __isl_keep pet_expr *expr, __isl_keep isl_id_to_ast_expr *ref2expr)
480 switch (expr->n_arg) {
481 case 1:
482 if (!is_postfix(expr->op))
483 p = isl_printer_print_str(p, pet_op_str(expr->op));
484 p = print_pet_expr(p, expr->args[pet_un_arg], 0, ref2expr);
485 if (is_postfix(expr->op))
486 p = isl_printer_print_str(p, pet_op_str(expr->op));
487 break;
488 case 2:
489 p = print_pet_expr(p, expr->args[pet_bin_lhs], 0,
490 ref2expr);
491 p = isl_printer_print_str(p, " ");
492 p = isl_printer_print_str(p, pet_op_str(expr->op));
493 p = isl_printer_print_str(p, " ");
494 p = print_pet_expr(p, expr->args[pet_bin_rhs], 0,
495 ref2expr);
496 break;
497 case 3:
498 p = print_pet_expr(p, expr->args[pet_ter_cond], 0,
499 ref2expr);
500 p = isl_printer_print_str(p, " ? ");
501 p = print_pet_expr(p, expr->args[pet_ter_true], 0,
502 ref2expr);
503 p = isl_printer_print_str(p, " : ");
504 p = print_pet_expr(p, expr->args[pet_ter_false], 0,
505 ref2expr);
506 break;
509 return p;
512 /* Print "expr" to "p".
514 * If "outer" is set, then we are printing the outer expression statement.
516 * The access subexpressions are replaced by the isl_ast_expr
517 * associated to its reference identifier in "ref2expr".
519 static __isl_give isl_printer *print_pet_expr(__isl_take isl_printer *p,
520 __isl_keep pet_expr *expr, int outer,
521 __isl_keep isl_id_to_ast_expr *ref2expr)
523 int i;
525 switch (expr->type) {
526 case pet_expr_error:
527 p = isl_printer_free(p);
528 break;
529 case pet_expr_int:
530 p = isl_printer_print_val(p, expr->i);
531 break;
532 case pet_expr_double:
533 p = isl_printer_print_str(p, expr->d.s);
534 break;
535 case pet_expr_access:
536 p = print_access(p, expr, ref2expr);
537 break;
538 case pet_expr_op:
539 if (!outer)
540 p = isl_printer_print_str(p, "(");
541 p = print_op(p, expr, ref2expr);
542 if (!outer)
543 p = isl_printer_print_str(p, ")");
544 break;
545 case pet_expr_call:
546 p = isl_printer_print_str(p, expr->c.name);
547 p = isl_printer_print_str(p, "(");
548 for (i = 0; i < expr->n_arg; ++i) {
549 if (i)
550 p = isl_printer_print_str(p, ", ");
551 p = print_pet_expr(p, expr->args[i], 1, ref2expr);
553 p = isl_printer_print_str(p, ")");
554 break;
555 case pet_expr_cast:
556 if (!outer)
557 p = isl_printer_print_str(p, "(");
558 p = isl_printer_print_str(p, "(");
559 p = isl_printer_print_str(p, expr->type_name);
560 p = isl_printer_print_str(p, ") ");
561 p = print_pet_expr(p, expr->args[0], 0, ref2expr);
562 if (!outer)
563 p = isl_printer_print_str(p, ")");
564 break;
567 return p;
570 static __isl_give isl_printer *print_pet_tree(__isl_take isl_printer *p,
571 __isl_keep pet_tree *tree, int in_block,
572 __isl_keep isl_id_to_ast_expr *ref2expr);
574 /* Print "tree" to "p", where "tree" is of type pet_tree_block.
576 * If "in_block" is set, then the caller has just printed a block,
577 * so there is no need to print one for this node.
579 * The access subexpressions are replaced by the isl_ast_expr
580 * associated to its reference identifier in "ref2expr".
582 static __isl_give isl_printer *print_pet_tree_block(__isl_take isl_printer *p,
583 __isl_keep pet_tree *tree, int in_block,
584 __isl_keep isl_id_to_ast_expr *ref2expr)
586 int i, n;
588 if (!in_block) {
589 p = isl_printer_start_line(p);
590 p = isl_printer_print_str(p, "{");
591 p = isl_printer_end_line(p);
592 p = isl_printer_indent(p, 2);
595 n = pet_tree_block_n_child(tree);
597 for (i = 0; i < n; ++i) {
598 pet_tree *child;
600 child = pet_tree_block_get_child(tree, i);
601 p = print_pet_tree(p, child, 0, ref2expr);
602 pet_tree_free(child);
605 if (!in_block) {
606 p = isl_printer_indent(p, -2);
607 p = isl_printer_start_line(p);
608 p = isl_printer_print_str(p, "}");
609 p = isl_printer_end_line(p);
612 return p;
615 /* Print "tree" to "p", where "tree" is of type pet_tree_if or
616 * pet_tree_if_else..
618 * The access subexpressions are replaced by the isl_ast_expr
619 * associated to its reference identifier in "ref2expr".
621 static __isl_give isl_printer *print_pet_tree_if(__isl_take isl_printer *p,
622 __isl_keep pet_tree *tree, __isl_keep isl_id_to_ast_expr *ref2expr)
624 pet_expr *expr;
625 pet_tree *body;
627 p = isl_printer_start_line(p);
628 p = isl_printer_print_str(p, "if (");
629 expr = pet_tree_if_get_cond(tree);
630 p = print_pet_expr(p, expr, 1, ref2expr);
631 pet_expr_free(expr);
632 p = isl_printer_print_str(p, ") {");
633 p = isl_printer_end_line(p);
635 p = isl_printer_indent(p, 2);
636 body = pet_tree_if_get_then(tree);
637 p = print_pet_tree(p, body, 1, ref2expr);
638 pet_tree_free(body);
639 p = isl_printer_indent(p, -2);
641 p = isl_printer_start_line(p);
642 p = isl_printer_print_str(p, "}");
644 if (pet_tree_get_type(tree) == pet_tree_if_else) {
645 p = isl_printer_print_str(p, " else {");
646 p = isl_printer_end_line(p);
648 p = isl_printer_indent(p, 2);
649 body = pet_tree_if_get_else(tree);
650 p = print_pet_tree(p, body, 1, ref2expr);
651 pet_tree_free(body);
652 p = isl_printer_indent(p, -2);
654 p = isl_printer_start_line(p);
655 p = isl_printer_print_str(p, "}");
658 p = isl_printer_end_line(p);
660 return p;
663 /* Print "tree" to "p", where "tree" is of type pet_tree_for.
665 * The access subexpressions are replaced by the isl_ast_expr
666 * associated to its reference identifier in "ref2expr".
668 static __isl_give isl_printer *print_pet_tree_for(__isl_take isl_printer *p,
669 __isl_keep pet_tree *tree, __isl_keep isl_id_to_ast_expr *ref2expr)
671 pet_expr *expr_iv, *expr;
672 pet_tree *body;
674 expr_iv = pet_tree_loop_get_var(tree);
676 p = isl_printer_start_line(p);
677 p = isl_printer_print_str(p, "for (");
678 p = print_pet_expr(p, expr_iv, 1, ref2expr);
679 p = isl_printer_print_str(p, " = ");
680 expr = pet_tree_loop_get_init(tree);
681 p = print_pet_expr(p, expr, 0, ref2expr);
682 pet_expr_free(expr);
683 p = isl_printer_print_str(p, "; ");
684 expr = pet_tree_loop_get_cond(tree);
685 p = print_pet_expr(p, expr, 1, ref2expr);
686 pet_expr_free(expr);
687 p = isl_printer_print_str(p, "; ");
688 p = print_pet_expr(p, expr_iv, 1, ref2expr);
689 p = isl_printer_print_str(p, " += ");
690 expr = pet_tree_loop_get_inc(tree);
691 p = print_pet_expr(p, expr, 0, ref2expr);
692 pet_expr_free(expr);
693 p = isl_printer_print_str(p, ") {");
694 p = isl_printer_end_line(p);
696 pet_expr_free(expr_iv);
698 p = isl_printer_indent(p, 2);
699 body = pet_tree_loop_get_body(tree);
700 p = print_pet_tree(p, body, 1, ref2expr);
701 pet_tree_free(body);
702 p = isl_printer_indent(p, -2);
704 p = isl_printer_start_line(p);
705 p = isl_printer_print_str(p, "}");
706 p = isl_printer_end_line(p);
708 return p;
711 /* Print "tree" to "p", where "tree" is of type pet_tree_while or
712 * pet_tree_infinite_loop.
714 * The access subexpressions are replaced by the isl_ast_expr
715 * associated to its reference identifier in "ref2expr".
717 * pet_tree_loop_get_cond returns "1" when called on a tree of type
718 * pet_tree_infinite_loop, so we can treat them in the same way
719 * as trees of type pet_tree_while.
721 static __isl_give isl_printer *print_pet_tree_while(__isl_take isl_printer *p,
722 __isl_keep pet_tree *tree, __isl_keep isl_id_to_ast_expr *ref2expr)
724 pet_expr *expr;
725 pet_tree *body;
727 p = isl_printer_start_line(p);
728 p = isl_printer_print_str(p, "while (");
729 expr = pet_tree_loop_get_cond(tree);
730 p = print_pet_expr(p, expr, 1, ref2expr);
731 pet_expr_free(expr);
732 p = isl_printer_print_str(p, ") {");
733 p = isl_printer_end_line(p);
735 p = isl_printer_indent(p, 2);
736 body = pet_tree_loop_get_body(tree);
737 p = print_pet_tree(p, body, 1, ref2expr);
738 pet_tree_free(body);
739 p = isl_printer_indent(p, -2);
741 p = isl_printer_start_line(p);
742 p = isl_printer_print_str(p, "}");
743 p = isl_printer_end_line(p);
745 return p;
748 /* Print "tree" to "p", where "tree" is of type pet_tree_decl_init.
750 * We assume all variables have already been declared, so we
751 * only print the assignment implied by the declaration initialization.
753 * The access subexpressions are replaced by the isl_ast_expr
754 * associated to its reference identifier in "ref2expr".
756 static __isl_give isl_printer *print_pet_tree_decl_init(
757 __isl_take isl_printer *p, __isl_keep pet_tree *tree,
758 __isl_keep isl_id_to_ast_expr *ref2expr)
760 pet_expr *var, *init;
762 p = isl_printer_start_line(p);
764 var = pet_tree_decl_get_var(tree);
765 p = print_pet_expr(p, var, 1, ref2expr);
766 pet_expr_free(var);
768 p = isl_printer_print_str(p, " = ");
770 init = pet_tree_decl_get_init(tree);
771 p = print_pet_expr(p, init, 1, ref2expr);
772 pet_expr_free(init);
774 p = isl_printer_print_str(p, ";");
775 p = isl_printer_end_line(p);
777 return p;
780 /* Print "tree" to "p", where "tree" is of type pet_tree_return.
782 * The access subexpressions are replaced by the isl_ast_expr
783 * associated to its reference identifier in "ref2expr".
785 static __isl_give isl_printer *print_pet_tree_return(__isl_take isl_printer *p,
786 __isl_keep pet_tree *tree, __isl_keep isl_id_to_ast_expr *ref2expr)
788 pet_expr *expr;
790 expr = pet_tree_expr_get_expr(tree);
791 p = isl_printer_start_line(p);
792 p = isl_printer_print_str(p, "return ");
793 p = print_pet_expr(p, expr, 1, ref2expr);
794 p = isl_printer_print_str(p, ";");
795 p = isl_printer_end_line(p);
796 pet_expr_free(expr);
798 return p;
801 /* Print "tree" to "p".
803 * If "in_block" is set, then the caller has just printed a block,
804 * so there is no need to print one for this node.
806 * The access subexpressions are replaced by the isl_ast_expr
807 * associated to its reference identifier in "ref2expr".
809 * We assume all variables have already been declared,
810 * so there is nothing to print for nodes of type pet_tree_decl.
812 static __isl_give isl_printer *print_pet_tree(__isl_take isl_printer *p,
813 __isl_keep pet_tree *tree, int in_block,
814 __isl_keep isl_id_to_ast_expr *ref2expr)
816 pet_expr *expr;
817 enum pet_tree_type type;
819 type = pet_tree_get_type(tree);
820 switch (type) {
821 case pet_tree_error:
822 return isl_printer_free(p);
823 case pet_tree_block:
824 return print_pet_tree_block(p, tree, in_block, ref2expr);
825 case pet_tree_break:
826 case pet_tree_continue:
827 p = isl_printer_start_line(p);
828 if (type == pet_tree_break)
829 p = isl_printer_print_str(p, "break;");
830 else
831 p = isl_printer_print_str(p, "continue;");
832 return isl_printer_end_line(p);
833 case pet_tree_expr:
834 expr = pet_tree_expr_get_expr(tree);
835 p = isl_printer_start_line(p);
836 p = print_pet_expr(p, expr, 1, ref2expr);
837 p = isl_printer_print_str(p, ";");
838 p = isl_printer_end_line(p);
839 pet_expr_free(expr);
840 break;
841 case pet_tree_return:
842 return print_pet_tree_return(p, tree, ref2expr);
843 case pet_tree_if:
844 case pet_tree_if_else:
845 return print_pet_tree_if(p, tree, ref2expr);
846 case pet_tree_for:
847 return print_pet_tree_for(p, tree, ref2expr);
848 case pet_tree_while:
849 case pet_tree_infinite_loop:
850 return print_pet_tree_while(p, tree, ref2expr);
851 case pet_tree_decl:
852 return p;
853 case pet_tree_decl_init:
854 return print_pet_tree_decl_init(p, tree, ref2expr);
857 return p;
860 /* Print "stmt" to "p".
862 * The access expressions in "stmt" are replaced by the isl_ast_expr
863 * associated to its reference identifier in "ref2expr".
865 * If the statement is an assume or a kill statement, then we print nothing.
867 __isl_give isl_printer *pet_stmt_print_body(struct pet_stmt *stmt,
868 __isl_take isl_printer *p, __isl_keep isl_id_to_ast_expr *ref2expr)
870 if (!stmt)
871 return isl_printer_free(p);
872 if (pet_stmt_is_assume(stmt))
873 return p;
874 if (pet_stmt_is_kill(stmt))
875 return p;
876 p = print_pet_tree(p, stmt->body, 0, ref2expr);
878 return p;
881 /* Copy the contents of "input" from offset "start" to "end" to "output".
883 int copy(FILE *input, FILE *output, long start, long end)
885 char buffer[1024];
886 size_t n, m;
888 if (end < 0) {
889 fseek(input, 0, SEEK_END);
890 end = ftell(input);
893 fseek(input, start, SEEK_SET);
895 while (start < end) {
896 n = end - start;
897 if (n > 1024)
898 n = 1024;
899 n = fread(buffer, 1, n, input);
900 if (n <= 0)
901 return -1;
902 m = fwrite(buffer, 1, n, output);
903 if (n != m)
904 return -1;
905 start += n;
908 return 0;