CLooG 0.18.4
[cloog.git] / source / pprint.c
blobc7e494fc4254ffa9a54edf51bc3d8a07bbcbade5
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 = osl_statement_get_body(stmt);
316 if ((body != NULL) &&
317 (body->expression != NULL) &&
318 (body->iterators != NULL)) {
319 expr = osl_util_identifier_substitution(body->expression->string[0],
320 body->iterators->string);
321 tmp = expr;
322 /* Print the body expression, substituting the @...@ markers. */
323 while (*expr) {
324 if (*expr == '@') {
325 int iterator;
326 expr += sscanf(expr, "@%d", &iterator) + 2; /* 2 for the @s */
327 t = u->substitutions;
328 for (i = 0; i < iterator; i++)
329 t = t->next;
330 pprint_assignment(options, dst, (struct clast_assignment *)t);
331 } else {
332 fprintf(dst, "%c", *expr++);
335 fprintf(dst, "\n");
336 free(tmp);
337 return 1;
340 #endif
341 return 0;
344 /* pprint_parentheses_are_safer function:
345 * this function returns 1 if it decides that it would be safer to put
346 * parentheses around the clast_assignment when it is used as a macro
347 * parameter, 0 otherwise.
348 * \param[in] s Pointer to the clast_assignment to check.
349 * \return 1 if we should print parentheses around s, 0 otherwise.
351 static int pprint_parentheses_are_safer(struct clast_assignment * s) {
352 /* Expressions of the form X = Y should not be used in macros, so we
353 * consider readability first for them and avoid parentheses.
354 * Also, expressions having only one term can live without parentheses.
356 if ((s->LHS) ||
357 (s->RHS->type == clast_expr_term) ||
358 ((s->RHS->type == clast_expr_red) &&
359 (((struct clast_reduction *)(s->RHS))->n == 1) &&
360 (((struct clast_reduction *)(s->RHS))->elts[0]->type ==
361 clast_expr_term)))
362 return 0;
364 return 1;
367 void pprint_user_stmt(struct cloogoptions *options, FILE *dst,
368 struct clast_user_stmt *u)
370 int parenthesis_to_close = 0;
371 struct clast_stmt *t;
373 if (pprint_osl_body(options, dst, u))
374 return;
376 if (u->statement->name)
377 fprintf(dst, "%s", u->statement->name);
378 else
379 fprintf(dst, "S%d", u->statement->number);
380 fprintf(dst, "(");
381 for (t = u->substitutions; t; t = t->next) {
382 assert(CLAST_STMT_IS_A(t, stmt_ass));
383 if (pprint_parentheses_are_safer((struct clast_assignment *)t)) {
384 fprintf(dst, "(");
385 parenthesis_to_close = 1;
387 pprint_assignment(options, dst, (struct clast_assignment *)t);
388 if (t->next) {
389 if (parenthesis_to_close) {
390 fprintf(dst, ")");
391 parenthesis_to_close = 0;
393 fprintf(dst, ",");
396 if (parenthesis_to_close)
397 fprintf(dst, ")");
398 fprintf(dst, ")");
399 if (options->language != CLOOG_LANGUAGE_FORTRAN)
400 fprintf(dst, ";");
401 fprintf(dst, "\n");
404 void pprint_guard(struct cloogoptions *options, FILE *dst, int indent,
405 struct clast_guard *g)
407 int k;
408 if (options->language == CLOOG_LANGUAGE_FORTRAN)
409 fprintf(dst,"IF ");
410 else
411 fprintf(dst,"if ");
412 if (g->n > 1)
413 fprintf(dst,"(");
414 for (k = 0; k < g->n; ++k) {
415 if (k > 0) {
416 if (options->language == CLOOG_LANGUAGE_FORTRAN)
417 fprintf(dst," .AND. ");
418 else
419 fprintf(dst," && ");
421 fprintf(dst,"(");
422 pprint_equation(options, dst, &g->eq[k]);
423 fprintf(dst,")");
425 if (g->n > 1)
426 fprintf(dst,")");
427 if (options->language == CLOOG_LANGUAGE_FORTRAN)
428 fprintf(dst," THEN\n");
429 else
430 fprintf(dst," {\n");
432 pprint_stmt_list(options, dst, indent + INDENT_STEP, g->then);
434 fprintf(dst, "%*s", indent, "");
435 if (options->language == CLOOG_LANGUAGE_FORTRAN)
436 fprintf(dst,"END IF\n");
437 else
438 fprintf(dst,"}\n");
441 void pprint_for(struct cloogoptions *options, FILE *dst, int indent,
442 struct clast_for *f)
444 if (options->language == CLOOG_LANGUAGE_C) {
445 if (f->time_var_name) {
446 fprintf(dst, "IF_TIME(%s_start = cloog_util_rtclock());\n",
447 (f->time_var_name) ? f->time_var_name : "");
449 if ((f->parallel & CLAST_PARALLEL_OMP) && !(f->parallel & CLAST_PARALLEL_MPI)) {
450 if (f->LB) {
451 fprintf(dst, "lbp=");
452 pprint_expr(options, dst, f->LB);
453 fprintf(dst, ";\n");
455 if (f->UB) {
456 fprintf(dst, "%*s", indent, "");
457 fprintf(dst, "ubp=");
458 pprint_expr(options, dst, f->UB);
459 fprintf(dst, ";\n");
461 fprintf(dst, "#pragma omp parallel for%s%s%s%s%s%s\n",
462 (f->private_vars)? " private(":"",
463 (f->private_vars)? f->private_vars: "",
464 (f->private_vars)? ")":"",
465 (f->reduction_vars)? " reduction(": "",
466 (f->reduction_vars)? f->reduction_vars: "",
467 (f->reduction_vars)? ")": "");
468 fprintf(dst, "%*s", indent, "");
470 if ((f->parallel & CLAST_PARALLEL_VEC) && !(f->parallel & CLAST_PARALLEL_OMP)
471 && !(f->parallel & CLAST_PARALLEL_MPI)) {
472 if (f->LB) {
473 fprintf(dst, "lbv=");
474 pprint_expr(options, dst, f->LB);
475 fprintf(dst, ";\n");
477 if (f->UB) {
478 fprintf(dst, "%*s", indent, "");
479 fprintf(dst, "ubv=");
480 pprint_expr(options, dst, f->UB);
481 fprintf(dst, ";\n");
483 fprintf(dst, "%*s#pragma ivdep\n", indent, "");
484 fprintf(dst, "%*s#pragma vector always\n", indent, "");
485 fprintf(dst, "%*s", indent, "");
487 if (f->parallel & CLAST_PARALLEL_MPI) {
488 if (f->LB) {
489 fprintf(dst, "_lb_dist=");
490 pprint_expr(options, dst, f->LB);
491 fprintf(dst, ";\n");
493 if (f->UB) {
494 fprintf(dst, "%*s", indent, "");
495 fprintf(dst, "_ub_dist=");
496 pprint_expr(options, dst, f->UB);
497 fprintf(dst, ";\n");
499 fprintf(dst, "%*s", indent, "");
500 fprintf(dst, "polyrt_loop_dist(_lb_dist, _ub_dist, nprocs, my_rank, &lbp, &ubp);\n");
501 if (f->parallel & CLAST_PARALLEL_OMP) {
502 fprintf(dst, "#pragma omp parallel for%s%s%s%s%s%s\n",
503 (f->private_vars)? " private(":"",
504 (f->private_vars)? f->private_vars: "",
505 (f->private_vars)? ")":"",
506 (f->reduction_vars)? " reduction(": "",
507 (f->reduction_vars)? f->reduction_vars: "",
508 (f->reduction_vars)? ")": "");
510 fprintf(dst, "%*s", indent, "");
515 if (options->language == CLOOG_LANGUAGE_FORTRAN)
516 fprintf(dst, "DO ");
517 else
518 fprintf(dst, "for (");
520 if (f->LB) {
521 fprintf(dst, "%s=", f->iterator);
522 if (f->parallel & (CLAST_PARALLEL_OMP | CLAST_PARALLEL_MPI)) {
523 fprintf(dst, "lbp");
524 }else if (f->parallel & CLAST_PARALLEL_VEC){
525 fprintf(dst, "lbv");
526 }else{
527 pprint_expr(options, dst, f->LB);
529 } else if (options->language == CLOOG_LANGUAGE_FORTRAN)
530 cloog_die("unbounded loops not allowed in FORTRAN.\n");
532 if (options->language == CLOOG_LANGUAGE_FORTRAN)
533 fprintf(dst,", ");
534 else
535 fprintf(dst,";");
537 if (f->UB) {
538 if (options->language != CLOOG_LANGUAGE_FORTRAN)
539 fprintf(dst,"%s<=", f->iterator);
541 if (f->parallel & (CLAST_PARALLEL_OMP | CLAST_PARALLEL_MPI)) {
542 fprintf(dst, "ubp");
543 }else if (f->parallel & CLAST_PARALLEL_VEC){
544 fprintf(dst, "ubv");
545 }else{
546 pprint_expr(options, dst, f->UB);
548 }else if (options->language == CLOOG_LANGUAGE_FORTRAN)
549 cloog_die("unbounded loops not allowed in FORTRAN.\n");
551 if (options->language == CLOOG_LANGUAGE_FORTRAN) {
552 if (cloog_int_gt_si(f->stride, 1))
553 cloog_int_print(dst, f->stride);
554 fprintf(dst,"\n");
556 else {
557 if (cloog_int_gt_si(f->stride, 1)) {
558 fprintf(dst,";%s+=", f->iterator);
559 cloog_int_print(dst, f->stride);
560 fprintf(dst, ") {\n");
561 } else
562 fprintf(dst, ";%s++) {\n", f->iterator);
565 pprint_stmt_list(options, dst, indent + INDENT_STEP, f->body);
567 fprintf(dst, "%*s", indent, "");
568 if (options->language == CLOOG_LANGUAGE_FORTRAN)
569 fprintf(dst,"END DO\n") ;
570 else
571 fprintf(dst,"}\n") ;
573 if (options->language == CLOOG_LANGUAGE_C) {
574 if (f->time_var_name) {
575 fprintf(dst, "IF_TIME(%s += cloog_util_rtclock() - %s_start);\n",
576 (f->time_var_name) ? f->time_var_name : "",
577 (f->time_var_name) ? f->time_var_name : "");
582 void pprint_stmt_list(struct cloogoptions *options, FILE *dst, int indent,
583 struct clast_stmt *s)
585 for ( ; s; s = s->next) {
586 if (CLAST_STMT_IS_A(s, stmt_root))
587 continue;
588 fprintf(dst, "%*s", indent, "");
589 if (CLAST_STMT_IS_A(s, stmt_ass)) {
590 pprint_assignment(options, dst, (struct clast_assignment *) s);
591 if (options->language != CLOOG_LANGUAGE_FORTRAN)
592 fprintf(dst, ";");
593 fprintf(dst, "\n");
594 } else if (CLAST_STMT_IS_A(s, stmt_user)) {
595 pprint_user_stmt(options, dst, (struct clast_user_stmt *) s);
596 } else if (CLAST_STMT_IS_A(s, stmt_for)) {
597 pprint_for(options, dst, indent, (struct clast_for *) s);
598 } else if (CLAST_STMT_IS_A(s, stmt_guard)) {
599 pprint_guard(options, dst, indent, (struct clast_guard *) s);
600 } else if (CLAST_STMT_IS_A(s, stmt_block)) {
601 fprintf(dst, "{\n");
602 pprint_stmt_list(options, dst, indent + INDENT_STEP,
603 ((struct clast_block *)s)->body);
604 fprintf(dst, "%*s", indent, "");
605 fprintf(dst, "}\n");
606 } else {
607 assert(0);
613 /******************************************************************************
614 * Pretty Printing (dirty) functions *
615 ******************************************************************************/
617 void clast_pprint(FILE *foo, struct clast_stmt *root,
618 int indent, CloogOptions *options)
620 pprint_stmt_list(options, foo, indent, root);
624 void clast_pprint_expr(struct cloogoptions *i, FILE *dst, struct clast_expr *e)
626 pprint_expr(i, dst, e);