README: update latest release of clang
[pet.git] / print.c
blob8163dc2ca76e143975f7ba52ec808e0c5d944d27
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_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 /* Construct an AST expression from the access expression "expr" and
303 * add the mapping from reference identifier to AST expression to
304 * data->ref2expr.
306 static int add_access(__isl_keep pet_expr *expr, void *user)
308 struct pet_build_ast_expr_data *data = user;
309 isl_id *id;
310 isl_ast_expr *ast_expr;
312 ast_expr = pet_expr_build_ast_expr(expr, data);
314 id = isl_id_copy(expr->acc.ref_id);
315 data->ref2expr = isl_id_to_ast_expr_set(data->ref2expr, id, ast_expr);
317 return 0;
320 /* Construct an associative array from reference identifiers of
321 * access expressions in "stmt" to the corresponding isl_ast_expr.
322 * Each index expression is first transformed through "fn_index"
323 * (if not NULL). Then an AST expression is generated using "build".
324 * Finally, the AST expression is transformed using "fn_expr"
325 * (if not NULL).
327 __isl_give isl_id_to_ast_expr *pet_stmt_build_ast_exprs(struct pet_stmt *stmt,
328 __isl_keep isl_ast_build *build,
329 __isl_give isl_multi_pw_aff *(*fn_index)(
330 __isl_take isl_multi_pw_aff *mpa, __isl_keep isl_id *id,
331 void *user), void *user_index,
332 __isl_give isl_ast_expr *(*fn_expr)(__isl_take isl_ast_expr *expr,
333 __isl_keep isl_id *id, void *user), void *user_expr)
335 struct pet_build_ast_expr_data data =
336 { build, fn_index, user_index, fn_expr, user_expr };
337 isl_ctx *ctx;
339 if (!stmt || !build)
340 return NULL;
342 ctx = isl_ast_build_get_ctx(build);
343 data.ref2expr = isl_id_to_ast_expr_alloc(ctx, 0);
344 if (pet_tree_foreach_access_expr(stmt->body, &add_access, &data) < 0)
345 data.ref2expr = isl_id_to_ast_expr_free(data.ref2expr);
347 return data.ref2expr;
350 /* Print the access expression "expr" to "p".
352 * We look up the corresponding isl_ast_expr in "ref2expr"
353 * and print that to "p".
355 static __isl_give isl_printer *print_access(__isl_take isl_printer *p,
356 __isl_keep pet_expr *expr, __isl_keep isl_id_to_ast_expr *ref2expr)
358 isl_ast_expr *ast_expr;
359 int is_access;
361 if (!isl_id_to_ast_expr_has(ref2expr, expr->acc.ref_id))
362 isl_die(isl_printer_get_ctx(p), isl_error_internal,
363 "missing expression", return isl_printer_free(p));
365 ast_expr = isl_id_to_ast_expr_get(ref2expr,
366 isl_id_copy(expr->acc.ref_id));
367 is_access = isl_ast_expr_get_type(ast_expr) == isl_ast_expr_op &&
368 isl_ast_expr_get_op_type(ast_expr) == isl_ast_op_access;
369 if (!is_access)
370 p = isl_printer_print_str(p, "(");
371 p = isl_printer_print_ast_expr(p, ast_expr);
372 if (!is_access)
373 p = isl_printer_print_str(p, ")");
374 isl_ast_expr_free(ast_expr);
376 return p;
379 /* Is "op" a postfix operator?
381 static int is_postfix(enum pet_op_type op)
383 switch (op) {
384 case pet_op_post_inc:
385 case pet_op_post_dec:
386 return 1;
387 default:
388 return 0;
392 static __isl_give isl_printer *print_pet_expr(__isl_take isl_printer *p,
393 __isl_keep pet_expr *expr, int outer,
394 __isl_keep isl_id_to_ast_expr *ref2expr);
396 /* Print operation expression "expr" to "p".
398 * The access subexpressions are replaced by the isl_ast_expr
399 * associated to its reference identifier in "ref2expr".
401 static __isl_give isl_printer *print_op(__isl_take isl_printer *p,
402 __isl_keep pet_expr *expr, __isl_keep isl_id_to_ast_expr *ref2expr)
404 switch (expr->n_arg) {
405 case 1:
406 if (!is_postfix(expr->op))
407 p = isl_printer_print_str(p, pet_op_str(expr->op));
408 p = print_pet_expr(p, expr->args[pet_un_arg], 0, ref2expr);
409 if (is_postfix(expr->op))
410 p = isl_printer_print_str(p, pet_op_str(expr->op));
411 break;
412 case 2:
413 p = print_pet_expr(p, expr->args[pet_bin_lhs], 0,
414 ref2expr);
415 p = isl_printer_print_str(p, " ");
416 p = isl_printer_print_str(p, pet_op_str(expr->op));
417 p = isl_printer_print_str(p, " ");
418 p = print_pet_expr(p, expr->args[pet_bin_rhs], 0,
419 ref2expr);
420 break;
421 case 3:
422 p = print_pet_expr(p, expr->args[pet_ter_cond], 0,
423 ref2expr);
424 p = isl_printer_print_str(p, " ? ");
425 p = print_pet_expr(p, expr->args[pet_ter_true], 0,
426 ref2expr);
427 p = isl_printer_print_str(p, " : ");
428 p = print_pet_expr(p, expr->args[pet_ter_false], 0,
429 ref2expr);
430 break;
433 return p;
436 /* Print "expr" to "p".
438 * If "outer" is set, then we are printing the outer expression statement.
440 * The access subexpressions are replaced by the isl_ast_expr
441 * associated to its reference identifier in "ref2expr".
443 static __isl_give isl_printer *print_pet_expr(__isl_take isl_printer *p,
444 __isl_keep pet_expr *expr, int outer,
445 __isl_keep isl_id_to_ast_expr *ref2expr)
447 int i;
449 switch (expr->type) {
450 case pet_expr_error:
451 p = isl_printer_free(p);
452 break;
453 case pet_expr_int:
454 p = isl_printer_print_val(p, expr->i);
455 break;
456 case pet_expr_double:
457 p = isl_printer_print_str(p, expr->d.s);
458 break;
459 case pet_expr_access:
460 p = print_access(p, expr, ref2expr);
461 break;
462 case pet_expr_op:
463 if (!outer)
464 p = isl_printer_print_str(p, "(");
465 p = print_op(p, expr, ref2expr);
466 if (!outer)
467 p = isl_printer_print_str(p, ")");
468 break;
469 case pet_expr_call:
470 p = isl_printer_print_str(p, expr->c.name);
471 p = isl_printer_print_str(p, "(");
472 for (i = 0; i < expr->n_arg; ++i) {
473 if (i)
474 p = isl_printer_print_str(p, ", ");
475 p = print_pet_expr(p, expr->args[i], 1, ref2expr);
477 p = isl_printer_print_str(p, ")");
478 break;
479 case pet_expr_cast:
480 if (!outer)
481 p = isl_printer_print_str(p, "(");
482 p = isl_printer_print_str(p, "(");
483 p = isl_printer_print_str(p, expr->type_name);
484 p = isl_printer_print_str(p, ") ");
485 p = print_pet_expr(p, expr->args[0], 0, ref2expr);
486 if (!outer)
487 p = isl_printer_print_str(p, ")");
488 break;
491 return p;
494 static __isl_give isl_printer *print_pet_tree(__isl_take isl_printer *p,
495 __isl_keep pet_tree *tree, int in_block,
496 __isl_keep isl_id_to_ast_expr *ref2expr);
498 /* Print "tree" to "p", where "tree" is of type pet_tree_block.
500 * If "in_block" is set, then the caller has just printed a block,
501 * so there is no need to print one for this node.
503 * The access subexpressions are replaced by the isl_ast_expr
504 * associated to its reference identifier in "ref2expr".
506 static __isl_give isl_printer *print_pet_tree_block(__isl_take isl_printer *p,
507 __isl_keep pet_tree *tree, int in_block,
508 __isl_keep isl_id_to_ast_expr *ref2expr)
510 int i, n;
512 if (!in_block) {
513 p = isl_printer_start_line(p);
514 p = isl_printer_print_str(p, "{");
515 p = isl_printer_end_line(p);
516 p = isl_printer_indent(p, 2);
519 n = pet_tree_block_n_child(tree);
521 for (i = 0; i < n; ++i) {
522 pet_tree *child;
524 child = pet_tree_block_get_child(tree, i);
525 p = print_pet_tree(p, child, 0, ref2expr);
526 pet_tree_free(child);
529 if (!in_block) {
530 p = isl_printer_indent(p, -2);
531 p = isl_printer_start_line(p);
532 p = isl_printer_print_str(p, "}");
533 p = isl_printer_end_line(p);
536 return p;
539 /* Print "tree" to "p", where "tree" is of type pet_tree_if or
540 * pet_tree_if_else..
542 * The access subexpressions are replaced by the isl_ast_expr
543 * associated to its reference identifier in "ref2expr".
545 static __isl_give isl_printer *print_pet_tree_if(__isl_take isl_printer *p,
546 __isl_keep pet_tree *tree, __isl_keep isl_id_to_ast_expr *ref2expr)
548 pet_expr *expr;
549 pet_tree *body;
551 p = isl_printer_start_line(p);
552 p = isl_printer_print_str(p, "if (");
553 expr = pet_tree_if_get_cond(tree);
554 p = print_pet_expr(p, expr, 1, ref2expr);
555 pet_expr_free(expr);
556 p = isl_printer_print_str(p, ") {");
557 p = isl_printer_end_line(p);
559 p = isl_printer_indent(p, 2);
560 body = pet_tree_if_get_then(tree);
561 p = print_pet_tree(p, body, 1, ref2expr);
562 pet_tree_free(body);
563 p = isl_printer_indent(p, -2);
565 p = isl_printer_start_line(p);
566 p = isl_printer_print_str(p, "}");
568 if (pet_tree_get_type(tree) == pet_tree_if_else) {
569 p = isl_printer_print_str(p, " else {");
570 p = isl_printer_end_line(p);
572 p = isl_printer_indent(p, 2);
573 body = pet_tree_if_get_else(tree);
574 p = print_pet_tree(p, body, 1, ref2expr);
575 pet_tree_free(body);
576 p = isl_printer_indent(p, -2);
578 p = isl_printer_start_line(p);
579 p = isl_printer_print_str(p, "}");
582 p = isl_printer_end_line(p);
584 return p;
587 /* Print "tree" to "p", where "tree" is of type pet_tree_for.
589 * The access subexpressions are replaced by the isl_ast_expr
590 * associated to its reference identifier in "ref2expr".
592 static __isl_give isl_printer *print_pet_tree_for(__isl_take isl_printer *p,
593 __isl_keep pet_tree *tree, __isl_keep isl_id_to_ast_expr *ref2expr)
595 pet_expr *expr_iv, *expr;
596 pet_tree *body;
598 expr_iv = pet_tree_loop_get_var(tree);
600 p = isl_printer_start_line(p);
601 p = isl_printer_print_str(p, "for (");
602 p = print_pet_expr(p, expr_iv, 1, ref2expr);
603 p = isl_printer_print_str(p, " = ");
604 expr = pet_tree_loop_get_init(tree);
605 p = print_pet_expr(p, expr, 0, ref2expr);
606 pet_expr_free(expr);
607 p = isl_printer_print_str(p, "; ");
608 expr = pet_tree_loop_get_cond(tree);
609 p = print_pet_expr(p, expr, 1, ref2expr);
610 pet_expr_free(expr);
611 p = isl_printer_print_str(p, "; ");
612 p = print_pet_expr(p, expr_iv, 1, ref2expr);
613 p = isl_printer_print_str(p, " += ");
614 expr = pet_tree_loop_get_inc(tree);
615 p = print_pet_expr(p, expr, 0, ref2expr);
616 pet_expr_free(expr);
617 p = isl_printer_print_str(p, ") {");
618 p = isl_printer_end_line(p);
620 pet_expr_free(expr_iv);
622 p = isl_printer_indent(p, 2);
623 body = pet_tree_loop_get_body(tree);
624 p = print_pet_tree(p, body, 1, ref2expr);
625 pet_tree_free(body);
626 p = isl_printer_indent(p, -2);
628 p = isl_printer_start_line(p);
629 p = isl_printer_print_str(p, "}");
630 p = isl_printer_end_line(p);
632 return p;
635 /* Print "tree" to "p", where "tree" is of type pet_tree_while or
636 * pet_tree_infinite_loop.
638 * The access subexpressions are replaced by the isl_ast_expr
639 * associated to its reference identifier in "ref2expr".
641 * pet_tree_loop_get_cond returns "1" when called on a tree of type
642 * pet_tree_infinite_loop, so we can treat them in the same way
643 * as trees of type pet_tree_while.
645 static __isl_give isl_printer *print_pet_tree_while(__isl_take isl_printer *p,
646 __isl_keep pet_tree *tree, __isl_keep isl_id_to_ast_expr *ref2expr)
648 pet_expr *expr;
649 pet_tree *body;
651 p = isl_printer_start_line(p);
652 p = isl_printer_print_str(p, "while (");
653 expr = pet_tree_loop_get_cond(tree);
654 p = print_pet_expr(p, expr, 1, ref2expr);
655 pet_expr_free(expr);
656 p = isl_printer_print_str(p, ") {");
657 p = isl_printer_end_line(p);
659 p = isl_printer_indent(p, 2);
660 body = pet_tree_loop_get_body(tree);
661 p = print_pet_tree(p, body, 1, ref2expr);
662 pet_tree_free(body);
663 p = isl_printer_indent(p, -2);
665 p = isl_printer_start_line(p);
666 p = isl_printer_print_str(p, "}");
667 p = isl_printer_end_line(p);
669 return p;
672 /* Print "tree" to "p", where "tree" is of type pet_tree_decl_init.
674 * We assume all variables have already been declared, so we
675 * only print the assignment implied by the declaration initialization.
677 * The access subexpressions are replaced by the isl_ast_expr
678 * associated to its reference identifier in "ref2expr".
680 static __isl_give isl_printer *print_pet_tree_decl_init(
681 __isl_take isl_printer *p, __isl_keep pet_tree *tree,
682 __isl_keep isl_id_to_ast_expr *ref2expr)
684 pet_expr *var, *init;
686 p = isl_printer_start_line(p);
688 var = pet_tree_decl_get_var(tree);
689 p = print_pet_expr(p, var, 1, ref2expr);
690 pet_expr_free(var);
692 p = isl_printer_print_str(p, " = ");
694 init = pet_tree_decl_get_init(tree);
695 p = print_pet_expr(p, init, 1, ref2expr);
696 pet_expr_free(init);
698 p = isl_printer_print_str(p, ";");
699 p = isl_printer_end_line(p);
701 return p;
704 /* Print "tree" to "p", where "tree" is of type pet_tree_return.
706 * The access subexpressions are replaced by the isl_ast_expr
707 * associated to its reference identifier in "ref2expr".
709 static __isl_give isl_printer *print_pet_tree_return(__isl_take isl_printer *p,
710 __isl_keep pet_tree *tree, __isl_keep isl_id_to_ast_expr *ref2expr)
712 pet_expr *expr;
714 expr = pet_tree_expr_get_expr(tree);
715 p = isl_printer_start_line(p);
716 p = isl_printer_print_str(p, "return ");
717 p = print_pet_expr(p, expr, 1, ref2expr);
718 p = isl_printer_print_str(p, ";");
719 p = isl_printer_end_line(p);
720 pet_expr_free(expr);
722 return p;
725 /* Print "tree" to "p".
727 * If "in_block" is set, then the caller has just printed a block,
728 * so there is no need to print one for this node.
730 * The access subexpressions are replaced by the isl_ast_expr
731 * associated to its reference identifier in "ref2expr".
733 * We assume all variables have already been declared,
734 * so there is nothing to print for nodes of type pet_tree_decl.
736 static __isl_give isl_printer *print_pet_tree(__isl_take isl_printer *p,
737 __isl_keep pet_tree *tree, int in_block,
738 __isl_keep isl_id_to_ast_expr *ref2expr)
740 pet_expr *expr;
741 enum pet_tree_type type;
743 type = pet_tree_get_type(tree);
744 switch (type) {
745 case pet_tree_error:
746 return isl_printer_free(p);
747 case pet_tree_block:
748 return print_pet_tree_block(p, tree, in_block, ref2expr);
749 case pet_tree_break:
750 case pet_tree_continue:
751 p = isl_printer_start_line(p);
752 if (type == pet_tree_break)
753 p = isl_printer_print_str(p, "break;");
754 else
755 p = isl_printer_print_str(p, "continue;");
756 return isl_printer_end_line(p);
757 case pet_tree_expr:
758 expr = pet_tree_expr_get_expr(tree);
759 p = isl_printer_start_line(p);
760 p = print_pet_expr(p, expr, 1, ref2expr);
761 p = isl_printer_print_str(p, ";");
762 p = isl_printer_end_line(p);
763 pet_expr_free(expr);
764 break;
765 case pet_tree_return:
766 return print_pet_tree_return(p, tree, ref2expr);
767 case pet_tree_if:
768 case pet_tree_if_else:
769 return print_pet_tree_if(p, tree, ref2expr);
770 case pet_tree_for:
771 return print_pet_tree_for(p, tree, ref2expr);
772 case pet_tree_while:
773 case pet_tree_infinite_loop:
774 return print_pet_tree_while(p, tree, ref2expr);
775 case pet_tree_decl:
776 return p;
777 case pet_tree_decl_init:
778 return print_pet_tree_decl_init(p, tree, ref2expr);
781 return p;
784 /* Print "stmt" to "p".
786 * The access expressions in "stmt" are replaced by the isl_ast_expr
787 * associated to its reference identifier in "ref2expr".
789 * If the statement is an assume or a kill statement, then we print nothing.
791 __isl_give isl_printer *pet_stmt_print_body(struct pet_stmt *stmt,
792 __isl_take isl_printer *p, __isl_keep isl_id_to_ast_expr *ref2expr)
794 if (!stmt)
795 return isl_printer_free(p);
796 if (pet_stmt_is_assume(stmt))
797 return p;
798 if (pet_stmt_is_kill(stmt))
799 return p;
800 p = print_pet_tree(p, stmt->body, 0, ref2expr);
802 return p;
805 /* Copy the contents of "input" from offset "start" to "end" to "output".
807 int copy(FILE *input, FILE *output, long start, long end)
809 char buffer[1024];
810 size_t n, m;
812 if (end < 0) {
813 fseek(input, 0, SEEK_END);
814 end = ftell(input);
817 fseek(input, start, SEEK_SET);
819 while (start < end) {
820 n = end - start;
821 if (n > 1024)
822 n = 1024;
823 n = fread(buffer, 1, n, input);
824 if (n <= 0)
825 return -1;
826 m = fwrite(buffer, 1, n, output);
827 if (n != m)
828 return -1;
829 start += n;
832 return 0;