expose clast_pprint_expr
[cloog.git] / source / pprint.c
blobab4b22fbbeeb364a8c2c4877228975963f53703a
2 /**-------------------------------------------------------------------**
3 ** CLooG **
4 **-------------------------------------------------------------------**
5 ** pprint.c **
6 **-------------------------------------------------------------------**
7 ** First version: october 26th 2001 **
8 **-------------------------------------------------------------------**/
11 /******************************************************************************
12 * CLooG : the Chunky Loop Generator (experimental) *
13 ******************************************************************************
14 * *
15 * Copyright (C) 2001-2005 Cedric Bastoul *
16 * *
17 * This library is free software; you can redistribute it and/or *
18 * modify it under the terms of the GNU Lesser General Public *
19 * License as published by the Free Software Foundation; either *
20 * version 2.1 of the License, or (at your option) any later version. *
21 * *
22 * This library is distributed in the hope that it will be useful, *
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
25 * Lesser General Public License for more details. *
26 * *
27 * You should have received a copy of the GNU Lesser General Public *
28 * License along with this library; if not, write to the Free Software *
29 * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
30 * Boston, MA 02110-1301 USA *
31 * *
32 * CLooG, the Chunky Loop Generator *
33 * Written by Cedric Bastoul, Cedric.Bastoul@inria.fr *
34 * *
35 ******************************************************************************/
36 /* CAUTION: the english used for comments is probably the worst you ever read,
37 * please feel free to correct and improve it !
40 /* June 22nd 2005: General adaptation for GMP.
41 * October 26th 2005: General adaptation from CloogDomain to Matrix data
42 * structure for all constraint systems.
43 * October 27th 2005: General adaptation from CloogEqual to Matrix data
44 * structure for equality spreading.
47 # include <stdlib.h>
48 # include <stdio.h>
49 # include <string.h>
50 #include <assert.h>
51 # include "../include/cloog/cloog.h"
53 #ifdef OSL_SUPPORT
54 #include <osl/util.h>
55 #include <osl/body.h>
56 #include <osl/extensions/extbody.h>
57 #include <osl/statement.h>
58 #include <osl/scop.h>
59 #endif
62 static void pprint_name(FILE *dst, struct clast_name *n);
63 static void pprint_term(struct cloogoptions *i, FILE *dst, struct clast_term *t);
64 static void pprint_sum(struct cloogoptions *opt,
65 FILE *dst, struct clast_reduction *r);
66 static void pprint_binary(struct cloogoptions *i,
67 FILE *dst, struct clast_binary *b);
68 static void pprint_minmax_f(struct cloogoptions *info,
69 FILE *dst, struct clast_reduction *r);
70 static void pprint_minmax_c(struct cloogoptions *info,
71 FILE *dst, struct clast_reduction *r);
72 static void pprint_reduction(struct cloogoptions *i,
73 FILE *dst, struct clast_reduction *r);
74 static void pprint_expr(struct cloogoptions *i, FILE *dst, struct clast_expr *e);
75 static void pprint_equation(struct cloogoptions *i,
76 FILE *dst, struct clast_equation *eq);
77 static void pprint_assignment(struct cloogoptions *i, FILE *dst,
78 struct clast_assignment *a);
79 static void pprint_user_stmt(struct cloogoptions *options, FILE *dst,
80 struct clast_user_stmt *u);
81 static void pprint_guard(struct cloogoptions *options, FILE *dst, int indent,
82 struct clast_guard *g);
83 static void pprint_for(struct cloogoptions *options, FILE *dst, int indent,
84 struct clast_for *f);
85 static void pprint_stmt_list(struct cloogoptions *options, FILE *dst, int indent,
86 struct clast_stmt *s);
89 void pprint_name(FILE *dst, struct clast_name *n)
91 fprintf(dst, "%s", n->name);
94 /**
95 * This function returns a string containing the printing of a value (possibly
96 * an iterator or a parameter with its coefficient or a constant).
97 * - val is the coefficient or constant value,
98 * - name is a string containing the name of the iterator or of the parameter,
100 void pprint_term(struct cloogoptions *i, FILE *dst, struct clast_term *t)
102 if (t->var) {
103 int group = t->var->type == clast_expr_red &&
104 ((struct clast_reduction*) t->var)->n > 1;
105 if (cloog_int_is_one(t->val))
107 else if (cloog_int_is_neg_one(t->val))
108 fprintf(dst, "-");
109 else {
110 cloog_int_print(dst, t->val);
111 fprintf(dst, "*");
113 if (group)
114 fprintf(dst, "(");
115 pprint_expr(i, dst, t->var);
116 if (group)
117 fprintf(dst, ")");
118 } else
119 cloog_int_print(dst, t->val);
122 void pprint_sum(struct cloogoptions *opt, FILE *dst, struct clast_reduction *r)
124 int i;
125 struct clast_term *t;
127 assert(r->n >= 1);
128 assert(r->elts[0]->type == clast_expr_term);
129 t = (struct clast_term *) r->elts[0];
130 pprint_term(opt, dst, t);
132 for (i = 1; i < r->n; ++i) {
133 assert(r->elts[i]->type == clast_expr_term);
134 t = (struct clast_term *) r->elts[i];
135 if (cloog_int_is_pos(t->val))
136 fprintf(dst, "+");
137 pprint_term(opt, dst, t);
141 void pprint_binary(struct cloogoptions *i, FILE *dst, struct clast_binary *b)
143 const char *s1 = NULL, *s2 = NULL, *s3 = NULL;
144 int group = b->LHS->type == clast_expr_red &&
145 ((struct clast_reduction*) b->LHS)->n > 1;
146 if (i->language == CLOOG_LANGUAGE_FORTRAN) {
147 switch (b->type) {
148 case clast_bin_fdiv:
149 s1 = "FLOOR(REAL(", s2 = ")/REAL(", s3 = "))";
150 break;
151 case clast_bin_cdiv:
152 s1 = "CEILING(REAL(", s2 = ")/REAL(", s3 = "))";
153 break;
154 case clast_bin_div:
155 if (group)
156 s1 = "(", s2 = ")/", s3 = "";
157 else
158 s1 = "", s2 = "/", s3 = "";
159 break;
160 case clast_bin_mod:
161 s1 = "MOD(", s2 = ", ", s3 = ")";
162 break;
164 } else {
165 switch (b->type) {
166 case clast_bin_fdiv:
167 s1 = "floord(", s2 = ",", s3 = ")";
168 break;
169 case clast_bin_cdiv:
170 s1 = "ceild(", s2 = ",", s3 = ")";
171 break;
172 case clast_bin_div:
173 if (group)
174 s1 = "(", s2 = ")/", s3 = "";
175 else
176 s1 = "", s2 = "/", s3 = "";
177 break;
178 case clast_bin_mod:
179 if (group)
180 s1 = "(", s2 = ")%", s3 = "";
181 else
182 s1 = "", s2 = "%", s3 = "";
183 break;
186 fprintf(dst, "%s", s1);
187 pprint_expr(i, dst, b->LHS);
188 fprintf(dst, "%s", s2);
189 cloog_int_print(dst, b->RHS);
190 fprintf(dst, "%s", s3);
193 void pprint_minmax_f(struct cloogoptions *info, FILE *dst, struct clast_reduction *r)
195 int i;
196 if (r->n == 0)
197 return;
198 fprintf(dst, r->type == clast_red_max ? "MAX(" : "MIN(");
199 pprint_expr(info, dst, r->elts[0]);
200 for (i = 1; i < r->n; ++i) {
201 fprintf(dst, ",");
202 pprint_expr(info, dst, r->elts[i]);
204 fprintf(dst, ")");
207 void pprint_minmax_c(struct cloogoptions *info, FILE *dst, struct clast_reduction *r)
209 int i;
210 for (i = 1; i < r->n; ++i)
211 fprintf(dst, r->type == clast_red_max ? "max(" : "min(");
212 if (r->n > 0)
213 pprint_expr(info, dst, r->elts[0]);
214 for (i = 1; i < r->n; ++i) {
215 fprintf(dst, ",");
216 pprint_expr(info, dst, r->elts[i]);
217 fprintf(dst, ")");
221 void pprint_reduction(struct cloogoptions *i, FILE *dst, struct clast_reduction *r)
223 switch (r->type) {
224 case clast_red_sum:
225 pprint_sum(i, dst, r);
226 break;
227 case clast_red_min:
228 case clast_red_max:
229 if (r->n == 1) {
230 pprint_expr(i, dst, r->elts[0]);
231 break;
233 if (i->language == CLOOG_LANGUAGE_FORTRAN)
234 pprint_minmax_f(i, dst, r);
235 else
236 pprint_minmax_c(i, dst, r);
237 break;
238 default:
239 assert(0);
243 void pprint_expr(struct cloogoptions *i, FILE *dst, struct clast_expr *e)
245 if (!e)
246 return;
247 switch (e->type) {
248 case clast_expr_name:
249 pprint_name(dst, (struct clast_name*) e);
250 break;
251 case clast_expr_term:
252 pprint_term(i, dst, (struct clast_term*) e);
253 break;
254 case clast_expr_red:
255 pprint_reduction(i, dst, (struct clast_reduction*) e);
256 break;
257 case clast_expr_bin:
258 pprint_binary(i, dst, (struct clast_binary*) e);
259 break;
260 default:
261 assert(0);
265 void pprint_equation(struct cloogoptions *i, FILE *dst, struct clast_equation *eq)
267 pprint_expr(i, dst, eq->LHS);
268 if (eq->sign == 0)
269 fprintf(dst, " == ");
270 else if (eq->sign > 0)
271 fprintf(dst, " >= ");
272 else
273 fprintf(dst, " <= ");
274 pprint_expr(i, dst, eq->RHS);
277 void pprint_assignment(struct cloogoptions *i, FILE *dst,
278 struct clast_assignment *a)
280 if (a->LHS)
281 fprintf(dst, "%s = ", a->LHS);
282 pprint_expr(i, dst, a->RHS);
287 * pprint_osl_body function:
288 * this function pretty-prints the OpenScop body of a given statement.
289 * It returns 1 if it succeeds to find an OpenScop body to print for
290 * that statement, 0 otherwise.
291 * \param[in] options CLooG Options.
292 * \param[in] dst Output stream.
293 * \param[in] u Statement to print the OpenScop body.
294 * \return 1 on success to pretty-print an OpenScop body for u, 0 otherwise.
296 int pprint_osl_body(struct cloogoptions *options, FILE *dst,
297 struct clast_user_stmt *u) {
298 #ifdef OSL_SUPPORT
299 int i;
300 char *expr, *tmp;
301 struct clast_stmt *t;
302 osl_scop_p scop = options->scop;
303 osl_statement_p stmt;
304 osl_body_p body;
306 if ((scop != NULL) &&
307 (osl_statement_number(scop->statement) >= u->statement->number)) {
308 stmt = scop->statement;
310 /* Go to the convenient statement in the SCoP. */
311 for (i = 1; i < u->statement->number; i++)
312 stmt = stmt->next;
314 /* Ensure it has a printable body. */
315 body = NULL;
316 if (osl_generic_has_URI(stmt->body, OSL_URI_BODY)) {
317 body = stmt->body->data;
318 } else if (osl_generic_has_URI(stmt->body, OSL_URI_EXTBODY)) {
319 if (stmt->body->data != NULL) {
320 body = ((osl_extbody_p)(stmt->body->data))->body;
323 if ((body != NULL) &&
324 (body->expression != NULL) &&
325 (body->iterators != NULL)) {
326 expr = osl_util_identifier_substitution(body->expression->string[0],
327 body->iterators->string);
328 tmp = expr;
329 /* Print the body expression, substituting the @...@ markers. */
330 while (*expr) {
331 if (*expr == '@') {
332 int iterator;
333 expr += sscanf(expr, "@%d", &iterator) + 2; /* 2 for the @s */
334 t = u->substitutions;
335 for (i = 0; i < iterator; i++)
336 t = t->next;
337 pprint_assignment(options, dst, (struct clast_assignment *)t);
338 } else {
339 fprintf(dst, "%c", *expr++);
342 fprintf(dst, "\n");
343 free(tmp);
344 return 1;
347 #endif
348 return 0;
351 /* pprint_parentheses_are_safer function:
352 * this function returns 1 if it decides that it would be safer to put
353 * parentheses around the clast_assignment when it is used as a macro
354 * parameter, 0 otherwise.
355 * \param[in] s Pointer to the clast_assignment to check.
356 * \return 1 if we should print parentheses around s, 0 otherwise.
358 static int pprint_parentheses_are_safer(struct clast_assignment * s) {
359 /* Expressions of the form X = Y should not be used in macros, so we
360 * consider readability first for them and avoid parentheses.
361 * Also, expressions having only one term can live without parentheses.
363 if ((s->LHS) ||
364 (s->RHS->type == clast_expr_term) ||
365 ((s->RHS->type == clast_expr_red) &&
366 (((struct clast_reduction *)(s->RHS))->n == 1) &&
367 (((struct clast_reduction *)(s->RHS))->elts[0]->type ==
368 clast_expr_term)))
369 return 0;
371 return 1;
374 void pprint_user_stmt(struct cloogoptions *options, FILE *dst,
375 struct clast_user_stmt *u)
377 int parenthesis_to_close = 0;
378 struct clast_stmt *t;
380 if (pprint_osl_body(options, dst, u))
381 return;
383 if (u->statement->name)
384 fprintf(dst, "%s", u->statement->name);
385 else
386 fprintf(dst, "S%d", u->statement->number);
387 fprintf(dst, "(");
388 for (t = u->substitutions; t; t = t->next) {
389 assert(CLAST_STMT_IS_A(t, stmt_ass));
390 if (pprint_parentheses_are_safer((struct clast_assignment *)t)) {
391 fprintf(dst, "(");
392 parenthesis_to_close = 1;
394 pprint_assignment(options, dst, (struct clast_assignment *)t);
395 if (t->next) {
396 if (parenthesis_to_close) {
397 fprintf(dst, ")");
398 parenthesis_to_close = 0;
400 fprintf(dst, ",");
403 if (parenthesis_to_close)
404 fprintf(dst, ")");
405 fprintf(dst, ")");
406 if (options->language != CLOOG_LANGUAGE_FORTRAN)
407 fprintf(dst, ";");
408 fprintf(dst, "\n");
411 void pprint_guard(struct cloogoptions *options, FILE *dst, int indent,
412 struct clast_guard *g)
414 int k;
415 if (options->language == CLOOG_LANGUAGE_FORTRAN)
416 fprintf(dst,"IF ");
417 else
418 fprintf(dst,"if ");
419 if (g->n > 1)
420 fprintf(dst,"(");
421 for (k = 0; k < g->n; ++k) {
422 if (k > 0) {
423 if (options->language == CLOOG_LANGUAGE_FORTRAN)
424 fprintf(dst," .AND. ");
425 else
426 fprintf(dst," && ");
428 fprintf(dst,"(");
429 pprint_equation(options, dst, &g->eq[k]);
430 fprintf(dst,")");
432 if (g->n > 1)
433 fprintf(dst,")");
434 if (options->language == CLOOG_LANGUAGE_FORTRAN)
435 fprintf(dst," THEN\n");
436 else
437 fprintf(dst," {\n");
439 pprint_stmt_list(options, dst, indent + INDENT_STEP, g->then);
441 fprintf(dst, "%*s", indent, "");
442 if (options->language == CLOOG_LANGUAGE_FORTRAN)
443 fprintf(dst,"END IF\n");
444 else
445 fprintf(dst,"}\n");
448 void pprint_for(struct cloogoptions *options, FILE *dst, int indent,
449 struct clast_for *f)
451 if (options->language == CLOOG_LANGUAGE_C) {
452 if (f->time_var_name) {
453 fprintf(dst, "IF_TIME(%s_start = cloog_util_rtclock());\n",
454 (f->time_var_name) ? f->time_var_name : "");
456 if ((f->parallel & CLAST_PARALLEL_OMP) && !(f->parallel & CLAST_PARALLEL_MPI)) {
457 if (f->LB) {
458 fprintf(dst, "lbp=");
459 pprint_expr(options, dst, f->LB);
460 fprintf(dst, ";\n");
462 if (f->UB) {
463 fprintf(dst, "%*s", indent, "");
464 fprintf(dst, "ubp=");
465 pprint_expr(options, dst, f->UB);
466 fprintf(dst, ";\n");
468 fprintf(dst, "#pragma omp parallel for%s%s%s%s%s%s\n",
469 (f->private_vars)? " private(":"",
470 (f->private_vars)? f->private_vars: "",
471 (f->private_vars)? ")":"",
472 (f->reduction_vars)? " reduction(": "",
473 (f->reduction_vars)? f->reduction_vars: "",
474 (f->reduction_vars)? ")": "");
475 fprintf(dst, "%*s", indent, "");
477 if ((f->parallel & CLAST_PARALLEL_VEC) && !(f->parallel & CLAST_PARALLEL_OMP)
478 && !(f->parallel & CLAST_PARALLEL_MPI)) {
479 if (f->LB) {
480 fprintf(dst, "lbv=");
481 pprint_expr(options, dst, f->LB);
482 fprintf(dst, ";\n");
484 if (f->UB) {
485 fprintf(dst, "%*s", indent, "");
486 fprintf(dst, "ubv=");
487 pprint_expr(options, dst, f->UB);
488 fprintf(dst, ";\n");
490 fprintf(dst, "%*s#pragma ivdep\n", indent, "");
491 fprintf(dst, "%*s#pragma vector always\n", indent, "");
492 fprintf(dst, "%*s", indent, "");
494 if (f->parallel & CLAST_PARALLEL_MPI) {
495 if (f->LB) {
496 fprintf(dst, "_lb_dist=");
497 pprint_expr(options, dst, f->LB);
498 fprintf(dst, ";\n");
500 if (f->UB) {
501 fprintf(dst, "%*s", indent, "");
502 fprintf(dst, "_ub_dist=");
503 pprint_expr(options, dst, f->UB);
504 fprintf(dst, ";\n");
506 fprintf(dst, "%*s", indent, "");
507 fprintf(dst, "polyrt_loop_dist(_lb_dist, _ub_dist, nprocs, my_rank, &lbp, &ubp);\n");
508 if (f->parallel & CLAST_PARALLEL_OMP) {
509 fprintf(dst, "#pragma omp parallel for%s%s%s%s%s%s\n",
510 (f->private_vars)? " private(":"",
511 (f->private_vars)? f->private_vars: "",
512 (f->private_vars)? ")":"",
513 (f->reduction_vars)? " reduction(": "",
514 (f->reduction_vars)? f->reduction_vars: "",
515 (f->reduction_vars)? ")": "");
517 fprintf(dst, "%*s", indent, "");
522 if (options->language == CLOOG_LANGUAGE_FORTRAN)
523 fprintf(dst, "DO ");
524 else
525 fprintf(dst, "for (");
527 if (f->LB) {
528 fprintf(dst, "%s=", f->iterator);
529 if (f->parallel & (CLAST_PARALLEL_OMP | CLAST_PARALLEL_MPI)) {
530 fprintf(dst, "lbp");
531 }else if (f->parallel & CLAST_PARALLEL_VEC){
532 fprintf(dst, "lbv");
533 }else{
534 pprint_expr(options, dst, f->LB);
536 } else if (options->language == CLOOG_LANGUAGE_FORTRAN)
537 cloog_die("unbounded loops not allowed in FORTRAN.\n");
539 if (options->language == CLOOG_LANGUAGE_FORTRAN)
540 fprintf(dst,", ");
541 else
542 fprintf(dst,";");
544 if (f->UB) {
545 if (options->language != CLOOG_LANGUAGE_FORTRAN)
546 fprintf(dst,"%s<=", f->iterator);
548 if (f->parallel & (CLAST_PARALLEL_OMP | CLAST_PARALLEL_MPI)) {
549 fprintf(dst, "ubp");
550 }else if (f->parallel & CLAST_PARALLEL_VEC){
551 fprintf(dst, "ubv");
552 }else{
553 pprint_expr(options, dst, f->UB);
555 }else if (options->language == CLOOG_LANGUAGE_FORTRAN)
556 cloog_die("unbounded loops not allowed in FORTRAN.\n");
558 if (options->language == CLOOG_LANGUAGE_FORTRAN) {
559 if (cloog_int_gt_si(f->stride, 1))
560 cloog_int_print(dst, f->stride);
561 fprintf(dst,"\n");
563 else {
564 if (cloog_int_gt_si(f->stride, 1)) {
565 fprintf(dst,";%s+=", f->iterator);
566 cloog_int_print(dst, f->stride);
567 fprintf(dst, ") {\n");
568 } else
569 fprintf(dst, ";%s++) {\n", f->iterator);
572 pprint_stmt_list(options, dst, indent + INDENT_STEP, f->body);
574 fprintf(dst, "%*s", indent, "");
575 if (options->language == CLOOG_LANGUAGE_FORTRAN)
576 fprintf(dst,"END DO\n") ;
577 else
578 fprintf(dst,"}\n") ;
580 if (options->language == CLOOG_LANGUAGE_C) {
581 if (f->time_var_name) {
582 fprintf(dst, "IF_TIME(%s += cloog_util_rtclock() - %s_start);\n",
583 (f->time_var_name) ? f->time_var_name : "",
584 (f->time_var_name) ? f->time_var_name : "");
589 void pprint_stmt_list(struct cloogoptions *options, FILE *dst, int indent,
590 struct clast_stmt *s)
592 for ( ; s; s = s->next) {
593 if (CLAST_STMT_IS_A(s, stmt_root))
594 continue;
595 fprintf(dst, "%*s", indent, "");
596 if (CLAST_STMT_IS_A(s, stmt_ass)) {
597 pprint_assignment(options, dst, (struct clast_assignment *) s);
598 if (options->language != CLOOG_LANGUAGE_FORTRAN)
599 fprintf(dst, ";");
600 fprintf(dst, "\n");
601 } else if (CLAST_STMT_IS_A(s, stmt_user)) {
602 pprint_user_stmt(options, dst, (struct clast_user_stmt *) s);
603 } else if (CLAST_STMT_IS_A(s, stmt_for)) {
604 pprint_for(options, dst, indent, (struct clast_for *) s);
605 } else if (CLAST_STMT_IS_A(s, stmt_guard)) {
606 pprint_guard(options, dst, indent, (struct clast_guard *) s);
607 } else if (CLAST_STMT_IS_A(s, stmt_block)) {
608 fprintf(dst, "{\n");
609 pprint_stmt_list(options, dst, indent + INDENT_STEP,
610 ((struct clast_block *)s)->body);
611 fprintf(dst, "%*s", indent, "");
612 fprintf(dst, "}\n");
613 } else {
614 assert(0);
620 /******************************************************************************
621 * Pretty Printing (dirty) functions *
622 ******************************************************************************/
624 void clast_pprint(FILE *foo, struct clast_stmt *root,
625 int indent, CloogOptions *options)
627 pprint_stmt_list(options, foo, indent, root);
631 void clast_pprint_expr(struct cloogoptions *i, FILE *dst, struct clast_expr *e)
633 pprint_expr(i, dst, e);