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
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
36 #include <isl/space.h>
37 #include <isl/local_space.h>
40 #include <isl/ast_build.h>
41 #include <isl/printer.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
)
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
);
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
)
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))
83 if (expr
->args
[i
]->type
!= pet_expr_access
) {
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
)
105 r
= pet_tree_foreach_access_expr(stmt
->body
,
106 &depends_on_expressions
, &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
)
125 for (i
= 0; i
< scop
->n_stmt
; ++i
) {
126 int ok
= pet_stmt_can_build_ast_exprs(scop
->stmts
[i
]);
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
,
148 __isl_give isl_ast_expr
*(*fn_expr
)(__isl_take isl_ast_expr
*expr
,
149 __isl_keep isl_id
*id
, void *user
);
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
)
174 isl_space
*space
, *space2
;
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,
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
) {
197 aff
= isl_aff_var_on_domain(isl_local_space_copy(ls
),
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
)
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
) {
230 isl_ast_expr
*ast_expr
;
232 if (!isl_multi_pw_aff_involves_dims(expr
->acc
.index
,
233 isl_dim_in
, dim
+ i
, 1))
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
);
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
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
)
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
;
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
);
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
);
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
);
294 ast_expr
= isl_ast_expr_substitute_ids(ast_expr
, id2expr
);
296 ast_expr
= data
->fn_expr(ast_expr
, expr
->acc
.ref_id
,
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
;
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
];
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,
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
)
355 switch (expr
->type
) {
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
);
366 return pet_expr_op_build_ast_expr(expr
, data
);
368 isl_die(pet_expr_get_ctx(expr
), isl_error_unsupported
,
369 "unsupported expression type", return NULL
);
371 isl_die(pet_expr_get_ctx(expr
), isl_error_unsupported
,
372 "unsupported expression type", return NULL
);
378 /* Construct an AST expression from the access expression "expr" and
379 * add the mapping from reference identifier to AST expression to
382 static int add_access(__isl_keep pet_expr
*expr
, void *user
)
384 struct pet_build_ast_expr_data
*data
= user
;
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
);
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"
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
};
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
;
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
;
446 p
= isl_printer_print_str(p
, "(");
447 p
= isl_printer_print_ast_expr(p
, ast_expr
);
449 p
= isl_printer_print_str(p
, ")");
450 isl_ast_expr_free(ast_expr
);
455 /* Is "op" a postfix operator?
457 static int is_postfix(enum pet_op_type op
)
460 case pet_op_post_inc
:
461 case pet_op_post_dec
:
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
) {
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
));
489 p
= print_pet_expr(p
, expr
->args
[pet_bin_lhs
], 0,
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,
498 p
= print_pet_expr(p
, expr
->args
[pet_ter_cond
], 0,
500 p
= isl_printer_print_str(p
, " ? ");
501 p
= print_pet_expr(p
, expr
->args
[pet_ter_true
], 0,
503 p
= isl_printer_print_str(p
, " : ");
504 p
= print_pet_expr(p
, expr
->args
[pet_ter_false
], 0,
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
)
525 switch (expr
->type
) {
527 p
= isl_printer_free(p
);
530 p
= isl_printer_print_val(p
, expr
->i
);
532 case pet_expr_double
:
533 p
= isl_printer_print_str(p
, expr
->d
.s
);
535 case pet_expr_access
:
536 p
= print_access(p
, expr
, ref2expr
);
540 p
= isl_printer_print_str(p
, "(");
541 p
= print_op(p
, expr
, ref2expr
);
543 p
= isl_printer_print_str(p
, ")");
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
) {
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
, ")");
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
);
563 p
= isl_printer_print_str(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
)
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
) {
600 child
= pet_tree_block_get_child(tree
, i
);
601 p
= print_pet_tree(p
, child
, 0, ref2expr
);
602 pet_tree_free(child
);
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
);
615 /* Print "tree" to "p", where "tree" is of type pet_tree_if or
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
)
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
);
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
);
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
);
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
);
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
;
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
);
683 p
= isl_printer_print_str(p
, "; ");
684 expr
= pet_tree_loop_get_cond(tree
);
685 p
= print_pet_expr(p
, expr
, 1, ref2expr
);
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
);
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
);
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
);
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
)
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
);
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
);
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
);
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
);
768 p
= isl_printer_print_str(p
, " = ");
770 init
= pet_tree_decl_get_init(tree
);
771 p
= print_pet_expr(p
, init
, 1, ref2expr
);
774 p
= isl_printer_print_str(p
, ";");
775 p
= isl_printer_end_line(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
)
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
);
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
)
817 enum pet_tree_type type
;
819 type
= pet_tree_get_type(tree
);
822 return isl_printer_free(p
);
824 return print_pet_tree_block(p
, tree
, in_block
, ref2expr
);
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;");
831 p
= isl_printer_print_str(p
, "continue;");
832 return isl_printer_end_line(p
);
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
);
841 case pet_tree_return
:
842 return print_pet_tree_return(p
, tree
, ref2expr
);
844 case pet_tree_if_else
:
845 return print_pet_tree_if(p
, tree
, ref2expr
);
847 return print_pet_tree_for(p
, tree
, ref2expr
);
849 case pet_tree_infinite_loop
:
850 return print_pet_tree_while(p
, tree
, ref2expr
);
853 case pet_tree_decl_init
:
854 return print_pet_tree_decl_init(p
, tree
, ref2expr
);
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
)
871 return isl_printer_free(p
);
872 if (pet_stmt_is_assume(stmt
))
874 if (pet_stmt_is_kill(stmt
))
876 p
= print_pet_tree(p
, stmt
->body
, 0, ref2expr
);
881 /* Copy the contents of "input" from offset "start" to "end" to "output".
883 int copy(FILE *input
, FILE *output
, long start
, long end
)
889 fseek(input
, 0, SEEK_END
);
893 fseek(input
, start
, SEEK_SET
);
895 while (start
< end
) {
899 n
= fread(buffer
, 1, n
, input
);
902 m
= fwrite(buffer
, 1, n
, output
);