Line data Source code
1 : /*
2 : * Copyright 2012-2013 Ecole Normale Superieure
3 : *
4 : * Use of this software is governed by the MIT license
5 : *
6 : * Written by Sven Verdoolaege,
7 : * Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
8 : */
9 :
10 : #include <string.h>
11 :
12 : #include <isl/id.h>
13 : #include <isl/val.h>
14 : #include <isl_ast_private.h>
15 :
16 : #undef BASE
17 : #define BASE ast_expr
18 :
19 : #include <isl_list_templ.c>
20 :
21 : #undef BASE
22 : #define BASE ast_node
23 :
24 : #include <isl_list_templ.c>
25 :
26 0 : isl_ctx *isl_ast_print_options_get_ctx(
27 : __isl_keep isl_ast_print_options *options)
28 : {
29 0 : return options ? options->ctx : NULL;
30 : }
31 :
32 0 : __isl_give isl_ast_print_options *isl_ast_print_options_alloc(isl_ctx *ctx)
33 : {
34 : isl_ast_print_options *options;
35 :
36 0 : options = isl_calloc_type(ctx, isl_ast_print_options);
37 0 : if (!options)
38 0 : return NULL;
39 :
40 0 : options->ctx = ctx;
41 0 : isl_ctx_ref(ctx);
42 0 : options->ref = 1;
43 :
44 0 : return options;
45 : }
46 :
47 0 : __isl_give isl_ast_print_options *isl_ast_print_options_dup(
48 : __isl_keep isl_ast_print_options *options)
49 : {
50 : isl_ctx *ctx;
51 : isl_ast_print_options *dup;
52 :
53 0 : if (!options)
54 0 : return NULL;
55 :
56 0 : ctx = isl_ast_print_options_get_ctx(options);
57 0 : dup = isl_ast_print_options_alloc(ctx);
58 0 : if (!dup)
59 0 : return NULL;
60 :
61 0 : dup->print_for = options->print_for;
62 0 : dup->print_for_user = options->print_for_user;
63 0 : dup->print_user = options->print_user;
64 0 : dup->print_user_user = options->print_user_user;
65 :
66 0 : return dup;
67 : }
68 :
69 0 : __isl_give isl_ast_print_options *isl_ast_print_options_cow(
70 : __isl_take isl_ast_print_options *options)
71 : {
72 0 : if (!options)
73 0 : return NULL;
74 :
75 0 : if (options->ref == 1)
76 0 : return options;
77 0 : options->ref--;
78 0 : return isl_ast_print_options_dup(options);
79 : }
80 :
81 0 : __isl_give isl_ast_print_options *isl_ast_print_options_copy(
82 : __isl_keep isl_ast_print_options *options)
83 : {
84 0 : if (!options)
85 0 : return NULL;
86 :
87 0 : options->ref++;
88 0 : return options;
89 : }
90 :
91 0 : __isl_null isl_ast_print_options *isl_ast_print_options_free(
92 : __isl_take isl_ast_print_options *options)
93 : {
94 0 : if (!options)
95 0 : return NULL;
96 :
97 0 : if (--options->ref > 0)
98 0 : return NULL;
99 :
100 0 : isl_ctx_deref(options->ctx);
101 :
102 0 : free(options);
103 0 : return NULL;
104 : }
105 :
106 : /* Set the print_user callback of "options" to "print_user".
107 : *
108 : * If this callback is set, then it used to print user nodes in the AST.
109 : * Otherwise, the expression associated to the user node is printed.
110 : */
111 0 : __isl_give isl_ast_print_options *isl_ast_print_options_set_print_user(
112 : __isl_take isl_ast_print_options *options,
113 : __isl_give isl_printer *(*print_user)(__isl_take isl_printer *p,
114 : __isl_take isl_ast_print_options *options,
115 : __isl_keep isl_ast_node *node, void *user),
116 : void *user)
117 : {
118 0 : options = isl_ast_print_options_cow(options);
119 0 : if (!options)
120 0 : return NULL;
121 :
122 0 : options->print_user = print_user;
123 0 : options->print_user_user = user;
124 :
125 0 : return options;
126 : }
127 :
128 : /* Set the print_for callback of "options" to "print_for".
129 : *
130 : * If this callback is set, then it used to print for nodes in the AST.
131 : */
132 0 : __isl_give isl_ast_print_options *isl_ast_print_options_set_print_for(
133 : __isl_take isl_ast_print_options *options,
134 : __isl_give isl_printer *(*print_for)(__isl_take isl_printer *p,
135 : __isl_take isl_ast_print_options *options,
136 : __isl_keep isl_ast_node *node, void *user),
137 : void *user)
138 : {
139 0 : options = isl_ast_print_options_cow(options);
140 0 : if (!options)
141 0 : return NULL;
142 :
143 0 : options->print_for = print_for;
144 0 : options->print_for_user = user;
145 :
146 0 : return options;
147 : }
148 :
149 0 : __isl_give isl_ast_expr *isl_ast_expr_copy(__isl_keep isl_ast_expr *expr)
150 : {
151 0 : if (!expr)
152 0 : return NULL;
153 :
154 0 : expr->ref++;
155 0 : return expr;
156 : }
157 :
158 0 : __isl_give isl_ast_expr *isl_ast_expr_dup(__isl_keep isl_ast_expr *expr)
159 : {
160 : int i;
161 : isl_ctx *ctx;
162 : isl_ast_expr *dup;
163 :
164 0 : if (!expr)
165 0 : return NULL;
166 :
167 0 : ctx = isl_ast_expr_get_ctx(expr);
168 0 : switch (expr->type) {
169 : case isl_ast_expr_int:
170 0 : dup = isl_ast_expr_from_val(isl_val_copy(expr->u.v));
171 0 : break;
172 : case isl_ast_expr_id:
173 0 : dup = isl_ast_expr_from_id(isl_id_copy(expr->u.id));
174 0 : break;
175 : case isl_ast_expr_op:
176 0 : dup = isl_ast_expr_alloc_op(ctx,
177 0 : expr->u.op.op, expr->u.op.n_arg);
178 0 : if (!dup)
179 0 : return NULL;
180 0 : for (i = 0; i < expr->u.op.n_arg; ++i)
181 0 : dup->u.op.args[i] =
182 0 : isl_ast_expr_copy(expr->u.op.args[i]);
183 0 : break;
184 : case isl_ast_expr_error:
185 0 : dup = NULL;
186 : }
187 :
188 0 : if (!dup)
189 0 : return NULL;
190 :
191 0 : return dup;
192 : }
193 :
194 0 : __isl_give isl_ast_expr *isl_ast_expr_cow(__isl_take isl_ast_expr *expr)
195 : {
196 0 : if (!expr)
197 0 : return NULL;
198 :
199 0 : if (expr->ref == 1)
200 0 : return expr;
201 0 : expr->ref--;
202 0 : return isl_ast_expr_dup(expr);
203 : }
204 :
205 0 : __isl_null isl_ast_expr *isl_ast_expr_free(__isl_take isl_ast_expr *expr)
206 : {
207 : int i;
208 :
209 0 : if (!expr)
210 0 : return NULL;
211 :
212 0 : if (--expr->ref > 0)
213 0 : return NULL;
214 :
215 0 : isl_ctx_deref(expr->ctx);
216 :
217 0 : switch (expr->type) {
218 : case isl_ast_expr_int:
219 0 : isl_val_free(expr->u.v);
220 0 : break;
221 : case isl_ast_expr_id:
222 0 : isl_id_free(expr->u.id);
223 0 : break;
224 : case isl_ast_expr_op:
225 0 : if (expr->u.op.args)
226 0 : for (i = 0; i < expr->u.op.n_arg; ++i)
227 0 : isl_ast_expr_free(expr->u.op.args[i]);
228 0 : free(expr->u.op.args);
229 0 : break;
230 : case isl_ast_expr_error:
231 0 : break;
232 : }
233 :
234 0 : free(expr);
235 0 : return NULL;
236 : }
237 :
238 0 : isl_ctx *isl_ast_expr_get_ctx(__isl_keep isl_ast_expr *expr)
239 : {
240 0 : return expr ? expr->ctx : NULL;
241 : }
242 :
243 0 : enum isl_ast_expr_type isl_ast_expr_get_type(__isl_keep isl_ast_expr *expr)
244 : {
245 0 : return expr ? expr->type : isl_ast_expr_error;
246 : }
247 :
248 : /* Return the integer value represented by "expr".
249 : */
250 0 : __isl_give isl_val *isl_ast_expr_get_val(__isl_keep isl_ast_expr *expr)
251 : {
252 0 : if (!expr)
253 0 : return NULL;
254 0 : if (expr->type != isl_ast_expr_int)
255 0 : isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
256 : "expression not an int", return NULL);
257 0 : return isl_val_copy(expr->u.v);
258 : }
259 :
260 0 : __isl_give isl_id *isl_ast_expr_get_id(__isl_keep isl_ast_expr *expr)
261 : {
262 0 : if (!expr)
263 0 : return NULL;
264 0 : if (expr->type != isl_ast_expr_id)
265 0 : isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
266 : "expression not an identifier", return NULL);
267 :
268 0 : return isl_id_copy(expr->u.id);
269 : }
270 :
271 0 : enum isl_ast_op_type isl_ast_expr_get_op_type(__isl_keep isl_ast_expr *expr)
272 : {
273 0 : if (!expr)
274 0 : return isl_ast_op_error;
275 0 : if (expr->type != isl_ast_expr_op)
276 0 : isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
277 : "expression not an operation", return isl_ast_op_error);
278 0 : return expr->u.op.op;
279 : }
280 :
281 0 : int isl_ast_expr_get_op_n_arg(__isl_keep isl_ast_expr *expr)
282 : {
283 0 : if (!expr)
284 0 : return -1;
285 0 : if (expr->type != isl_ast_expr_op)
286 0 : isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
287 : "expression not an operation", return -1);
288 0 : return expr->u.op.n_arg;
289 : }
290 :
291 0 : __isl_give isl_ast_expr *isl_ast_expr_get_op_arg(__isl_keep isl_ast_expr *expr,
292 : int pos)
293 : {
294 0 : if (!expr)
295 0 : return NULL;
296 0 : if (expr->type != isl_ast_expr_op)
297 0 : isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
298 : "expression not an operation", return NULL);
299 0 : if (pos < 0 || pos >= expr->u.op.n_arg)
300 0 : isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
301 : "index out of bounds", return NULL);
302 :
303 0 : return isl_ast_expr_copy(expr->u.op.args[pos]);
304 : }
305 :
306 : /* Replace the argument at position "pos" of "expr" by "arg".
307 : */
308 0 : __isl_give isl_ast_expr *isl_ast_expr_set_op_arg(__isl_take isl_ast_expr *expr,
309 : int pos, __isl_take isl_ast_expr *arg)
310 : {
311 0 : expr = isl_ast_expr_cow(expr);
312 0 : if (!expr || !arg)
313 : goto error;
314 0 : if (expr->type != isl_ast_expr_op)
315 0 : isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
316 : "expression not an operation", goto error);
317 0 : if (pos < 0 || pos >= expr->u.op.n_arg)
318 0 : isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
319 : "index out of bounds", goto error);
320 :
321 0 : isl_ast_expr_free(expr->u.op.args[pos]);
322 0 : expr->u.op.args[pos] = arg;
323 :
324 0 : return expr;
325 : error:
326 0 : isl_ast_expr_free(arg);
327 0 : return isl_ast_expr_free(expr);
328 : }
329 :
330 : /* Is "expr1" equal to "expr2"?
331 : */
332 0 : isl_bool isl_ast_expr_is_equal(__isl_keep isl_ast_expr *expr1,
333 : __isl_keep isl_ast_expr *expr2)
334 : {
335 : int i;
336 :
337 0 : if (!expr1 || !expr2)
338 0 : return isl_bool_error;
339 :
340 0 : if (expr1 == expr2)
341 0 : return isl_bool_true;
342 0 : if (expr1->type != expr2->type)
343 0 : return isl_bool_false;
344 0 : switch (expr1->type) {
345 : case isl_ast_expr_int:
346 0 : return isl_val_eq(expr1->u.v, expr2->u.v);
347 : case isl_ast_expr_id:
348 0 : return expr1->u.id == expr2->u.id;
349 : case isl_ast_expr_op:
350 0 : if (expr1->u.op.op != expr2->u.op.op)
351 0 : return isl_bool_false;
352 0 : if (expr1->u.op.n_arg != expr2->u.op.n_arg)
353 0 : return isl_bool_false;
354 0 : for (i = 0; i < expr1->u.op.n_arg; ++i) {
355 : isl_bool equal;
356 0 : equal = isl_ast_expr_is_equal(expr1->u.op.args[i],
357 0 : expr2->u.op.args[i]);
358 0 : if (equal < 0 || !equal)
359 0 : return equal;
360 : }
361 0 : return isl_bool_true;
362 : case isl_ast_expr_error:
363 0 : return isl_bool_error;
364 : }
365 :
366 0 : isl_die(isl_ast_expr_get_ctx(expr1), isl_error_internal,
367 : "unhandled case", return isl_bool_error);
368 : }
369 :
370 : /* Create a new operation expression of operation type "op",
371 : * with "n_arg" as yet unspecified arguments.
372 : */
373 0 : __isl_give isl_ast_expr *isl_ast_expr_alloc_op(isl_ctx *ctx,
374 : enum isl_ast_op_type op, int n_arg)
375 : {
376 : isl_ast_expr *expr;
377 :
378 0 : expr = isl_calloc_type(ctx, isl_ast_expr);
379 0 : if (!expr)
380 0 : return NULL;
381 :
382 0 : expr->ctx = ctx;
383 0 : isl_ctx_ref(ctx);
384 0 : expr->ref = 1;
385 0 : expr->type = isl_ast_expr_op;
386 0 : expr->u.op.op = op;
387 0 : expr->u.op.n_arg = n_arg;
388 0 : expr->u.op.args = isl_calloc_array(ctx, isl_ast_expr *, n_arg);
389 :
390 0 : if (n_arg && !expr->u.op.args)
391 0 : return isl_ast_expr_free(expr);
392 :
393 0 : return expr;
394 : }
395 :
396 : /* Create a new id expression representing "id".
397 : */
398 0 : __isl_give isl_ast_expr *isl_ast_expr_from_id(__isl_take isl_id *id)
399 : {
400 : isl_ctx *ctx;
401 : isl_ast_expr *expr;
402 :
403 0 : if (!id)
404 0 : return NULL;
405 :
406 0 : ctx = isl_id_get_ctx(id);
407 0 : expr = isl_calloc_type(ctx, isl_ast_expr);
408 0 : if (!expr)
409 0 : goto error;
410 :
411 0 : expr->ctx = ctx;
412 0 : isl_ctx_ref(ctx);
413 0 : expr->ref = 1;
414 0 : expr->type = isl_ast_expr_id;
415 0 : expr->u.id = id;
416 :
417 0 : return expr;
418 : error:
419 0 : isl_id_free(id);
420 0 : return NULL;
421 : }
422 :
423 : /* Create a new integer expression representing "i".
424 : */
425 0 : __isl_give isl_ast_expr *isl_ast_expr_alloc_int_si(isl_ctx *ctx, int i)
426 : {
427 : isl_ast_expr *expr;
428 :
429 0 : expr = isl_calloc_type(ctx, isl_ast_expr);
430 0 : if (!expr)
431 0 : return NULL;
432 :
433 0 : expr->ctx = ctx;
434 0 : isl_ctx_ref(ctx);
435 0 : expr->ref = 1;
436 0 : expr->type = isl_ast_expr_int;
437 0 : expr->u.v = isl_val_int_from_si(ctx, i);
438 0 : if (!expr->u.v)
439 0 : return isl_ast_expr_free(expr);
440 :
441 0 : return expr;
442 : }
443 :
444 : /* Create a new integer expression representing "v".
445 : */
446 0 : __isl_give isl_ast_expr *isl_ast_expr_from_val(__isl_take isl_val *v)
447 : {
448 : isl_ctx *ctx;
449 : isl_ast_expr *expr;
450 :
451 0 : if (!v)
452 0 : return NULL;
453 0 : if (!isl_val_is_int(v))
454 0 : isl_die(isl_val_get_ctx(v), isl_error_invalid,
455 : "expecting integer value", goto error);
456 :
457 0 : ctx = isl_val_get_ctx(v);
458 0 : expr = isl_calloc_type(ctx, isl_ast_expr);
459 0 : if (!expr)
460 0 : goto error;
461 :
462 0 : expr->ctx = ctx;
463 0 : isl_ctx_ref(ctx);
464 0 : expr->ref = 1;
465 0 : expr->type = isl_ast_expr_int;
466 0 : expr->u.v = v;
467 :
468 0 : return expr;
469 : error:
470 0 : isl_val_free(v);
471 0 : return NULL;
472 : }
473 :
474 : /* Create an expression representing the unary operation "type" applied to
475 : * "arg".
476 : */
477 0 : __isl_give isl_ast_expr *isl_ast_expr_alloc_unary(enum isl_ast_op_type type,
478 : __isl_take isl_ast_expr *arg)
479 : {
480 : isl_ctx *ctx;
481 0 : isl_ast_expr *expr = NULL;
482 :
483 0 : if (!arg)
484 0 : return NULL;
485 :
486 0 : ctx = isl_ast_expr_get_ctx(arg);
487 0 : expr = isl_ast_expr_alloc_op(ctx, type, 1);
488 0 : if (!expr)
489 0 : goto error;
490 :
491 0 : expr->u.op.args[0] = arg;
492 :
493 0 : return expr;
494 : error:
495 0 : isl_ast_expr_free(arg);
496 0 : return NULL;
497 : }
498 :
499 : /* Create an expression representing the negation of "arg".
500 : */
501 0 : __isl_give isl_ast_expr *isl_ast_expr_neg(__isl_take isl_ast_expr *arg)
502 : {
503 0 : return isl_ast_expr_alloc_unary(isl_ast_op_minus, arg);
504 : }
505 :
506 : /* Create an expression representing the address of "expr".
507 : */
508 0 : __isl_give isl_ast_expr *isl_ast_expr_address_of(__isl_take isl_ast_expr *expr)
509 : {
510 0 : if (!expr)
511 0 : return NULL;
512 :
513 0 : if (isl_ast_expr_get_type(expr) != isl_ast_expr_op ||
514 0 : isl_ast_expr_get_op_type(expr) != isl_ast_op_access)
515 0 : isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
516 : "can only take address of access expressions",
517 : return isl_ast_expr_free(expr));
518 :
519 0 : return isl_ast_expr_alloc_unary(isl_ast_op_address_of, expr);
520 : }
521 :
522 : /* Create an expression representing the binary operation "type"
523 : * applied to "expr1" and "expr2".
524 : */
525 0 : __isl_give isl_ast_expr *isl_ast_expr_alloc_binary(enum isl_ast_op_type type,
526 : __isl_take isl_ast_expr *expr1, __isl_take isl_ast_expr *expr2)
527 : {
528 : isl_ctx *ctx;
529 0 : isl_ast_expr *expr = NULL;
530 :
531 0 : if (!expr1 || !expr2)
532 : goto error;
533 :
534 0 : ctx = isl_ast_expr_get_ctx(expr1);
535 0 : expr = isl_ast_expr_alloc_op(ctx, type, 2);
536 0 : if (!expr)
537 0 : goto error;
538 :
539 0 : expr->u.op.args[0] = expr1;
540 0 : expr->u.op.args[1] = expr2;
541 :
542 0 : return expr;
543 : error:
544 0 : isl_ast_expr_free(expr1);
545 0 : isl_ast_expr_free(expr2);
546 0 : return NULL;
547 : }
548 :
549 : /* Create an expression representing the sum of "expr1" and "expr2".
550 : */
551 0 : __isl_give isl_ast_expr *isl_ast_expr_add(__isl_take isl_ast_expr *expr1,
552 : __isl_take isl_ast_expr *expr2)
553 : {
554 0 : return isl_ast_expr_alloc_binary(isl_ast_op_add, expr1, expr2);
555 : }
556 :
557 : /* Create an expression representing the difference of "expr1" and "expr2".
558 : */
559 0 : __isl_give isl_ast_expr *isl_ast_expr_sub(__isl_take isl_ast_expr *expr1,
560 : __isl_take isl_ast_expr *expr2)
561 : {
562 0 : return isl_ast_expr_alloc_binary(isl_ast_op_sub, expr1, expr2);
563 : }
564 :
565 : /* Create an expression representing the product of "expr1" and "expr2".
566 : */
567 0 : __isl_give isl_ast_expr *isl_ast_expr_mul(__isl_take isl_ast_expr *expr1,
568 : __isl_take isl_ast_expr *expr2)
569 : {
570 0 : return isl_ast_expr_alloc_binary(isl_ast_op_mul, expr1, expr2);
571 : }
572 :
573 : /* Create an expression representing the quotient of "expr1" and "expr2".
574 : */
575 0 : __isl_give isl_ast_expr *isl_ast_expr_div(__isl_take isl_ast_expr *expr1,
576 : __isl_take isl_ast_expr *expr2)
577 : {
578 0 : return isl_ast_expr_alloc_binary(isl_ast_op_div, expr1, expr2);
579 : }
580 :
581 : /* Create an expression representing the quotient of the integer
582 : * division of "expr1" by "expr2", where "expr1" is known to be
583 : * non-negative.
584 : */
585 0 : __isl_give isl_ast_expr *isl_ast_expr_pdiv_q(__isl_take isl_ast_expr *expr1,
586 : __isl_take isl_ast_expr *expr2)
587 : {
588 0 : return isl_ast_expr_alloc_binary(isl_ast_op_pdiv_q, expr1, expr2);
589 : }
590 :
591 : /* Create an expression representing the remainder of the integer
592 : * division of "expr1" by "expr2", where "expr1" is known to be
593 : * non-negative.
594 : */
595 0 : __isl_give isl_ast_expr *isl_ast_expr_pdiv_r(__isl_take isl_ast_expr *expr1,
596 : __isl_take isl_ast_expr *expr2)
597 : {
598 0 : return isl_ast_expr_alloc_binary(isl_ast_op_pdiv_r, expr1, expr2);
599 : }
600 :
601 : /* Create an expression representing the conjunction of "expr1" and "expr2".
602 : */
603 0 : __isl_give isl_ast_expr *isl_ast_expr_and(__isl_take isl_ast_expr *expr1,
604 : __isl_take isl_ast_expr *expr2)
605 : {
606 0 : return isl_ast_expr_alloc_binary(isl_ast_op_and, expr1, expr2);
607 : }
608 :
609 : /* Create an expression representing the conjunction of "expr1" and "expr2",
610 : * where "expr2" is evaluated only if "expr1" is evaluated to true.
611 : */
612 0 : __isl_give isl_ast_expr *isl_ast_expr_and_then(__isl_take isl_ast_expr *expr1,
613 : __isl_take isl_ast_expr *expr2)
614 : {
615 0 : return isl_ast_expr_alloc_binary(isl_ast_op_and_then, expr1, expr2);
616 : }
617 :
618 : /* Create an expression representing the disjunction of "expr1" and "expr2".
619 : */
620 0 : __isl_give isl_ast_expr *isl_ast_expr_or(__isl_take isl_ast_expr *expr1,
621 : __isl_take isl_ast_expr *expr2)
622 : {
623 0 : return isl_ast_expr_alloc_binary(isl_ast_op_or, expr1, expr2);
624 : }
625 :
626 : /* Create an expression representing the disjunction of "expr1" and "expr2",
627 : * where "expr2" is evaluated only if "expr1" is evaluated to false.
628 : */
629 0 : __isl_give isl_ast_expr *isl_ast_expr_or_else(__isl_take isl_ast_expr *expr1,
630 : __isl_take isl_ast_expr *expr2)
631 : {
632 0 : return isl_ast_expr_alloc_binary(isl_ast_op_or_else, expr1, expr2);
633 : }
634 :
635 : /* Create an expression representing "expr1" less than or equal to "expr2".
636 : */
637 0 : __isl_give isl_ast_expr *isl_ast_expr_le(__isl_take isl_ast_expr *expr1,
638 : __isl_take isl_ast_expr *expr2)
639 : {
640 0 : return isl_ast_expr_alloc_binary(isl_ast_op_le, expr1, expr2);
641 : }
642 :
643 : /* Create an expression representing "expr1" less than "expr2".
644 : */
645 0 : __isl_give isl_ast_expr *isl_ast_expr_lt(__isl_take isl_ast_expr *expr1,
646 : __isl_take isl_ast_expr *expr2)
647 : {
648 0 : return isl_ast_expr_alloc_binary(isl_ast_op_lt, expr1, expr2);
649 : }
650 :
651 : /* Create an expression representing "expr1" greater than or equal to "expr2".
652 : */
653 0 : __isl_give isl_ast_expr *isl_ast_expr_ge(__isl_take isl_ast_expr *expr1,
654 : __isl_take isl_ast_expr *expr2)
655 : {
656 0 : return isl_ast_expr_alloc_binary(isl_ast_op_ge, expr1, expr2);
657 : }
658 :
659 : /* Create an expression representing "expr1" greater than "expr2".
660 : */
661 0 : __isl_give isl_ast_expr *isl_ast_expr_gt(__isl_take isl_ast_expr *expr1,
662 : __isl_take isl_ast_expr *expr2)
663 : {
664 0 : return isl_ast_expr_alloc_binary(isl_ast_op_gt, expr1, expr2);
665 : }
666 :
667 : /* Create an expression representing "expr1" equal to "expr2".
668 : */
669 0 : __isl_give isl_ast_expr *isl_ast_expr_eq(__isl_take isl_ast_expr *expr1,
670 : __isl_take isl_ast_expr *expr2)
671 : {
672 0 : return isl_ast_expr_alloc_binary(isl_ast_op_eq, expr1, expr2);
673 : }
674 :
675 : /* Create an expression of type "type" with as arguments "arg0" followed
676 : * by "arguments".
677 : */
678 0 : static __isl_give isl_ast_expr *ast_expr_with_arguments(
679 : enum isl_ast_op_type type, __isl_take isl_ast_expr *arg0,
680 : __isl_take isl_ast_expr_list *arguments)
681 : {
682 : int i, n;
683 : isl_ctx *ctx;
684 0 : isl_ast_expr *res = NULL;
685 :
686 0 : if (!arg0 || !arguments)
687 : goto error;
688 :
689 0 : ctx = isl_ast_expr_get_ctx(arg0);
690 0 : n = isl_ast_expr_list_n_ast_expr(arguments);
691 0 : res = isl_ast_expr_alloc_op(ctx, type, 1 + n);
692 0 : if (!res)
693 0 : goto error;
694 0 : for (i = 0; i < n; ++i) {
695 : isl_ast_expr *arg;
696 0 : arg = isl_ast_expr_list_get_ast_expr(arguments, i);
697 0 : res->u.op.args[1 + i] = arg;
698 0 : if (!arg)
699 0 : goto error;
700 : }
701 0 : res->u.op.args[0] = arg0;
702 :
703 0 : isl_ast_expr_list_free(arguments);
704 0 : return res;
705 : error:
706 0 : isl_ast_expr_free(arg0);
707 0 : isl_ast_expr_list_free(arguments);
708 0 : isl_ast_expr_free(res);
709 0 : return NULL;
710 : }
711 :
712 : /* Create an expression representing an access to "array" with index
713 : * expressions "indices".
714 : */
715 0 : __isl_give isl_ast_expr *isl_ast_expr_access(__isl_take isl_ast_expr *array,
716 : __isl_take isl_ast_expr_list *indices)
717 : {
718 0 : return ast_expr_with_arguments(isl_ast_op_access, array, indices);
719 : }
720 :
721 : /* Create an expression representing a call to "function" with argument
722 : * expressions "arguments".
723 : */
724 0 : __isl_give isl_ast_expr *isl_ast_expr_call(__isl_take isl_ast_expr *function,
725 : __isl_take isl_ast_expr_list *arguments)
726 : {
727 0 : return ast_expr_with_arguments(isl_ast_op_call, function, arguments);
728 : }
729 :
730 : /* For each subexpression of "expr" of type isl_ast_expr_id,
731 : * if it appears in "id2expr", then replace it by the corresponding
732 : * expression.
733 : */
734 0 : __isl_give isl_ast_expr *isl_ast_expr_substitute_ids(
735 : __isl_take isl_ast_expr *expr, __isl_take isl_id_to_ast_expr *id2expr)
736 : {
737 : int i;
738 : isl_maybe_isl_ast_expr m;
739 :
740 0 : if (!expr || !id2expr)
741 : goto error;
742 :
743 0 : switch (expr->type) {
744 : case isl_ast_expr_int:
745 0 : break;
746 : case isl_ast_expr_id:
747 0 : m = isl_id_to_ast_expr_try_get(id2expr, expr->u.id);
748 0 : if (m.valid < 0)
749 0 : goto error;
750 0 : if (!m.valid)
751 0 : break;
752 0 : isl_ast_expr_free(expr);
753 0 : expr = m.value;
754 0 : break;
755 : case isl_ast_expr_op:
756 0 : for (i = 0; i < expr->u.op.n_arg; ++i) {
757 : isl_ast_expr *arg;
758 0 : arg = isl_ast_expr_copy(expr->u.op.args[i]);
759 0 : arg = isl_ast_expr_substitute_ids(arg,
760 : isl_id_to_ast_expr_copy(id2expr));
761 0 : if (arg == expr->u.op.args[i]) {
762 0 : isl_ast_expr_free(arg);
763 0 : continue;
764 : }
765 0 : if (!arg)
766 0 : expr = isl_ast_expr_free(expr);
767 0 : expr = isl_ast_expr_cow(expr);
768 0 : if (!expr) {
769 0 : isl_ast_expr_free(arg);
770 0 : break;
771 : }
772 0 : isl_ast_expr_free(expr->u.op.args[i]);
773 0 : expr->u.op.args[i] = arg;
774 : }
775 0 : break;
776 : case isl_ast_expr_error:
777 0 : expr = isl_ast_expr_free(expr);
778 0 : break;
779 : }
780 :
781 0 : isl_id_to_ast_expr_free(id2expr);
782 0 : return expr;
783 : error:
784 0 : isl_ast_expr_free(expr);
785 0 : isl_id_to_ast_expr_free(id2expr);
786 0 : return NULL;
787 : }
788 :
789 0 : isl_ctx *isl_ast_node_get_ctx(__isl_keep isl_ast_node *node)
790 : {
791 0 : return node ? node->ctx : NULL;
792 : }
793 :
794 0 : enum isl_ast_node_type isl_ast_node_get_type(__isl_keep isl_ast_node *node)
795 : {
796 0 : return node ? node->type : isl_ast_node_error;
797 : }
798 :
799 0 : __isl_give isl_ast_node *isl_ast_node_alloc(isl_ctx *ctx,
800 : enum isl_ast_node_type type)
801 : {
802 : isl_ast_node *node;
803 :
804 0 : node = isl_calloc_type(ctx, isl_ast_node);
805 0 : if (!node)
806 0 : return NULL;
807 :
808 0 : node->ctx = ctx;
809 0 : isl_ctx_ref(ctx);
810 0 : node->ref = 1;
811 0 : node->type = type;
812 :
813 0 : return node;
814 : }
815 :
816 : /* Create an if node with the given guard.
817 : *
818 : * The then body needs to be filled in later.
819 : */
820 0 : __isl_give isl_ast_node *isl_ast_node_alloc_if(__isl_take isl_ast_expr *guard)
821 : {
822 : isl_ast_node *node;
823 :
824 0 : if (!guard)
825 0 : return NULL;
826 :
827 0 : node = isl_ast_node_alloc(isl_ast_expr_get_ctx(guard), isl_ast_node_if);
828 0 : if (!node)
829 0 : goto error;
830 0 : node->u.i.guard = guard;
831 :
832 0 : return node;
833 : error:
834 0 : isl_ast_expr_free(guard);
835 0 : return NULL;
836 : }
837 :
838 : /* Create a for node with the given iterator.
839 : *
840 : * The remaining fields need to be filled in later.
841 : */
842 0 : __isl_give isl_ast_node *isl_ast_node_alloc_for(__isl_take isl_id *id)
843 : {
844 : isl_ast_node *node;
845 : isl_ctx *ctx;
846 :
847 0 : if (!id)
848 0 : return NULL;
849 :
850 0 : ctx = isl_id_get_ctx(id);
851 0 : node = isl_ast_node_alloc(ctx, isl_ast_node_for);
852 0 : if (!node)
853 0 : goto error;
854 :
855 0 : node->u.f.iterator = isl_ast_expr_from_id(id);
856 0 : if (!node->u.f.iterator)
857 0 : return isl_ast_node_free(node);
858 :
859 0 : return node;
860 : error:
861 0 : isl_id_free(id);
862 0 : return NULL;
863 : }
864 :
865 : /* Create a mark node, marking "node" with "id".
866 : */
867 0 : __isl_give isl_ast_node *isl_ast_node_alloc_mark(__isl_take isl_id *id,
868 : __isl_take isl_ast_node *node)
869 : {
870 : isl_ctx *ctx;
871 : isl_ast_node *mark;
872 :
873 0 : if (!id || !node)
874 : goto error;
875 :
876 0 : ctx = isl_id_get_ctx(id);
877 0 : mark = isl_ast_node_alloc(ctx, isl_ast_node_mark);
878 0 : if (!mark)
879 0 : goto error;
880 :
881 0 : mark->u.m.mark = id;
882 0 : mark->u.m.node = node;
883 :
884 0 : return mark;
885 : error:
886 0 : isl_id_free(id);
887 0 : isl_ast_node_free(node);
888 0 : return NULL;
889 : }
890 :
891 : /* Create a user node evaluating "expr".
892 : */
893 0 : __isl_give isl_ast_node *isl_ast_node_alloc_user(__isl_take isl_ast_expr *expr)
894 : {
895 : isl_ctx *ctx;
896 : isl_ast_node *node;
897 :
898 0 : if (!expr)
899 0 : return NULL;
900 :
901 0 : ctx = isl_ast_expr_get_ctx(expr);
902 0 : node = isl_ast_node_alloc(ctx, isl_ast_node_user);
903 0 : if (!node)
904 0 : goto error;
905 :
906 0 : node->u.e.expr = expr;
907 :
908 0 : return node;
909 : error:
910 0 : isl_ast_expr_free(expr);
911 0 : return NULL;
912 : }
913 :
914 : /* Create a block node with the given children.
915 : */
916 0 : __isl_give isl_ast_node *isl_ast_node_alloc_block(
917 : __isl_take isl_ast_node_list *list)
918 : {
919 : isl_ast_node *node;
920 : isl_ctx *ctx;
921 :
922 0 : if (!list)
923 0 : return NULL;
924 :
925 0 : ctx = isl_ast_node_list_get_ctx(list);
926 0 : node = isl_ast_node_alloc(ctx, isl_ast_node_block);
927 0 : if (!node)
928 0 : goto error;
929 :
930 0 : node->u.b.children = list;
931 :
932 0 : return node;
933 : error:
934 0 : isl_ast_node_list_free(list);
935 0 : return NULL;
936 : }
937 :
938 : /* Represent the given list of nodes as a single node, either by
939 : * extract the node from a single element list or by creating
940 : * a block node with the list of nodes as children.
941 : */
942 0 : __isl_give isl_ast_node *isl_ast_node_from_ast_node_list(
943 : __isl_take isl_ast_node_list *list)
944 : {
945 : isl_ast_node *node;
946 :
947 0 : if (isl_ast_node_list_n_ast_node(list) != 1)
948 0 : return isl_ast_node_alloc_block(list);
949 :
950 0 : node = isl_ast_node_list_get_ast_node(list, 0);
951 0 : isl_ast_node_list_free(list);
952 :
953 0 : return node;
954 : }
955 :
956 0 : __isl_give isl_ast_node *isl_ast_node_copy(__isl_keep isl_ast_node *node)
957 : {
958 0 : if (!node)
959 0 : return NULL;
960 :
961 0 : node->ref++;
962 0 : return node;
963 : }
964 :
965 0 : __isl_give isl_ast_node *isl_ast_node_dup(__isl_keep isl_ast_node *node)
966 : {
967 : isl_ast_node *dup;
968 :
969 0 : if (!node)
970 0 : return NULL;
971 :
972 0 : dup = isl_ast_node_alloc(isl_ast_node_get_ctx(node), node->type);
973 0 : if (!dup)
974 0 : return NULL;
975 :
976 0 : switch (node->type) {
977 : case isl_ast_node_if:
978 0 : dup->u.i.guard = isl_ast_expr_copy(node->u.i.guard);
979 0 : dup->u.i.then = isl_ast_node_copy(node->u.i.then);
980 0 : dup->u.i.else_node = isl_ast_node_copy(node->u.i.else_node);
981 0 : if (!dup->u.i.guard || !dup->u.i.then ||
982 0 : (node->u.i.else_node && !dup->u.i.else_node))
983 0 : return isl_ast_node_free(dup);
984 0 : break;
985 : case isl_ast_node_for:
986 0 : dup->u.f.iterator = isl_ast_expr_copy(node->u.f.iterator);
987 0 : dup->u.f.init = isl_ast_expr_copy(node->u.f.init);
988 0 : dup->u.f.cond = isl_ast_expr_copy(node->u.f.cond);
989 0 : dup->u.f.inc = isl_ast_expr_copy(node->u.f.inc);
990 0 : dup->u.f.body = isl_ast_node_copy(node->u.f.body);
991 0 : if (!dup->u.f.iterator || !dup->u.f.init || !dup->u.f.cond ||
992 0 : !dup->u.f.inc || !dup->u.f.body)
993 0 : return isl_ast_node_free(dup);
994 0 : break;
995 : case isl_ast_node_block:
996 0 : dup->u.b.children = isl_ast_node_list_copy(node->u.b.children);
997 0 : if (!dup->u.b.children)
998 0 : return isl_ast_node_free(dup);
999 0 : break;
1000 : case isl_ast_node_mark:
1001 0 : dup->u.m.mark = isl_id_copy(node->u.m.mark);
1002 0 : dup->u.m.node = isl_ast_node_copy(node->u.m.node);
1003 0 : if (!dup->u.m.mark || !dup->u.m.node)
1004 0 : return isl_ast_node_free(dup);
1005 0 : break;
1006 : case isl_ast_node_user:
1007 0 : dup->u.e.expr = isl_ast_expr_copy(node->u.e.expr);
1008 0 : if (!dup->u.e.expr)
1009 0 : return isl_ast_node_free(dup);
1010 0 : break;
1011 : case isl_ast_node_error:
1012 0 : break;
1013 : }
1014 :
1015 0 : return dup;
1016 : }
1017 :
1018 0 : __isl_give isl_ast_node *isl_ast_node_cow(__isl_take isl_ast_node *node)
1019 : {
1020 0 : if (!node)
1021 0 : return NULL;
1022 :
1023 0 : if (node->ref == 1)
1024 0 : return node;
1025 0 : node->ref--;
1026 0 : return isl_ast_node_dup(node);
1027 : }
1028 :
1029 0 : __isl_null isl_ast_node *isl_ast_node_free(__isl_take isl_ast_node *node)
1030 : {
1031 0 : if (!node)
1032 0 : return NULL;
1033 :
1034 0 : if (--node->ref > 0)
1035 0 : return NULL;
1036 :
1037 0 : switch (node->type) {
1038 : case isl_ast_node_if:
1039 0 : isl_ast_expr_free(node->u.i.guard);
1040 0 : isl_ast_node_free(node->u.i.then);
1041 0 : isl_ast_node_free(node->u.i.else_node);
1042 0 : break;
1043 : case isl_ast_node_for:
1044 0 : isl_ast_expr_free(node->u.f.iterator);
1045 0 : isl_ast_expr_free(node->u.f.init);
1046 0 : isl_ast_expr_free(node->u.f.cond);
1047 0 : isl_ast_expr_free(node->u.f.inc);
1048 0 : isl_ast_node_free(node->u.f.body);
1049 0 : break;
1050 : case isl_ast_node_block:
1051 0 : isl_ast_node_list_free(node->u.b.children);
1052 0 : break;
1053 : case isl_ast_node_mark:
1054 0 : isl_id_free(node->u.m.mark);
1055 0 : isl_ast_node_free(node->u.m.node);
1056 0 : break;
1057 : case isl_ast_node_user:
1058 0 : isl_ast_expr_free(node->u.e.expr);
1059 0 : break;
1060 : case isl_ast_node_error:
1061 0 : break;
1062 : }
1063 :
1064 0 : isl_id_free(node->annotation);
1065 0 : isl_ctx_deref(node->ctx);
1066 0 : free(node);
1067 :
1068 0 : return NULL;
1069 : }
1070 :
1071 : /* Replace the body of the for node "node" by "body".
1072 : */
1073 0 : __isl_give isl_ast_node *isl_ast_node_for_set_body(
1074 : __isl_take isl_ast_node *node, __isl_take isl_ast_node *body)
1075 : {
1076 0 : node = isl_ast_node_cow(node);
1077 0 : if (!node || !body)
1078 : goto error;
1079 0 : if (node->type != isl_ast_node_for)
1080 0 : isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
1081 : "not a for node", goto error);
1082 :
1083 0 : isl_ast_node_free(node->u.f.body);
1084 0 : node->u.f.body = body;
1085 :
1086 0 : return node;
1087 : error:
1088 0 : isl_ast_node_free(node);
1089 0 : isl_ast_node_free(body);
1090 0 : return NULL;
1091 : }
1092 :
1093 0 : __isl_give isl_ast_node *isl_ast_node_for_get_body(
1094 : __isl_keep isl_ast_node *node)
1095 : {
1096 0 : if (!node)
1097 0 : return NULL;
1098 0 : if (node->type != isl_ast_node_for)
1099 0 : isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
1100 : "not a for node", return NULL);
1101 0 : return isl_ast_node_copy(node->u.f.body);
1102 : }
1103 :
1104 : /* Mark the given for node as being degenerate.
1105 : */
1106 0 : __isl_give isl_ast_node *isl_ast_node_for_mark_degenerate(
1107 : __isl_take isl_ast_node *node)
1108 : {
1109 0 : node = isl_ast_node_cow(node);
1110 0 : if (!node)
1111 0 : return NULL;
1112 0 : node->u.f.degenerate = 1;
1113 0 : return node;
1114 : }
1115 :
1116 0 : isl_bool isl_ast_node_for_is_degenerate(__isl_keep isl_ast_node *node)
1117 : {
1118 0 : if (!node)
1119 0 : return isl_bool_error;
1120 0 : if (node->type != isl_ast_node_for)
1121 0 : isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
1122 : "not a for node", return isl_bool_error);
1123 0 : return node->u.f.degenerate;
1124 : }
1125 :
1126 0 : __isl_give isl_ast_expr *isl_ast_node_for_get_iterator(
1127 : __isl_keep isl_ast_node *node)
1128 : {
1129 0 : if (!node)
1130 0 : return NULL;
1131 0 : if (node->type != isl_ast_node_for)
1132 0 : isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
1133 : "not a for node", return NULL);
1134 0 : return isl_ast_expr_copy(node->u.f.iterator);
1135 : }
1136 :
1137 0 : __isl_give isl_ast_expr *isl_ast_node_for_get_init(
1138 : __isl_keep isl_ast_node *node)
1139 : {
1140 0 : if (!node)
1141 0 : return NULL;
1142 0 : if (node->type != isl_ast_node_for)
1143 0 : isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
1144 : "not a for node", return NULL);
1145 0 : return isl_ast_expr_copy(node->u.f.init);
1146 : }
1147 :
1148 : /* Return the condition expression of the given for node.
1149 : *
1150 : * If the for node is degenerate, then the condition is not explicitly
1151 : * stored in the node. Instead, it is constructed as
1152 : *
1153 : * iterator <= init
1154 : */
1155 0 : __isl_give isl_ast_expr *isl_ast_node_for_get_cond(
1156 : __isl_keep isl_ast_node *node)
1157 : {
1158 0 : if (!node)
1159 0 : return NULL;
1160 0 : if (node->type != isl_ast_node_for)
1161 0 : isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
1162 : "not a for node", return NULL);
1163 0 : if (!node->u.f.degenerate)
1164 0 : return isl_ast_expr_copy(node->u.f.cond);
1165 :
1166 0 : return isl_ast_expr_alloc_binary(isl_ast_op_le,
1167 : isl_ast_expr_copy(node->u.f.iterator),
1168 : isl_ast_expr_copy(node->u.f.init));
1169 : }
1170 :
1171 : /* Return the increment of the given for node.
1172 : *
1173 : * If the for node is degenerate, then the increment is not explicitly
1174 : * stored in the node. We simply return "1".
1175 : */
1176 0 : __isl_give isl_ast_expr *isl_ast_node_for_get_inc(
1177 : __isl_keep isl_ast_node *node)
1178 : {
1179 0 : if (!node)
1180 0 : return NULL;
1181 0 : if (node->type != isl_ast_node_for)
1182 0 : isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
1183 : "not a for node", return NULL);
1184 0 : if (!node->u.f.degenerate)
1185 0 : return isl_ast_expr_copy(node->u.f.inc);
1186 0 : return isl_ast_expr_alloc_int_si(isl_ast_node_get_ctx(node), 1);
1187 : }
1188 :
1189 : /* Replace the then branch of the if node "node" by "child".
1190 : */
1191 0 : __isl_give isl_ast_node *isl_ast_node_if_set_then(
1192 : __isl_take isl_ast_node *node, __isl_take isl_ast_node *child)
1193 : {
1194 0 : node = isl_ast_node_cow(node);
1195 0 : if (!node || !child)
1196 : goto error;
1197 0 : if (node->type != isl_ast_node_if)
1198 0 : isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
1199 : "not an if node", goto error);
1200 :
1201 0 : isl_ast_node_free(node->u.i.then);
1202 0 : node->u.i.then = child;
1203 :
1204 0 : return node;
1205 : error:
1206 0 : isl_ast_node_free(node);
1207 0 : isl_ast_node_free(child);
1208 0 : return NULL;
1209 : }
1210 :
1211 0 : __isl_give isl_ast_node *isl_ast_node_if_get_then(
1212 : __isl_keep isl_ast_node *node)
1213 : {
1214 0 : if (!node)
1215 0 : return NULL;
1216 0 : if (node->type != isl_ast_node_if)
1217 0 : isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
1218 : "not an if node", return NULL);
1219 0 : return isl_ast_node_copy(node->u.i.then);
1220 : }
1221 :
1222 0 : isl_bool isl_ast_node_if_has_else(
1223 : __isl_keep isl_ast_node *node)
1224 : {
1225 0 : if (!node)
1226 0 : return isl_bool_error;
1227 0 : if (node->type != isl_ast_node_if)
1228 0 : isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
1229 : "not an if node", return isl_bool_error);
1230 0 : return node->u.i.else_node != NULL;
1231 : }
1232 :
1233 0 : __isl_give isl_ast_node *isl_ast_node_if_get_else(
1234 : __isl_keep isl_ast_node *node)
1235 : {
1236 0 : if (!node)
1237 0 : return NULL;
1238 0 : if (node->type != isl_ast_node_if)
1239 0 : isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
1240 : "not an if node", return NULL);
1241 0 : return isl_ast_node_copy(node->u.i.else_node);
1242 : }
1243 :
1244 0 : __isl_give isl_ast_expr *isl_ast_node_if_get_cond(
1245 : __isl_keep isl_ast_node *node)
1246 : {
1247 0 : if (!node)
1248 0 : return NULL;
1249 0 : if (node->type != isl_ast_node_if)
1250 0 : isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
1251 : "not a guard node", return NULL);
1252 0 : return isl_ast_expr_copy(node->u.i.guard);
1253 : }
1254 :
1255 0 : __isl_give isl_ast_node_list *isl_ast_node_block_get_children(
1256 : __isl_keep isl_ast_node *node)
1257 : {
1258 0 : if (!node)
1259 0 : return NULL;
1260 0 : if (node->type != isl_ast_node_block)
1261 0 : isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
1262 : "not a block node", return NULL);
1263 0 : return isl_ast_node_list_copy(node->u.b.children);
1264 : }
1265 :
1266 0 : __isl_give isl_ast_expr *isl_ast_node_user_get_expr(
1267 : __isl_keep isl_ast_node *node)
1268 : {
1269 0 : if (!node)
1270 0 : return NULL;
1271 0 : if (node->type != isl_ast_node_user)
1272 0 : isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
1273 : "not a user node", return NULL);
1274 :
1275 0 : return isl_ast_expr_copy(node->u.e.expr);
1276 : }
1277 :
1278 : /* Return the mark identifier of the mark node "node".
1279 : */
1280 0 : __isl_give isl_id *isl_ast_node_mark_get_id(__isl_keep isl_ast_node *node)
1281 : {
1282 0 : if (!node)
1283 0 : return NULL;
1284 0 : if (node->type != isl_ast_node_mark)
1285 0 : isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
1286 : "not a mark node", return NULL);
1287 :
1288 0 : return isl_id_copy(node->u.m.mark);
1289 : }
1290 :
1291 : /* Return the node marked by mark node "node".
1292 : */
1293 0 : __isl_give isl_ast_node *isl_ast_node_mark_get_node(
1294 : __isl_keep isl_ast_node *node)
1295 : {
1296 0 : if (!node)
1297 0 : return NULL;
1298 0 : if (node->type != isl_ast_node_mark)
1299 0 : isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
1300 : "not a mark node", return NULL);
1301 :
1302 0 : return isl_ast_node_copy(node->u.m.node);
1303 : }
1304 :
1305 0 : __isl_give isl_id *isl_ast_node_get_annotation(__isl_keep isl_ast_node *node)
1306 : {
1307 0 : return node ? isl_id_copy(node->annotation) : NULL;
1308 : }
1309 :
1310 : /* Replace node->annotation by "annotation".
1311 : */
1312 0 : __isl_give isl_ast_node *isl_ast_node_set_annotation(
1313 : __isl_take isl_ast_node *node, __isl_take isl_id *annotation)
1314 : {
1315 0 : node = isl_ast_node_cow(node);
1316 0 : if (!node || !annotation)
1317 : goto error;
1318 :
1319 0 : isl_id_free(node->annotation);
1320 0 : node->annotation = annotation;
1321 :
1322 0 : return node;
1323 : error:
1324 0 : isl_id_free(annotation);
1325 0 : return isl_ast_node_free(node);
1326 : }
1327 :
1328 : /* Traverse the elements of "list" and all their descendants
1329 : * in depth first preorder.
1330 : *
1331 : * Return isl_stat_ok on success and isl_stat_error on failure.
1332 : */
1333 0 : static isl_stat nodelist_foreach(__isl_keep isl_ast_node_list *list,
1334 : isl_bool (*fn)(__isl_keep isl_ast_node *node, void *user), void *user)
1335 : {
1336 : int i;
1337 :
1338 0 : if (!list)
1339 0 : return isl_stat_error;
1340 :
1341 0 : for (i = 0; i < list->n; ++i) {
1342 : isl_stat ok;
1343 0 : isl_ast_node *node = list->p[i];
1344 :
1345 0 : ok = isl_ast_node_foreach_descendant_top_down(node, fn, user);
1346 0 : if (ok < 0)
1347 0 : return isl_stat_error;
1348 : }
1349 :
1350 0 : return isl_stat_ok;
1351 : }
1352 :
1353 : /* Traverse the descendants of "node" (including the node itself)
1354 : * in depth first preorder.
1355 : *
1356 : * If "fn" returns isl_bool_error on any of the nodes, then the traversal
1357 : * is aborted.
1358 : * If "fn" returns isl_bool_false on any of the nodes, then the subtree rooted
1359 : * at that node is skipped.
1360 : *
1361 : * Return isl_stat_ok on success and isl_stat_error on failure.
1362 : */
1363 0 : isl_stat isl_ast_node_foreach_descendant_top_down(
1364 : __isl_keep isl_ast_node *node,
1365 : isl_bool (*fn)(__isl_keep isl_ast_node *node, void *user), void *user)
1366 : {
1367 : isl_bool more;
1368 : isl_stat ok;
1369 :
1370 0 : if (!node)
1371 0 : return isl_stat_error;
1372 :
1373 0 : more = fn(node, user);
1374 0 : if (more < 0)
1375 0 : return isl_stat_error;
1376 0 : if (!more)
1377 0 : return isl_stat_ok;
1378 :
1379 0 : switch (node->type) {
1380 : case isl_ast_node_for:
1381 0 : node = node->u.f.body;
1382 0 : return isl_ast_node_foreach_descendant_top_down(node, fn, user);
1383 : case isl_ast_node_if:
1384 0 : ok = isl_ast_node_foreach_descendant_top_down(node->u.i.then,
1385 : fn, user);
1386 0 : if (ok < 0)
1387 0 : return isl_stat_error;
1388 0 : if (!node->u.i.else_node)
1389 0 : return isl_stat_ok;
1390 0 : node = node->u.i.else_node;
1391 0 : return isl_ast_node_foreach_descendant_top_down(node, fn, user);
1392 : case isl_ast_node_block:
1393 0 : return nodelist_foreach(node->u.b.children, fn, user);
1394 : case isl_ast_node_mark:
1395 0 : node = node->u.m.node;
1396 0 : return isl_ast_node_foreach_descendant_top_down(node, fn, user);
1397 : case isl_ast_node_user:
1398 0 : break;
1399 : case isl_ast_node_error:
1400 0 : return isl_stat_error;
1401 : }
1402 :
1403 0 : return isl_stat_ok;
1404 : }
1405 :
1406 : /* Textual C representation of the various operators.
1407 : */
1408 : static char *op_str_c[] = {
1409 : [isl_ast_op_and] = "&&",
1410 : [isl_ast_op_and_then] = "&&",
1411 : [isl_ast_op_or] = "||",
1412 : [isl_ast_op_or_else] = "||",
1413 : [isl_ast_op_max] = "max",
1414 : [isl_ast_op_min] = "min",
1415 : [isl_ast_op_minus] = "-",
1416 : [isl_ast_op_add] = "+",
1417 : [isl_ast_op_sub] = "-",
1418 : [isl_ast_op_mul] = "*",
1419 : [isl_ast_op_fdiv_q] = "floord",
1420 : [isl_ast_op_pdiv_q] = "/",
1421 : [isl_ast_op_pdiv_r] = "%",
1422 : [isl_ast_op_zdiv_r] = "%",
1423 : [isl_ast_op_div] = "/",
1424 : [isl_ast_op_eq] = "==",
1425 : [isl_ast_op_le] = "<=",
1426 : [isl_ast_op_ge] = ">=",
1427 : [isl_ast_op_lt] = "<",
1428 : [isl_ast_op_gt] = ">",
1429 : [isl_ast_op_member] = ".",
1430 : [isl_ast_op_address_of] = "&"
1431 : };
1432 :
1433 : /* Precedence in C of the various operators.
1434 : * Based on http://en.wikipedia.org/wiki/Operators_in_C_and_C++
1435 : * Lowest value means highest precedence.
1436 : */
1437 : static int op_prec[] = {
1438 : [isl_ast_op_and] = 13,
1439 : [isl_ast_op_and_then] = 13,
1440 : [isl_ast_op_or] = 14,
1441 : [isl_ast_op_or_else] = 14,
1442 : [isl_ast_op_max] = 2,
1443 : [isl_ast_op_min] = 2,
1444 : [isl_ast_op_minus] = 3,
1445 : [isl_ast_op_add] = 6,
1446 : [isl_ast_op_sub] = 6,
1447 : [isl_ast_op_mul] = 5,
1448 : [isl_ast_op_div] = 5,
1449 : [isl_ast_op_fdiv_q] = 2,
1450 : [isl_ast_op_pdiv_q] = 5,
1451 : [isl_ast_op_pdiv_r] = 5,
1452 : [isl_ast_op_zdiv_r] = 5,
1453 : [isl_ast_op_cond] = 15,
1454 : [isl_ast_op_select] = 15,
1455 : [isl_ast_op_eq] = 9,
1456 : [isl_ast_op_le] = 8,
1457 : [isl_ast_op_ge] = 8,
1458 : [isl_ast_op_lt] = 8,
1459 : [isl_ast_op_gt] = 8,
1460 : [isl_ast_op_call] = 2,
1461 : [isl_ast_op_access] = 2,
1462 : [isl_ast_op_member] = 2,
1463 : [isl_ast_op_address_of] = 3
1464 : };
1465 :
1466 : /* Is the operator left-to-right associative?
1467 : */
1468 : static int op_left[] = {
1469 : [isl_ast_op_and] = 1,
1470 : [isl_ast_op_and_then] = 1,
1471 : [isl_ast_op_or] = 1,
1472 : [isl_ast_op_or_else] = 1,
1473 : [isl_ast_op_max] = 1,
1474 : [isl_ast_op_min] = 1,
1475 : [isl_ast_op_minus] = 0,
1476 : [isl_ast_op_add] = 1,
1477 : [isl_ast_op_sub] = 1,
1478 : [isl_ast_op_mul] = 1,
1479 : [isl_ast_op_div] = 1,
1480 : [isl_ast_op_fdiv_q] = 1,
1481 : [isl_ast_op_pdiv_q] = 1,
1482 : [isl_ast_op_pdiv_r] = 1,
1483 : [isl_ast_op_zdiv_r] = 1,
1484 : [isl_ast_op_cond] = 0,
1485 : [isl_ast_op_select] = 0,
1486 : [isl_ast_op_eq] = 1,
1487 : [isl_ast_op_le] = 1,
1488 : [isl_ast_op_ge] = 1,
1489 : [isl_ast_op_lt] = 1,
1490 : [isl_ast_op_gt] = 1,
1491 : [isl_ast_op_call] = 1,
1492 : [isl_ast_op_access] = 1,
1493 : [isl_ast_op_member] = 1,
1494 : [isl_ast_op_address_of] = 0
1495 : };
1496 :
1497 0 : static int is_and(enum isl_ast_op_type op)
1498 : {
1499 0 : return op == isl_ast_op_and || op == isl_ast_op_and_then;
1500 : }
1501 :
1502 0 : static int is_or(enum isl_ast_op_type op)
1503 : {
1504 0 : return op == isl_ast_op_or || op == isl_ast_op_or_else;
1505 : }
1506 :
1507 0 : static int is_add_sub(enum isl_ast_op_type op)
1508 : {
1509 0 : return op == isl_ast_op_add || op == isl_ast_op_sub;
1510 : }
1511 :
1512 0 : static int is_div_mod(enum isl_ast_op_type op)
1513 : {
1514 0 : return op == isl_ast_op_div ||
1515 0 : op == isl_ast_op_pdiv_r ||
1516 : op == isl_ast_op_zdiv_r;
1517 : }
1518 :
1519 : static __isl_give isl_printer *print_ast_expr_c(__isl_take isl_printer *p,
1520 : __isl_keep isl_ast_expr *expr);
1521 :
1522 : /* Do we need/want parentheses around "expr" as a subexpression of
1523 : * an "op" operation? If "left" is set, then "expr" is the left-most
1524 : * operand.
1525 : *
1526 : * We only need parentheses if "expr" represents an operation.
1527 : *
1528 : * If op has a higher precedence than expr->u.op.op, then we need
1529 : * parentheses.
1530 : * If op and expr->u.op.op have the same precedence, but the operations
1531 : * are performed in an order that is different from the associativity,
1532 : * then we need parentheses.
1533 : *
1534 : * An and inside an or technically does not require parentheses,
1535 : * but some compilers complain about that, so we add them anyway.
1536 : *
1537 : * Computations such as "a / b * c" and "a % b + c" can be somewhat
1538 : * difficult to read, so we add parentheses for those as well.
1539 : */
1540 0 : static int sub_expr_need_parens(enum isl_ast_op_type op,
1541 : __isl_keep isl_ast_expr *expr, int left)
1542 : {
1543 0 : if (expr->type != isl_ast_expr_op)
1544 0 : return 0;
1545 :
1546 0 : if (op_prec[expr->u.op.op] > op_prec[op])
1547 0 : return 1;
1548 0 : if (op_prec[expr->u.op.op] == op_prec[op] && left != op_left[op])
1549 0 : return 1;
1550 :
1551 0 : if (is_or(op) && is_and(expr->u.op.op))
1552 0 : return 1;
1553 0 : if (op == isl_ast_op_mul && expr->u.op.op != isl_ast_op_mul &&
1554 0 : op_prec[expr->u.op.op] == op_prec[op])
1555 0 : return 1;
1556 0 : if (is_add_sub(op) && is_div_mod(expr->u.op.op))
1557 0 : return 1;
1558 :
1559 0 : return 0;
1560 : }
1561 :
1562 : /* Print "expr" as a subexpression of an "op" operation in C format.
1563 : * If "left" is set, then "expr" is the left-most operand.
1564 : */
1565 0 : static __isl_give isl_printer *print_sub_expr_c(__isl_take isl_printer *p,
1566 : enum isl_ast_op_type op, __isl_keep isl_ast_expr *expr, int left)
1567 : {
1568 : int need_parens;
1569 :
1570 0 : need_parens = sub_expr_need_parens(op, expr, left);
1571 :
1572 0 : if (need_parens)
1573 0 : p = isl_printer_print_str(p, "(");
1574 0 : p = print_ast_expr_c(p, expr);
1575 0 : if (need_parens)
1576 0 : p = isl_printer_print_str(p, ")");
1577 0 : return p;
1578 : }
1579 :
1580 : #define isl_ast_op_last isl_ast_op_address_of
1581 :
1582 : /* Data structure that holds the user-specified textual
1583 : * representations for the operators in C format.
1584 : * The entries are either NULL or copies of strings.
1585 : * A NULL entry means that the default name should be used.
1586 : */
1587 : struct isl_ast_op_names {
1588 : char *op_str[isl_ast_op_last + 1];
1589 : };
1590 :
1591 : /* Create an empty struct isl_ast_op_names.
1592 : */
1593 0 : static void *create_names(isl_ctx *ctx)
1594 : {
1595 0 : return isl_calloc_type(ctx, struct isl_ast_op_names);
1596 : }
1597 :
1598 : /* Free a struct isl_ast_op_names along with all memory
1599 : * owned by the struct.
1600 : */
1601 0 : static void free_names(void *user)
1602 : {
1603 : int i;
1604 0 : struct isl_ast_op_names *names = user;
1605 :
1606 0 : if (!user)
1607 0 : return;
1608 :
1609 0 : for (i = 0; i <= isl_ast_op_last; ++i)
1610 0 : free(names->op_str[i]);
1611 0 : free(user);
1612 : }
1613 :
1614 : /* Create an identifier that is used to store
1615 : * an isl_ast_op_names note.
1616 : */
1617 0 : static __isl_give isl_id *names_id(isl_ctx *ctx)
1618 : {
1619 0 : return isl_id_alloc(ctx, "isl_ast_op_type_names", NULL);
1620 : }
1621 :
1622 : /* Ensure that "p" has a note identified by "id".
1623 : * If there is no such note yet, then it is created by "note_create" and
1624 : * scheduled do be freed by "note_free".
1625 : */
1626 0 : static __isl_give isl_printer *alloc_note(__isl_take isl_printer *p,
1627 : __isl_keep isl_id *id, void *(*note_create)(isl_ctx *),
1628 : void (*note_free)(void *))
1629 : {
1630 : isl_ctx *ctx;
1631 : isl_id *note_id;
1632 : isl_bool has_note;
1633 : void *note;
1634 :
1635 0 : has_note = isl_printer_has_note(p, id);
1636 0 : if (has_note < 0)
1637 0 : return isl_printer_free(p);
1638 0 : if (has_note)
1639 0 : return p;
1640 :
1641 0 : ctx = isl_printer_get_ctx(p);
1642 0 : note = note_create(ctx);
1643 0 : if (!note)
1644 0 : return isl_printer_free(p);
1645 0 : note_id = isl_id_alloc(ctx, NULL, note);
1646 0 : if (!note_id)
1647 0 : note_free(note);
1648 : else
1649 0 : note_id = isl_id_set_free_user(note_id, note_free);
1650 :
1651 0 : p = isl_printer_set_note(p, isl_id_copy(id), note_id);
1652 :
1653 0 : return p;
1654 : }
1655 :
1656 : /* Ensure that "p" has an isl_ast_op_names note identified by "id".
1657 : */
1658 0 : static __isl_give isl_printer *alloc_names(__isl_take isl_printer *p,
1659 : __isl_keep isl_id *id)
1660 : {
1661 0 : return alloc_note(p, id, &create_names, &free_names);
1662 : }
1663 :
1664 : /* Retrieve the note identified by "id" from "p".
1665 : * The note is assumed to exist.
1666 : */
1667 0 : static void *get_note(__isl_keep isl_printer *p, __isl_keep isl_id *id)
1668 : {
1669 : void *note;
1670 :
1671 0 : id = isl_printer_get_note(p, isl_id_copy(id));
1672 0 : note = isl_id_get_user(id);
1673 0 : isl_id_free(id);
1674 :
1675 0 : return note;
1676 : }
1677 :
1678 : /* Use "name" to print operations of type "type" to "p".
1679 : *
1680 : * Store the name in an isl_ast_op_names note attached to "p", such that
1681 : * it can be retrieved by get_op_str.
1682 : */
1683 0 : __isl_give isl_printer *isl_ast_op_type_set_print_name(
1684 : __isl_take isl_printer *p, enum isl_ast_op_type type,
1685 : __isl_keep const char *name)
1686 : {
1687 : isl_id *id;
1688 : struct isl_ast_op_names *names;
1689 :
1690 0 : if (!p)
1691 0 : return NULL;
1692 0 : if (type > isl_ast_op_last)
1693 0 : isl_die(isl_printer_get_ctx(p), isl_error_invalid,
1694 : "invalid type", return isl_printer_free(p));
1695 :
1696 0 : id = names_id(isl_printer_get_ctx(p));
1697 0 : p = alloc_names(p, id);
1698 0 : names = get_note(p, id);
1699 0 : isl_id_free(id);
1700 0 : if (!names)
1701 0 : return isl_printer_free(p);
1702 0 : free(names->op_str[type]);
1703 0 : names->op_str[type] = strdup(name);
1704 :
1705 0 : return p;
1706 : }
1707 :
1708 : /* Return the textual representation of "type" in C format.
1709 : *
1710 : * If there is a user-specified name in an isl_ast_op_names note
1711 : * associated to "p", then return that.
1712 : * Otherwise, return the default name in op_str.
1713 : */
1714 0 : static const char *get_op_str_c(__isl_keep isl_printer *p,
1715 : enum isl_ast_op_type type)
1716 : {
1717 : isl_id *id;
1718 : isl_bool has_names;
1719 0 : struct isl_ast_op_names *names = NULL;
1720 :
1721 0 : id = names_id(isl_printer_get_ctx(p));
1722 0 : has_names = isl_printer_has_note(p, id);
1723 0 : if (has_names >= 0 && has_names)
1724 0 : names = get_note(p, id);
1725 0 : isl_id_free(id);
1726 0 : if (names && names->op_str[type])
1727 0 : return names->op_str[type];
1728 0 : return op_str_c[type];
1729 : }
1730 :
1731 : /* Print a min or max reduction "expr" in C format.
1732 : */
1733 0 : static __isl_give isl_printer *print_min_max_c(__isl_take isl_printer *p,
1734 : __isl_keep isl_ast_expr *expr)
1735 : {
1736 0 : int i = 0;
1737 :
1738 0 : for (i = 1; i < expr->u.op.n_arg; ++i) {
1739 0 : p = isl_printer_print_str(p, get_op_str_c(p, expr->u.op.op));
1740 0 : p = isl_printer_print_str(p, "(");
1741 : }
1742 0 : p = isl_printer_print_ast_expr(p, expr->u.op.args[0]);
1743 0 : for (i = 1; i < expr->u.op.n_arg; ++i) {
1744 0 : p = isl_printer_print_str(p, ", ");
1745 0 : p = print_ast_expr_c(p, expr->u.op.args[i]);
1746 0 : p = isl_printer_print_str(p, ")");
1747 : }
1748 :
1749 0 : return p;
1750 : }
1751 :
1752 : /* Print a function call "expr" in C format.
1753 : *
1754 : * The first argument represents the function to be called.
1755 : */
1756 0 : static __isl_give isl_printer *print_call_c(__isl_take isl_printer *p,
1757 : __isl_keep isl_ast_expr *expr)
1758 : {
1759 0 : int i = 0;
1760 :
1761 0 : p = print_ast_expr_c(p, expr->u.op.args[0]);
1762 0 : p = isl_printer_print_str(p, "(");
1763 0 : for (i = 1; i < expr->u.op.n_arg; ++i) {
1764 0 : if (i != 1)
1765 0 : p = isl_printer_print_str(p, ", ");
1766 0 : p = print_ast_expr_c(p, expr->u.op.args[i]);
1767 : }
1768 0 : p = isl_printer_print_str(p, ")");
1769 :
1770 0 : return p;
1771 : }
1772 :
1773 : /* Print an array access "expr" in C format.
1774 : *
1775 : * The first argument represents the array being accessed.
1776 : */
1777 0 : static __isl_give isl_printer *print_access_c(__isl_take isl_printer *p,
1778 : __isl_keep isl_ast_expr *expr)
1779 : {
1780 0 : int i = 0;
1781 :
1782 0 : p = print_ast_expr_c(p, expr->u.op.args[0]);
1783 0 : for (i = 1; i < expr->u.op.n_arg; ++i) {
1784 0 : p = isl_printer_print_str(p, "[");
1785 0 : p = print_ast_expr_c(p, expr->u.op.args[i]);
1786 0 : p = isl_printer_print_str(p, "]");
1787 : }
1788 :
1789 0 : return p;
1790 : }
1791 :
1792 : /* Print "expr" to "p" in C format.
1793 : */
1794 0 : static __isl_give isl_printer *print_ast_expr_c(__isl_take isl_printer *p,
1795 : __isl_keep isl_ast_expr *expr)
1796 : {
1797 0 : if (!p)
1798 0 : return NULL;
1799 0 : if (!expr)
1800 0 : return isl_printer_free(p);
1801 :
1802 0 : switch (expr->type) {
1803 : case isl_ast_expr_op:
1804 0 : if (expr->u.op.op == isl_ast_op_call) {
1805 0 : p = print_call_c(p, expr);
1806 0 : break;
1807 : }
1808 0 : if (expr->u.op.op == isl_ast_op_access) {
1809 0 : p = print_access_c(p, expr);
1810 0 : break;
1811 : }
1812 0 : if (expr->u.op.n_arg == 1) {
1813 0 : p = isl_printer_print_str(p,
1814 : get_op_str_c(p, expr->u.op.op));
1815 0 : p = print_sub_expr_c(p, expr->u.op.op,
1816 0 : expr->u.op.args[0], 0);
1817 0 : break;
1818 : }
1819 0 : if (expr->u.op.op == isl_ast_op_fdiv_q) {
1820 0 : const char *name = get_op_str_c(p, isl_ast_op_fdiv_q);
1821 0 : p = isl_printer_print_str(p, name);
1822 0 : p = isl_printer_print_str(p, "(");
1823 0 : p = print_ast_expr_c(p, expr->u.op.args[0]);
1824 0 : p = isl_printer_print_str(p, ", ");
1825 0 : p = print_ast_expr_c(p, expr->u.op.args[1]);
1826 0 : p = isl_printer_print_str(p, ")");
1827 0 : break;
1828 : }
1829 0 : if (expr->u.op.op == isl_ast_op_max ||
1830 0 : expr->u.op.op == isl_ast_op_min) {
1831 0 : p = print_min_max_c(p, expr);
1832 0 : break;
1833 : }
1834 0 : if (expr->u.op.op == isl_ast_op_cond ||
1835 0 : expr->u.op.op == isl_ast_op_select) {
1836 0 : p = print_ast_expr_c(p, expr->u.op.args[0]);
1837 0 : p = isl_printer_print_str(p, " ? ");
1838 0 : p = print_ast_expr_c(p, expr->u.op.args[1]);
1839 0 : p = isl_printer_print_str(p, " : ");
1840 0 : p = print_ast_expr_c(p, expr->u.op.args[2]);
1841 0 : break;
1842 : }
1843 0 : if (expr->u.op.n_arg != 2)
1844 0 : isl_die(isl_printer_get_ctx(p), isl_error_internal,
1845 : "operation should have two arguments",
1846 : return isl_printer_free(p));
1847 0 : p = print_sub_expr_c(p, expr->u.op.op, expr->u.op.args[0], 1);
1848 0 : if (expr->u.op.op != isl_ast_op_member)
1849 0 : p = isl_printer_print_str(p, " ");
1850 0 : p = isl_printer_print_str(p, get_op_str_c(p, expr->u.op.op));
1851 0 : if (expr->u.op.op != isl_ast_op_member)
1852 0 : p = isl_printer_print_str(p, " ");
1853 0 : p = print_sub_expr_c(p, expr->u.op.op, expr->u.op.args[1], 0);
1854 0 : break;
1855 : case isl_ast_expr_id:
1856 0 : p = isl_printer_print_str(p, isl_id_get_name(expr->u.id));
1857 0 : break;
1858 : case isl_ast_expr_int:
1859 0 : p = isl_printer_print_val(p, expr->u.v);
1860 0 : break;
1861 : case isl_ast_expr_error:
1862 0 : break;
1863 : }
1864 :
1865 0 : return p;
1866 : }
1867 :
1868 : /* Textual representation of the isl_ast_op_type elements
1869 : * for use in a YAML representation of an isl_ast_expr.
1870 : */
1871 : static char *op_str[] = {
1872 : [isl_ast_op_and] = "and",
1873 : [isl_ast_op_and_then] = "and_then",
1874 : [isl_ast_op_or] = "or",
1875 : [isl_ast_op_or_else] = "or_else",
1876 : [isl_ast_op_max] = "max",
1877 : [isl_ast_op_min] = "min",
1878 : [isl_ast_op_minus] = "minus",
1879 : [isl_ast_op_add] = "add",
1880 : [isl_ast_op_sub] = "sub",
1881 : [isl_ast_op_mul] = "mul",
1882 : [isl_ast_op_div] = "div",
1883 : [isl_ast_op_fdiv_q] = "fdiv_q",
1884 : [isl_ast_op_pdiv_q] = "pdiv_q",
1885 : [isl_ast_op_pdiv_r] = "pdiv_r",
1886 : [isl_ast_op_zdiv_r] = "zdiv_r",
1887 : [isl_ast_op_cond] = "cond",
1888 : [isl_ast_op_select] = "select",
1889 : [isl_ast_op_eq] = "eq",
1890 : [isl_ast_op_le] = "le",
1891 : [isl_ast_op_lt] = "lt",
1892 : [isl_ast_op_ge] = "ge",
1893 : [isl_ast_op_gt] = "gt",
1894 : [isl_ast_op_call] = "call",
1895 : [isl_ast_op_access] = "access",
1896 : [isl_ast_op_member] = "member",
1897 : [isl_ast_op_address_of] = "address_of"
1898 : };
1899 :
1900 : static __isl_give isl_printer *print_ast_expr_isl(__isl_take isl_printer *p,
1901 : __isl_keep isl_ast_expr *expr);
1902 :
1903 : /* Print the arguments of "expr" to "p" in isl format.
1904 : *
1905 : * If there are no arguments, then nothing needs to be printed.
1906 : * Otherwise add an "args" key to the current mapping with as value
1907 : * the list of arguments of "expr".
1908 : */
1909 0 : static __isl_give isl_printer *print_arguments(__isl_take isl_printer *p,
1910 : __isl_keep isl_ast_expr *expr)
1911 : {
1912 : int i, n;
1913 :
1914 0 : n = isl_ast_expr_get_op_n_arg(expr);
1915 0 : if (n < 0)
1916 0 : return isl_printer_free(p);
1917 0 : if (n == 0)
1918 0 : return p;
1919 :
1920 0 : p = isl_printer_print_str(p, "args");
1921 0 : p = isl_printer_yaml_next(p);
1922 0 : p = isl_printer_yaml_start_sequence(p);
1923 0 : for (i = 0; i < n; ++i) {
1924 : isl_ast_expr *arg;
1925 :
1926 0 : arg = isl_ast_expr_get_op_arg(expr, i);
1927 0 : p = print_ast_expr_isl(p, arg);
1928 0 : isl_ast_expr_free(arg);
1929 0 : p = isl_printer_yaml_next(p);
1930 : }
1931 0 : p = isl_printer_yaml_end_sequence(p);
1932 :
1933 0 : return p;
1934 : }
1935 :
1936 : /* Print "expr" to "p" in isl format.
1937 : *
1938 : * In particular, print the isl_ast_expr as a YAML document.
1939 : */
1940 0 : static __isl_give isl_printer *print_ast_expr_isl(__isl_take isl_printer *p,
1941 : __isl_keep isl_ast_expr *expr)
1942 : {
1943 : enum isl_ast_expr_type type;
1944 : enum isl_ast_op_type op;
1945 : isl_id *id;
1946 : isl_val *v;
1947 :
1948 0 : if (!expr)
1949 0 : return isl_printer_free(p);
1950 :
1951 0 : p = isl_printer_yaml_start_mapping(p);
1952 0 : type = isl_ast_expr_get_type(expr);
1953 0 : switch (type) {
1954 : case isl_ast_expr_error:
1955 0 : return isl_printer_free(p);
1956 : case isl_ast_expr_op:
1957 0 : op = isl_ast_expr_get_op_type(expr);
1958 0 : if (op == isl_ast_op_error)
1959 0 : return isl_printer_free(p);
1960 0 : p = isl_printer_print_str(p, "op");
1961 0 : p = isl_printer_yaml_next(p);
1962 0 : p = isl_printer_print_str(p, op_str[op]);
1963 0 : p = isl_printer_yaml_next(p);
1964 0 : p = print_arguments(p, expr);
1965 0 : break;
1966 : case isl_ast_expr_id:
1967 0 : p = isl_printer_print_str(p, "id");
1968 0 : p = isl_printer_yaml_next(p);
1969 0 : id = isl_ast_expr_get_id(expr);
1970 0 : p = isl_printer_print_id(p, id);
1971 0 : isl_id_free(id);
1972 0 : break;
1973 : case isl_ast_expr_int:
1974 0 : p = isl_printer_print_str(p, "val");
1975 0 : p = isl_printer_yaml_next(p);
1976 0 : v = isl_ast_expr_get_val(expr);
1977 0 : p = isl_printer_print_val(p, v);
1978 0 : isl_val_free(v);
1979 0 : break;
1980 : }
1981 0 : p = isl_printer_yaml_end_mapping(p);
1982 :
1983 0 : return p;
1984 : }
1985 :
1986 : /* Print "expr" to "p".
1987 : *
1988 : * Only an isl and a C format are supported.
1989 : */
1990 0 : __isl_give isl_printer *isl_printer_print_ast_expr(__isl_take isl_printer *p,
1991 : __isl_keep isl_ast_expr *expr)
1992 : {
1993 : int format;
1994 :
1995 0 : if (!p)
1996 0 : return NULL;
1997 :
1998 0 : format = isl_printer_get_output_format(p);
1999 0 : switch (format) {
2000 : case ISL_FORMAT_ISL:
2001 0 : p = print_ast_expr_isl(p, expr);
2002 0 : break;
2003 : case ISL_FORMAT_C:
2004 0 : p = print_ast_expr_c(p, expr);
2005 0 : break;
2006 : default:
2007 0 : isl_die(isl_printer_get_ctx(p), isl_error_unsupported,
2008 : "output format not supported for ast_expr",
2009 : return isl_printer_free(p));
2010 : }
2011 :
2012 0 : return p;
2013 : }
2014 :
2015 : static __isl_give isl_printer *print_ast_node_isl(__isl_take isl_printer *p,
2016 : __isl_keep isl_ast_node *node);
2017 :
2018 : /* Print a YAML sequence containing the entries in "list" to "p".
2019 : */
2020 0 : static __isl_give isl_printer *print_ast_node_list(__isl_take isl_printer *p,
2021 : __isl_keep isl_ast_node_list *list)
2022 : {
2023 : int i, n;
2024 :
2025 0 : n = isl_ast_node_list_n_ast_node(list);
2026 0 : if (n < 0)
2027 0 : return isl_printer_free(p);
2028 :
2029 0 : p = isl_printer_yaml_start_sequence(p);
2030 0 : for (i = 0; i < n; ++i) {
2031 : isl_ast_node *node;
2032 :
2033 0 : node = isl_ast_node_list_get_ast_node(list, i);
2034 0 : p = print_ast_node_isl(p, node);
2035 0 : isl_ast_node_free(node);
2036 0 : p = isl_printer_yaml_next(p);
2037 : }
2038 0 : p = isl_printer_yaml_end_sequence(p);
2039 :
2040 0 : return p;
2041 : }
2042 :
2043 : /* Print "node" to "p" in "isl format".
2044 : *
2045 : * In particular, print the isl_ast_node as a YAML document.
2046 : */
2047 0 : static __isl_give isl_printer *print_ast_node_isl(__isl_take isl_printer *p,
2048 : __isl_keep isl_ast_node *node)
2049 : {
2050 0 : switch (node->type) {
2051 : case isl_ast_node_for:
2052 0 : p = isl_printer_yaml_start_mapping(p);
2053 0 : p = isl_printer_print_str(p, "iterator");
2054 0 : p = isl_printer_yaml_next(p);
2055 0 : p = isl_printer_print_ast_expr(p, node->u.f.iterator);
2056 0 : p = isl_printer_yaml_next(p);
2057 0 : if (node->u.f.degenerate) {
2058 0 : p = isl_printer_print_str(p, "value");
2059 0 : p = isl_printer_yaml_next(p);
2060 0 : p = isl_printer_print_ast_expr(p, node->u.f.init);
2061 0 : p = isl_printer_yaml_next(p);
2062 : } else {
2063 0 : p = isl_printer_print_str(p, "init");
2064 0 : p = isl_printer_yaml_next(p);
2065 0 : p = isl_printer_print_ast_expr(p, node->u.f.init);
2066 0 : p = isl_printer_yaml_next(p);
2067 0 : p = isl_printer_print_str(p, "cond");
2068 0 : p = isl_printer_yaml_next(p);
2069 0 : p = isl_printer_print_ast_expr(p, node->u.f.cond);
2070 0 : p = isl_printer_yaml_next(p);
2071 0 : p = isl_printer_print_str(p, "inc");
2072 0 : p = isl_printer_yaml_next(p);
2073 0 : p = isl_printer_print_ast_expr(p, node->u.f.inc);
2074 0 : p = isl_printer_yaml_next(p);
2075 : }
2076 0 : if (node->u.f.body) {
2077 0 : p = isl_printer_print_str(p, "body");
2078 0 : p = isl_printer_yaml_next(p);
2079 0 : p = isl_printer_print_ast_node(p, node->u.f.body);
2080 0 : p = isl_printer_yaml_next(p);
2081 : }
2082 0 : p = isl_printer_yaml_end_mapping(p);
2083 0 : break;
2084 : case isl_ast_node_mark:
2085 0 : p = isl_printer_yaml_start_mapping(p);
2086 0 : p = isl_printer_print_str(p, "mark");
2087 0 : p = isl_printer_yaml_next(p);
2088 0 : p = isl_printer_print_id(p, node->u.m.mark);
2089 0 : p = isl_printer_yaml_next(p);
2090 0 : p = isl_printer_print_str(p, "node");
2091 0 : p = isl_printer_yaml_next(p);
2092 0 : p = isl_printer_print_ast_node(p, node->u.m.node);
2093 0 : p = isl_printer_yaml_end_mapping(p);
2094 0 : break;
2095 : case isl_ast_node_user:
2096 0 : p = isl_printer_yaml_start_mapping(p);
2097 0 : p = isl_printer_print_str(p, "user");
2098 0 : p = isl_printer_yaml_next(p);
2099 0 : p = isl_printer_print_ast_expr(p, node->u.e.expr);
2100 0 : p = isl_printer_yaml_end_mapping(p);
2101 0 : break;
2102 : case isl_ast_node_if:
2103 0 : p = isl_printer_yaml_start_mapping(p);
2104 0 : p = isl_printer_print_str(p, "guard");
2105 0 : p = isl_printer_yaml_next(p);
2106 0 : p = isl_printer_print_ast_expr(p, node->u.i.guard);
2107 0 : p = isl_printer_yaml_next(p);
2108 0 : if (node->u.i.then) {
2109 0 : p = isl_printer_print_str(p, "then");
2110 0 : p = isl_printer_yaml_next(p);
2111 0 : p = isl_printer_print_ast_node(p, node->u.i.then);
2112 0 : p = isl_printer_yaml_next(p);
2113 : }
2114 0 : if (node->u.i.else_node) {
2115 0 : p = isl_printer_print_str(p, "else");
2116 0 : p = isl_printer_yaml_next(p);
2117 0 : p = isl_printer_print_ast_node(p, node->u.i.else_node);
2118 : }
2119 0 : p = isl_printer_yaml_end_mapping(p);
2120 0 : break;
2121 : case isl_ast_node_block:
2122 0 : p = print_ast_node_list(p, node->u.b.children);
2123 0 : break;
2124 : case isl_ast_node_error:
2125 0 : break;
2126 : }
2127 0 : return p;
2128 : }
2129 :
2130 : /* Do we need to print a block around the body "node" of a for or if node?
2131 : *
2132 : * If the node is a block, then we need to print a block.
2133 : * Also if the node is a degenerate for then we will print it as
2134 : * an assignment followed by the body of the for loop, so we need a block
2135 : * as well.
2136 : * If the node is an if node with an else, then we print a block
2137 : * to avoid spurious dangling else warnings emitted by some compilers.
2138 : * If the node is a mark, then in principle, we would have to check
2139 : * the child of the mark node. However, even if the child would not
2140 : * require us to print a block, for readability it is probably best
2141 : * to print a block anyway.
2142 : * If the ast_always_print_block option has been set, then we print a block.
2143 : */
2144 0 : static int need_block(__isl_keep isl_ast_node *node)
2145 : {
2146 : isl_ctx *ctx;
2147 :
2148 0 : if (node->type == isl_ast_node_block)
2149 0 : return 1;
2150 0 : if (node->type == isl_ast_node_for && node->u.f.degenerate)
2151 0 : return 1;
2152 0 : if (node->type == isl_ast_node_if && node->u.i.else_node)
2153 0 : return 1;
2154 0 : if (node->type == isl_ast_node_mark)
2155 0 : return 1;
2156 :
2157 0 : ctx = isl_ast_node_get_ctx(node);
2158 0 : return isl_options_get_ast_always_print_block(ctx);
2159 : }
2160 :
2161 : static __isl_give isl_printer *print_ast_node_c(__isl_take isl_printer *p,
2162 : __isl_keep isl_ast_node *node,
2163 : __isl_keep isl_ast_print_options *options, int in_block, int in_list);
2164 : static __isl_give isl_printer *print_if_c(__isl_take isl_printer *p,
2165 : __isl_keep isl_ast_node *node,
2166 : __isl_keep isl_ast_print_options *options, int new_line,
2167 : int force_block);
2168 :
2169 : /* Print the body "node" of a for or if node.
2170 : * If "else_node" is set, then it is printed as well.
2171 : * If "force_block" is set, then print out the body as a block.
2172 : *
2173 : * We first check if we need to print out a block.
2174 : * We always print out a block if there is an else node to make
2175 : * sure that the else node is matched to the correct if node.
2176 : * For consistency, the corresponding else node is also printed as a block.
2177 : *
2178 : * If the else node is itself an if, then we print it as
2179 : *
2180 : * } else if (..) {
2181 : * }
2182 : *
2183 : * Otherwise the else node is printed as
2184 : *
2185 : * } else {
2186 : * node
2187 : * }
2188 : */
2189 0 : static __isl_give isl_printer *print_body_c(__isl_take isl_printer *p,
2190 : __isl_keep isl_ast_node *node, __isl_keep isl_ast_node *else_node,
2191 : __isl_keep isl_ast_print_options *options, int force_block)
2192 : {
2193 0 : if (!node)
2194 0 : return isl_printer_free(p);
2195 :
2196 0 : if (!force_block && !else_node && !need_block(node)) {
2197 0 : p = isl_printer_end_line(p);
2198 0 : p = isl_printer_indent(p, 2);
2199 0 : p = isl_ast_node_print(node, p,
2200 : isl_ast_print_options_copy(options));
2201 0 : p = isl_printer_indent(p, -2);
2202 0 : return p;
2203 : }
2204 :
2205 0 : p = isl_printer_print_str(p, " {");
2206 0 : p = isl_printer_end_line(p);
2207 0 : p = isl_printer_indent(p, 2);
2208 0 : p = print_ast_node_c(p, node, options, 1, 0);
2209 0 : p = isl_printer_indent(p, -2);
2210 0 : p = isl_printer_start_line(p);
2211 0 : p = isl_printer_print_str(p, "}");
2212 0 : if (else_node) {
2213 0 : if (else_node->type == isl_ast_node_if) {
2214 0 : p = isl_printer_print_str(p, " else ");
2215 0 : p = print_if_c(p, else_node, options, 0, 1);
2216 : } else {
2217 0 : p = isl_printer_print_str(p, " else");
2218 0 : p = print_body_c(p, else_node, NULL, options, 1);
2219 : }
2220 : } else
2221 0 : p = isl_printer_end_line(p);
2222 :
2223 0 : return p;
2224 : }
2225 :
2226 : /* Print the start of a compound statement.
2227 : */
2228 0 : static __isl_give isl_printer *start_block(__isl_take isl_printer *p)
2229 : {
2230 0 : p = isl_printer_start_line(p);
2231 0 : p = isl_printer_print_str(p, "{");
2232 0 : p = isl_printer_end_line(p);
2233 0 : p = isl_printer_indent(p, 2);
2234 :
2235 0 : return p;
2236 : }
2237 :
2238 : /* Print the end of a compound statement.
2239 : */
2240 0 : static __isl_give isl_printer *end_block(__isl_take isl_printer *p)
2241 : {
2242 0 : p = isl_printer_indent(p, -2);
2243 0 : p = isl_printer_start_line(p);
2244 0 : p = isl_printer_print_str(p, "}");
2245 0 : p = isl_printer_end_line(p);
2246 :
2247 0 : return p;
2248 : }
2249 :
2250 : /* Print the for node "node".
2251 : *
2252 : * If the for node is degenerate, it is printed as
2253 : *
2254 : * type iterator = init;
2255 : * body
2256 : *
2257 : * Otherwise, it is printed as
2258 : *
2259 : * for (type iterator = init; cond; iterator += inc)
2260 : * body
2261 : *
2262 : * "in_block" is set if we are currently inside a block.
2263 : * "in_list" is set if the current node is not alone in the block.
2264 : * If we are not in a block or if the current not is not alone in the block
2265 : * then we print a block around a degenerate for loop such that the variable
2266 : * declaration will not conflict with any potential other declaration
2267 : * of the same variable.
2268 : */
2269 0 : static __isl_give isl_printer *print_for_c(__isl_take isl_printer *p,
2270 : __isl_keep isl_ast_node *node,
2271 : __isl_keep isl_ast_print_options *options, int in_block, int in_list)
2272 : {
2273 : isl_id *id;
2274 : const char *name;
2275 : const char *type;
2276 :
2277 0 : type = isl_options_get_ast_iterator_type(isl_printer_get_ctx(p));
2278 0 : if (!node->u.f.degenerate) {
2279 0 : id = isl_ast_expr_get_id(node->u.f.iterator);
2280 0 : name = isl_id_get_name(id);
2281 0 : isl_id_free(id);
2282 0 : p = isl_printer_start_line(p);
2283 0 : p = isl_printer_print_str(p, "for (");
2284 0 : p = isl_printer_print_str(p, type);
2285 0 : p = isl_printer_print_str(p, " ");
2286 0 : p = isl_printer_print_str(p, name);
2287 0 : p = isl_printer_print_str(p, " = ");
2288 0 : p = isl_printer_print_ast_expr(p, node->u.f.init);
2289 0 : p = isl_printer_print_str(p, "; ");
2290 0 : p = isl_printer_print_ast_expr(p, node->u.f.cond);
2291 0 : p = isl_printer_print_str(p, "; ");
2292 0 : p = isl_printer_print_str(p, name);
2293 0 : p = isl_printer_print_str(p, " += ");
2294 0 : p = isl_printer_print_ast_expr(p, node->u.f.inc);
2295 0 : p = isl_printer_print_str(p, ")");
2296 0 : p = print_body_c(p, node->u.f.body, NULL, options, 0);
2297 : } else {
2298 0 : id = isl_ast_expr_get_id(node->u.f.iterator);
2299 0 : name = isl_id_get_name(id);
2300 0 : isl_id_free(id);
2301 0 : if (!in_block || in_list)
2302 0 : p = start_block(p);
2303 0 : p = isl_printer_start_line(p);
2304 0 : p = isl_printer_print_str(p, type);
2305 0 : p = isl_printer_print_str(p, " ");
2306 0 : p = isl_printer_print_str(p, name);
2307 0 : p = isl_printer_print_str(p, " = ");
2308 0 : p = isl_printer_print_ast_expr(p, node->u.f.init);
2309 0 : p = isl_printer_print_str(p, ";");
2310 0 : p = isl_printer_end_line(p);
2311 0 : p = print_ast_node_c(p, node->u.f.body, options, 1, 0);
2312 0 : if (!in_block || in_list)
2313 0 : p = end_block(p);
2314 : }
2315 :
2316 0 : return p;
2317 : }
2318 :
2319 : /* Print the if node "node".
2320 : * If "new_line" is set then the if node should be printed on a new line.
2321 : * If "force_block" is set, then print out the body as a block.
2322 : */
2323 0 : static __isl_give isl_printer *print_if_c(__isl_take isl_printer *p,
2324 : __isl_keep isl_ast_node *node,
2325 : __isl_keep isl_ast_print_options *options, int new_line,
2326 : int force_block)
2327 : {
2328 0 : if (new_line)
2329 0 : p = isl_printer_start_line(p);
2330 0 : p = isl_printer_print_str(p, "if (");
2331 0 : p = isl_printer_print_ast_expr(p, node->u.i.guard);
2332 0 : p = isl_printer_print_str(p, ")");
2333 0 : p = print_body_c(p, node->u.i.then, node->u.i.else_node, options,
2334 : force_block);
2335 :
2336 0 : return p;
2337 : }
2338 :
2339 : /* Print the "node" to "p".
2340 : *
2341 : * "in_block" is set if we are currently inside a block.
2342 : * If so, we do not print a block around the children of a block node.
2343 : * We do this to avoid an extra block around the body of a degenerate
2344 : * for node.
2345 : *
2346 : * "in_list" is set if the current node is not alone in the block.
2347 : */
2348 0 : static __isl_give isl_printer *print_ast_node_c(__isl_take isl_printer *p,
2349 : __isl_keep isl_ast_node *node,
2350 : __isl_keep isl_ast_print_options *options, int in_block, int in_list)
2351 : {
2352 0 : switch (node->type) {
2353 : case isl_ast_node_for:
2354 0 : if (options->print_for)
2355 0 : return options->print_for(p,
2356 : isl_ast_print_options_copy(options),
2357 : node, options->print_for_user);
2358 0 : p = print_for_c(p, node, options, in_block, in_list);
2359 0 : break;
2360 : case isl_ast_node_if:
2361 0 : p = print_if_c(p, node, options, 1, 0);
2362 0 : break;
2363 : case isl_ast_node_block:
2364 0 : if (!in_block)
2365 0 : p = start_block(p);
2366 0 : p = isl_ast_node_list_print(node->u.b.children, p, options);
2367 0 : if (!in_block)
2368 0 : p = end_block(p);
2369 0 : break;
2370 : case isl_ast_node_mark:
2371 0 : p = isl_printer_start_line(p);
2372 0 : p = isl_printer_print_str(p, "// ");
2373 0 : p = isl_printer_print_str(p, isl_id_get_name(node->u.m.mark));
2374 0 : p = isl_printer_end_line(p);
2375 0 : p = print_ast_node_c(p, node->u.m.node, options, 0, in_list);
2376 0 : break;
2377 : case isl_ast_node_user:
2378 0 : if (options->print_user)
2379 0 : return options->print_user(p,
2380 : isl_ast_print_options_copy(options),
2381 : node, options->print_user_user);
2382 0 : p = isl_printer_start_line(p);
2383 0 : p = isl_printer_print_ast_expr(p, node->u.e.expr);
2384 0 : p = isl_printer_print_str(p, ";");
2385 0 : p = isl_printer_end_line(p);
2386 0 : break;
2387 : case isl_ast_node_error:
2388 0 : break;
2389 : }
2390 0 : return p;
2391 : }
2392 :
2393 : /* Print the for node "node" to "p".
2394 : */
2395 0 : __isl_give isl_printer *isl_ast_node_for_print(__isl_keep isl_ast_node *node,
2396 : __isl_take isl_printer *p, __isl_take isl_ast_print_options *options)
2397 : {
2398 0 : if (!node || !options)
2399 : goto error;
2400 0 : if (node->type != isl_ast_node_for)
2401 0 : isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
2402 : "not a for node", goto error);
2403 0 : p = print_for_c(p, node, options, 0, 0);
2404 0 : isl_ast_print_options_free(options);
2405 0 : return p;
2406 : error:
2407 0 : isl_ast_print_options_free(options);
2408 0 : isl_printer_free(p);
2409 0 : return NULL;
2410 : }
2411 :
2412 : /* Print the if node "node" to "p".
2413 : */
2414 0 : __isl_give isl_printer *isl_ast_node_if_print(__isl_keep isl_ast_node *node,
2415 : __isl_take isl_printer *p, __isl_take isl_ast_print_options *options)
2416 : {
2417 0 : if (!node || !options)
2418 : goto error;
2419 0 : if (node->type != isl_ast_node_if)
2420 0 : isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
2421 : "not an if node", goto error);
2422 0 : p = print_if_c(p, node, options, 1, 0);
2423 0 : isl_ast_print_options_free(options);
2424 0 : return p;
2425 : error:
2426 0 : isl_ast_print_options_free(options);
2427 0 : isl_printer_free(p);
2428 0 : return NULL;
2429 : }
2430 :
2431 : /* Print "node" to "p".
2432 : */
2433 0 : __isl_give isl_printer *isl_ast_node_print(__isl_keep isl_ast_node *node,
2434 : __isl_take isl_printer *p, __isl_take isl_ast_print_options *options)
2435 : {
2436 0 : if (!options || !node)
2437 : goto error;
2438 0 : p = print_ast_node_c(p, node, options, 0, 0);
2439 0 : isl_ast_print_options_free(options);
2440 0 : return p;
2441 : error:
2442 0 : isl_ast_print_options_free(options);
2443 0 : isl_printer_free(p);
2444 0 : return NULL;
2445 : }
2446 :
2447 : /* Print "node" to "p".
2448 : */
2449 0 : __isl_give isl_printer *isl_printer_print_ast_node(__isl_take isl_printer *p,
2450 : __isl_keep isl_ast_node *node)
2451 : {
2452 : int format;
2453 : isl_ast_print_options *options;
2454 :
2455 0 : if (!p)
2456 0 : return NULL;
2457 :
2458 0 : format = isl_printer_get_output_format(p);
2459 0 : switch (format) {
2460 : case ISL_FORMAT_ISL:
2461 0 : p = print_ast_node_isl(p, node);
2462 0 : break;
2463 : case ISL_FORMAT_C:
2464 0 : options = isl_ast_print_options_alloc(isl_printer_get_ctx(p));
2465 0 : p = isl_ast_node_print(node, p, options);
2466 0 : break;
2467 : default:
2468 0 : isl_die(isl_printer_get_ctx(p), isl_error_unsupported,
2469 : "output format not supported for ast_node",
2470 : return isl_printer_free(p));
2471 : }
2472 :
2473 0 : return p;
2474 : }
2475 :
2476 : /* Print the list of nodes "list" to "p".
2477 : */
2478 0 : __isl_give isl_printer *isl_ast_node_list_print(
2479 : __isl_keep isl_ast_node_list *list, __isl_take isl_printer *p,
2480 : __isl_keep isl_ast_print_options *options)
2481 : {
2482 : int i;
2483 :
2484 0 : if (!p || !list || !options)
2485 0 : return isl_printer_free(p);
2486 :
2487 0 : for (i = 0; i < list->n; ++i)
2488 0 : p = print_ast_node_c(p, list->p[i], options, 1, 1);
2489 :
2490 0 : return p;
2491 : }
2492 :
2493 : #define ISL_AST_MACRO_FLOORD (1 << 0)
2494 : #define ISL_AST_MACRO_MIN (1 << 1)
2495 : #define ISL_AST_MACRO_MAX (1 << 2)
2496 : #define ISL_AST_MACRO_ALL (ISL_AST_MACRO_FLOORD | \
2497 : ISL_AST_MACRO_MIN | \
2498 : ISL_AST_MACRO_MAX)
2499 :
2500 : /* If "expr" contains an isl_ast_op_min, isl_ast_op_max or isl_ast_op_fdiv_q
2501 : * then set the corresponding bit in "macros".
2502 : */
2503 0 : static int ast_expr_required_macros(__isl_keep isl_ast_expr *expr, int macros)
2504 : {
2505 : int i;
2506 :
2507 0 : if (macros == ISL_AST_MACRO_ALL)
2508 0 : return macros;
2509 :
2510 0 : if (expr->type != isl_ast_expr_op)
2511 0 : return macros;
2512 :
2513 0 : if (expr->u.op.op == isl_ast_op_min)
2514 0 : macros |= ISL_AST_MACRO_MIN;
2515 0 : if (expr->u.op.op == isl_ast_op_max)
2516 0 : macros |= ISL_AST_MACRO_MAX;
2517 0 : if (expr->u.op.op == isl_ast_op_fdiv_q)
2518 0 : macros |= ISL_AST_MACRO_FLOORD;
2519 :
2520 0 : for (i = 0; i < expr->u.op.n_arg; ++i)
2521 0 : macros = ast_expr_required_macros(expr->u.op.args[i], macros);
2522 :
2523 0 : return macros;
2524 : }
2525 :
2526 : static int ast_node_list_required_macros(__isl_keep isl_ast_node_list *list,
2527 : int macros);
2528 :
2529 : /* If "node" contains an isl_ast_op_min, isl_ast_op_max or isl_ast_op_fdiv_q
2530 : * then set the corresponding bit in "macros".
2531 : */
2532 0 : static int ast_node_required_macros(__isl_keep isl_ast_node *node, int macros)
2533 : {
2534 0 : if (macros == ISL_AST_MACRO_ALL)
2535 0 : return macros;
2536 :
2537 0 : switch (node->type) {
2538 : case isl_ast_node_for:
2539 0 : macros = ast_expr_required_macros(node->u.f.init, macros);
2540 0 : if (!node->u.f.degenerate) {
2541 0 : macros = ast_expr_required_macros(node->u.f.cond,
2542 : macros);
2543 0 : macros = ast_expr_required_macros(node->u.f.inc,
2544 : macros);
2545 : }
2546 0 : macros = ast_node_required_macros(node->u.f.body, macros);
2547 0 : break;
2548 : case isl_ast_node_if:
2549 0 : macros = ast_expr_required_macros(node->u.i.guard, macros);
2550 0 : macros = ast_node_required_macros(node->u.i.then, macros);
2551 0 : if (node->u.i.else_node)
2552 0 : macros = ast_node_required_macros(node->u.i.else_node,
2553 : macros);
2554 0 : break;
2555 : case isl_ast_node_block:
2556 0 : macros = ast_node_list_required_macros(node->u.b.children,
2557 : macros);
2558 0 : break;
2559 : case isl_ast_node_mark:
2560 0 : macros = ast_node_required_macros(node->u.m.node, macros);
2561 0 : break;
2562 : case isl_ast_node_user:
2563 0 : macros = ast_expr_required_macros(node->u.e.expr, macros);
2564 0 : break;
2565 : case isl_ast_node_error:
2566 0 : break;
2567 : }
2568 :
2569 0 : return macros;
2570 : }
2571 :
2572 : /* If "list" contains an isl_ast_op_min, isl_ast_op_max or isl_ast_op_fdiv_q
2573 : * then set the corresponding bit in "macros".
2574 : */
2575 0 : static int ast_node_list_required_macros(__isl_keep isl_ast_node_list *list,
2576 : int macros)
2577 : {
2578 : int i;
2579 :
2580 0 : for (i = 0; i < list->n; ++i)
2581 0 : macros = ast_node_required_macros(list->p[i], macros);
2582 :
2583 0 : return macros;
2584 : }
2585 :
2586 : /* Data structure for keeping track of whether a macro definition
2587 : * for a given type has already been printed.
2588 : * The value is zero if no definition has been printed and non-zero otherwise.
2589 : */
2590 : struct isl_ast_op_printed {
2591 : char printed[isl_ast_op_last + 1];
2592 : };
2593 :
2594 : /* Create an empty struct isl_ast_op_printed.
2595 : */
2596 0 : static void *create_printed(isl_ctx *ctx)
2597 : {
2598 0 : return isl_calloc_type(ctx, struct isl_ast_op_printed);
2599 : }
2600 :
2601 : /* Free a struct isl_ast_op_printed.
2602 : */
2603 0 : static void free_printed(void *user)
2604 : {
2605 0 : free(user);
2606 0 : }
2607 :
2608 : /* Ensure that "p" has an isl_ast_op_printed note identified by "id".
2609 : */
2610 0 : static __isl_give isl_printer *alloc_printed(__isl_take isl_printer *p,
2611 : __isl_keep isl_id *id)
2612 : {
2613 0 : return alloc_note(p, id, &create_printed, &free_printed);
2614 : }
2615 :
2616 : /* Create an identifier that is used to store
2617 : * an isl_ast_op_printed note.
2618 : */
2619 0 : static __isl_give isl_id *printed_id(isl_ctx *ctx)
2620 : {
2621 0 : return isl_id_alloc(ctx, "isl_ast_op_type_printed", NULL);
2622 : }
2623 :
2624 : /* Did the user specify that a macro definition should only be
2625 : * printed once and has a macro definition for "type" already
2626 : * been printed to "p"?
2627 : * If definitions should only be printed once, but a definition
2628 : * for "p" has not yet been printed, then mark it as having been
2629 : * printed so that it will not printed again.
2630 : * The actual printing is taken care of by the caller.
2631 : */
2632 0 : static isl_bool already_printed_once(__isl_keep isl_printer *p,
2633 : enum isl_ast_op_type type)
2634 : {
2635 : isl_ctx *ctx;
2636 : isl_id *id;
2637 : struct isl_ast_op_printed *printed;
2638 :
2639 0 : if (!p)
2640 0 : return isl_bool_error;
2641 :
2642 0 : ctx = isl_printer_get_ctx(p);
2643 0 : if (!isl_options_get_ast_print_macro_once(ctx))
2644 0 : return isl_bool_false;
2645 :
2646 0 : if (type > isl_ast_op_last)
2647 0 : isl_die(isl_printer_get_ctx(p), isl_error_invalid,
2648 : "invalid type", return isl_bool_error);
2649 :
2650 0 : id = printed_id(isl_printer_get_ctx(p));
2651 0 : p = alloc_printed(p, id);
2652 0 : printed = get_note(p, id);
2653 0 : isl_id_free(id);
2654 0 : if (!printed)
2655 0 : return isl_bool_error;
2656 :
2657 0 : if (printed->printed[type])
2658 0 : return isl_bool_true;
2659 :
2660 0 : printed->printed[type] = 1;
2661 0 : return isl_bool_false;
2662 : }
2663 :
2664 : /* Print a macro definition for the operator "type".
2665 : *
2666 : * If the user has specified that a macro definition should
2667 : * only be printed once to any given printer and if the macro definition
2668 : * has already been printed to "p", then do not print the definition.
2669 : */
2670 0 : __isl_give isl_printer *isl_ast_op_type_print_macro(
2671 : enum isl_ast_op_type type, __isl_take isl_printer *p)
2672 : {
2673 : isl_bool skip;
2674 :
2675 0 : skip = already_printed_once(p, type);
2676 0 : if (skip < 0)
2677 0 : return isl_printer_free(p);
2678 0 : if (skip)
2679 0 : return p;
2680 :
2681 0 : switch (type) {
2682 : case isl_ast_op_min:
2683 0 : p = isl_printer_start_line(p);
2684 0 : p = isl_printer_print_str(p, "#define ");
2685 0 : p = isl_printer_print_str(p, get_op_str_c(p, type));
2686 0 : p = isl_printer_print_str(p,
2687 : "(x,y) ((x) < (y) ? (x) : (y))");
2688 0 : p = isl_printer_end_line(p);
2689 0 : break;
2690 : case isl_ast_op_max:
2691 0 : p = isl_printer_start_line(p);
2692 0 : p = isl_printer_print_str(p, "#define ");
2693 0 : p = isl_printer_print_str(p, get_op_str_c(p, type));
2694 0 : p = isl_printer_print_str(p,
2695 : "(x,y) ((x) > (y) ? (x) : (y))");
2696 0 : p = isl_printer_end_line(p);
2697 0 : break;
2698 : case isl_ast_op_fdiv_q:
2699 0 : p = isl_printer_start_line(p);
2700 0 : p = isl_printer_print_str(p, "#define ");
2701 0 : p = isl_printer_print_str(p, get_op_str_c(p, type));
2702 0 : p = isl_printer_print_str(p,
2703 : "(n,d) "
2704 : "(((n)<0) ? -((-(n)+(d)-1)/(d)) : (n)/(d))");
2705 0 : p = isl_printer_end_line(p);
2706 0 : break;
2707 : default:
2708 0 : break;
2709 : }
2710 :
2711 0 : return p;
2712 : }
2713 :
2714 : /* Call "fn" for each type of operation represented in the "macros"
2715 : * bit vector.
2716 : */
2717 0 : static isl_stat foreach_ast_op_type(int macros,
2718 : isl_stat (*fn)(enum isl_ast_op_type type, void *user), void *user)
2719 : {
2720 0 : if (macros & ISL_AST_MACRO_MIN && fn(isl_ast_op_min, user) < 0)
2721 0 : return isl_stat_error;
2722 0 : if (macros & ISL_AST_MACRO_MAX && fn(isl_ast_op_max, user) < 0)
2723 0 : return isl_stat_error;
2724 0 : if (macros & ISL_AST_MACRO_FLOORD && fn(isl_ast_op_fdiv_q, user) < 0)
2725 0 : return isl_stat_error;
2726 :
2727 0 : return isl_stat_ok;
2728 : }
2729 :
2730 : /* Call "fn" for each type of operation that appears in "expr"
2731 : * and that requires a macro definition.
2732 : */
2733 0 : isl_stat isl_ast_expr_foreach_ast_op_type(__isl_keep isl_ast_expr *expr,
2734 : isl_stat (*fn)(enum isl_ast_op_type type, void *user), void *user)
2735 : {
2736 : int macros;
2737 :
2738 0 : if (!expr)
2739 0 : return isl_stat_error;
2740 :
2741 0 : macros = ast_expr_required_macros(expr, 0);
2742 0 : return foreach_ast_op_type(macros, fn, user);
2743 : }
2744 :
2745 : /* Call "fn" for each type of operation that appears in "node"
2746 : * and that requires a macro definition.
2747 : */
2748 0 : isl_stat isl_ast_node_foreach_ast_op_type(__isl_keep isl_ast_node *node,
2749 : isl_stat (*fn)(enum isl_ast_op_type type, void *user), void *user)
2750 : {
2751 : int macros;
2752 :
2753 0 : if (!node)
2754 0 : return isl_stat_error;
2755 :
2756 0 : macros = ast_node_required_macros(node, 0);
2757 0 : return foreach_ast_op_type(macros, fn, user);
2758 : }
2759 :
2760 0 : static isl_stat ast_op_type_print_macro(enum isl_ast_op_type type, void *user)
2761 : {
2762 0 : isl_printer **p = user;
2763 :
2764 0 : *p = isl_ast_op_type_print_macro(type, *p);
2765 :
2766 0 : return isl_stat_ok;
2767 : }
2768 :
2769 : /* Print macro definitions for all the macros used in the result
2770 : * of printing "expr".
2771 : */
2772 0 : __isl_give isl_printer *isl_ast_expr_print_macros(
2773 : __isl_keep isl_ast_expr *expr, __isl_take isl_printer *p)
2774 : {
2775 0 : if (isl_ast_expr_foreach_ast_op_type(expr,
2776 : &ast_op_type_print_macro, &p) < 0)
2777 0 : return isl_printer_free(p);
2778 0 : return p;
2779 : }
2780 :
2781 : /* Print macro definitions for all the macros used in the result
2782 : * of printing "node".
2783 : */
2784 0 : __isl_give isl_printer *isl_ast_node_print_macros(
2785 : __isl_keep isl_ast_node *node, __isl_take isl_printer *p)
2786 : {
2787 0 : if (isl_ast_node_foreach_ast_op_type(node,
2788 : &ast_op_type_print_macro, &p) < 0)
2789 0 : return isl_printer_free(p);
2790 0 : return p;
2791 : }
2792 :
2793 : /* Return a string containing C code representing this isl_ast_expr.
2794 : */
2795 0 : __isl_give char *isl_ast_expr_to_C_str(__isl_keep isl_ast_expr *expr)
2796 : {
2797 : isl_printer *p;
2798 : char *str;
2799 :
2800 0 : if (!expr)
2801 0 : return NULL;
2802 :
2803 0 : p = isl_printer_to_str(isl_ast_expr_get_ctx(expr));
2804 0 : p = isl_printer_set_output_format(p, ISL_FORMAT_C);
2805 0 : p = isl_printer_print_ast_expr(p, expr);
2806 :
2807 0 : str = isl_printer_get_str(p);
2808 :
2809 0 : isl_printer_free(p);
2810 :
2811 0 : return str;
2812 : }
2813 :
2814 : /* Return a string containing C code representing this isl_ast_node.
2815 : */
2816 0 : __isl_give char *isl_ast_node_to_C_str(__isl_keep isl_ast_node *node)
2817 : {
2818 : isl_printer *p;
2819 : char *str;
2820 :
2821 0 : if (!node)
2822 0 : return NULL;
2823 :
2824 0 : p = isl_printer_to_str(isl_ast_node_get_ctx(node));
2825 0 : p = isl_printer_set_output_format(p, ISL_FORMAT_C);
2826 0 : p = isl_printer_print_ast_node(p, node);
2827 :
2828 0 : str = isl_printer_get_str(p);
2829 :
2830 0 : isl_printer_free(p);
2831 :
2832 0 : return str;
2833 : }
|