Directly print OpenScop statement bodies when possible
[cloog.git] / source / pprint.c
blob9c7f1d466e283ca19563bf9805916270575f7f55
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/statement.h>
57 #include <osl/scop.h>
58 #endif
61 static void pprint_name(FILE *dst, struct clast_name *n);
62 static void pprint_term(struct cloogoptions *i, FILE *dst, struct clast_term *t);
63 static void pprint_sum(struct cloogoptions *opt,
64 FILE *dst, struct clast_reduction *r);
65 static void pprint_binary(struct cloogoptions *i,
66 FILE *dst, struct clast_binary *b);
67 static void pprint_minmax_f(struct cloogoptions *info,
68 FILE *dst, struct clast_reduction *r);
69 static void pprint_minmax_c(struct cloogoptions *info,
70 FILE *dst, struct clast_reduction *r);
71 static void pprint_reduction(struct cloogoptions *i,
72 FILE *dst, struct clast_reduction *r);
73 static void pprint_expr(struct cloogoptions *i, FILE *dst, struct clast_expr *e);
74 static void pprint_equation(struct cloogoptions *i,
75 FILE *dst, struct clast_equation *eq);
76 static void pprint_assignment(struct cloogoptions *i, FILE *dst,
77 struct clast_assignment *a);
78 static void pprint_user_stmt(struct cloogoptions *options, FILE *dst,
79 struct clast_user_stmt *u);
80 static void pprint_guard(struct cloogoptions *options, FILE *dst, int indent,
81 struct clast_guard *g);
82 static void pprint_for(struct cloogoptions *options, FILE *dst, int indent,
83 struct clast_for *f);
84 static void pprint_stmt_list(struct cloogoptions *options, FILE *dst, int indent,
85 struct clast_stmt *s);
88 void pprint_name(FILE *dst, struct clast_name *n)
90 fprintf(dst, "%s", n->name);
93 /**
94 * This function returns a string containing the printing of a value (possibly
95 * an iterator or a parameter with its coefficient or a constant).
96 * - val is the coefficient or constant value,
97 * - name is a string containing the name of the iterator or of the parameter,
99 void pprint_term(struct cloogoptions *i, FILE *dst, struct clast_term *t)
101 if (t->var) {
102 int group = t->var->type == clast_expr_red &&
103 ((struct clast_reduction*) t->var)->n > 1;
104 if (cloog_int_is_one(t->val))
106 else if (cloog_int_is_neg_one(t->val))
107 fprintf(dst, "-");
108 else {
109 cloog_int_print(dst, t->val);
110 fprintf(dst, "*");
112 if (group)
113 fprintf(dst, "(");
114 pprint_expr(i, dst, t->var);
115 if (group)
116 fprintf(dst, ")");
117 } else
118 cloog_int_print(dst, t->val);
121 void pprint_sum(struct cloogoptions *opt, FILE *dst, struct clast_reduction *r)
123 int i;
124 struct clast_term *t;
126 assert(r->n >= 1);
127 assert(r->elts[0]->type == clast_expr_term);
128 t = (struct clast_term *) r->elts[0];
129 pprint_term(opt, dst, t);
131 for (i = 1; i < r->n; ++i) {
132 assert(r->elts[i]->type == clast_expr_term);
133 t = (struct clast_term *) r->elts[i];
134 if (cloog_int_is_pos(t->val))
135 fprintf(dst, "+");
136 pprint_term(opt, dst, t);
140 void pprint_binary(struct cloogoptions *i, FILE *dst, struct clast_binary *b)
142 const char *s1 = NULL, *s2 = NULL, *s3 = NULL;
143 int group = b->LHS->type == clast_expr_red &&
144 ((struct clast_reduction*) b->LHS)->n > 1;
145 if (i->language == CLOOG_LANGUAGE_FORTRAN) {
146 switch (b->type) {
147 case clast_bin_fdiv:
148 s1 = "FLOOR(REAL(", s2 = ")/REAL(", s3 = "))";
149 break;
150 case clast_bin_cdiv:
151 s1 = "CEILING(REAL(", s2 = ")/REAL(", s3 = "))";
152 break;
153 case clast_bin_div:
154 if (group)
155 s1 = "(", s2 = ")/", s3 = "";
156 else
157 s1 = "", s2 = "/", s3 = "";
158 break;
159 case clast_bin_mod:
160 s1 = "MOD(", s2 = ", ", s3 = ")";
161 break;
163 } else {
164 switch (b->type) {
165 case clast_bin_fdiv:
166 s1 = "floord(", s2 = ",", s3 = ")";
167 break;
168 case clast_bin_cdiv:
169 s1 = "ceild(", s2 = ",", s3 = ")";
170 break;
171 case clast_bin_div:
172 if (group)
173 s1 = "(", s2 = ")/", s3 = "";
174 else
175 s1 = "", s2 = "/", s3 = "";
176 break;
177 case clast_bin_mod:
178 if (group)
179 s1 = "(", s2 = ")%", s3 = "";
180 else
181 s1 = "", s2 = "%", s3 = "";
182 break;
185 fprintf(dst, "%s", s1);
186 pprint_expr(i, dst, b->LHS);
187 fprintf(dst, "%s", s2);
188 cloog_int_print(dst, b->RHS);
189 fprintf(dst, "%s", s3);
192 void pprint_minmax_f(struct cloogoptions *info, FILE *dst, struct clast_reduction *r)
194 int i;
195 if (r->n == 0)
196 return;
197 fprintf(dst, r->type == clast_red_max ? "MAX(" : "MIN(");
198 pprint_expr(info, dst, r->elts[0]);
199 for (i = 1; i < r->n; ++i) {
200 fprintf(dst, ",");
201 pprint_expr(info, dst, r->elts[i]);
203 fprintf(dst, ")");
206 void pprint_minmax_c(struct cloogoptions *info, FILE *dst, struct clast_reduction *r)
208 int i;
209 for (i = 1; i < r->n; ++i)
210 fprintf(dst, r->type == clast_red_max ? "max(" : "min(");
211 if (r->n > 0)
212 pprint_expr(info, dst, r->elts[0]);
213 for (i = 1; i < r->n; ++i) {
214 fprintf(dst, ",");
215 pprint_expr(info, dst, r->elts[i]);
216 fprintf(dst, ")");
220 void pprint_reduction(struct cloogoptions *i, FILE *dst, struct clast_reduction *r)
222 switch (r->type) {
223 case clast_red_sum:
224 pprint_sum(i, dst, r);
225 break;
226 case clast_red_min:
227 case clast_red_max:
228 if (r->n == 1) {
229 pprint_expr(i, dst, r->elts[0]);
230 break;
232 if (i->language == CLOOG_LANGUAGE_FORTRAN)
233 pprint_minmax_f(i, dst, r);
234 else
235 pprint_minmax_c(i, dst, r);
236 break;
237 default:
238 assert(0);
242 void pprint_expr(struct cloogoptions *i, FILE *dst, struct clast_expr *e)
244 if (!e)
245 return;
246 switch (e->type) {
247 case clast_expr_name:
248 pprint_name(dst, (struct clast_name*) e);
249 break;
250 case clast_expr_term:
251 pprint_term(i, dst, (struct clast_term*) e);
252 break;
253 case clast_expr_red:
254 pprint_reduction(i, dst, (struct clast_reduction*) e);
255 break;
256 case clast_expr_bin:
257 pprint_binary(i, dst, (struct clast_binary*) e);
258 break;
259 default:
260 assert(0);
264 void pprint_equation(struct cloogoptions *i, FILE *dst, struct clast_equation *eq)
266 pprint_expr(i, dst, eq->LHS);
267 if (eq->sign == 0)
268 fprintf(dst, " == ");
269 else if (eq->sign > 0)
270 fprintf(dst, " >= ");
271 else
272 fprintf(dst, " <= ");
273 pprint_expr(i, dst, eq->RHS);
276 void pprint_assignment(struct cloogoptions *i, FILE *dst,
277 struct clast_assignment *a)
279 if (a->LHS)
280 fprintf(dst, "%s = ", a->LHS);
281 pprint_expr(i, dst, a->RHS);
286 * pprint_osl_body function:
287 * this function pretty-prints the OpenScop body of a given statement.
288 * It returns 1 if it succeeds to find an OpenScop body to print for
289 * that statement, 0 otherwise.
290 * \param[in] options CLooG Options.
291 * \param[in] dst Output stream.
292 * \param[in] u Statement to print the OpenScop body.
293 * \return 1 on success to pretty-print an OpenScop body for u, 0 otherwise.
295 int pprint_osl_body(struct cloogoptions *options, FILE *dst,
296 struct clast_user_stmt *u) {
297 #ifdef OSL_SUPPORT
298 int i;
299 char *expr, *tmp;
300 struct clast_stmt *t;
301 osl_scop_p scop = options->scop;
302 osl_statement_p stmt;
303 osl_body_p body;
305 if ((scop != NULL) &&
306 (osl_statement_number(scop->statement) >= u->statement->number)) {
307 stmt = scop->statement;
309 /* Go to the convenient statement in the SCoP. */
310 for (i = 1; i < u->statement->number; i++)
311 stmt = stmt->next;
313 /* Ensure it has a printable body. */
314 if ((osl_generic_has_URI(stmt->body, OSL_URI_BODY)) &&
315 ((body = stmt->body->data) != NULL) &&
316 (body->expression != NULL) &&
317 (body->iterators != NULL)) {
318 expr = osl_util_identifier_substitution(body->expression->string[0],
319 body->iterators->string);
320 tmp = expr;
321 /* Print the body expression, substituting the @...@ markers. */
322 while (*expr) {
323 if (*expr == '@') {
324 int iterator;
325 expr += sscanf(expr, "@%d", &iterator) + 2; /* 2 for the @s */
326 t = u->substitutions;
327 for (i = 0; i < iterator; i++)
328 t = t->next;
329 pprint_assignment(options, dst, (struct clast_assignment *)t);
330 } else {
331 fprintf(dst, "%c", *expr++);
334 fprintf(dst, "\n");
335 free(tmp);
336 return 1;
339 #endif
340 return 0;
343 void pprint_user_stmt(struct cloogoptions *options, FILE *dst,
344 struct clast_user_stmt *u)
346 struct clast_stmt *t;
348 if (pprint_osl_body(options, dst, u))
349 return;
351 if (u->statement->name)
352 fprintf(dst, "%s", u->statement->name);
353 else
354 fprintf(dst, "S%d", u->statement->number);
355 fprintf(dst, "(");
356 for (t = u->substitutions; t; t = t->next) {
357 assert(CLAST_STMT_IS_A(t, stmt_ass));
358 pprint_assignment(options, dst, (struct clast_assignment *)t);
359 if (t->next)
360 fprintf(dst, ",");
362 fprintf(dst, ")");
363 if (options->language != CLOOG_LANGUAGE_FORTRAN)
364 fprintf(dst, ";");
365 fprintf(dst, "\n");
368 void pprint_guard(struct cloogoptions *options, FILE *dst, int indent,
369 struct clast_guard *g)
371 int k;
372 if (options->language == CLOOG_LANGUAGE_FORTRAN)
373 fprintf(dst,"IF ");
374 else
375 fprintf(dst,"if ");
376 if (g->n > 1)
377 fprintf(dst,"(");
378 for (k = 0; k < g->n; ++k) {
379 if (k > 0) {
380 if (options->language == CLOOG_LANGUAGE_FORTRAN)
381 fprintf(dst," .AND. ");
382 else
383 fprintf(dst," && ");
385 fprintf(dst,"(");
386 pprint_equation(options, dst, &g->eq[k]);
387 fprintf(dst,")");
389 if (g->n > 1)
390 fprintf(dst,")");
391 if (options->language == CLOOG_LANGUAGE_FORTRAN)
392 fprintf(dst," THEN\n");
393 else
394 fprintf(dst," {\n");
396 pprint_stmt_list(options, dst, indent + INDENT_STEP, g->then);
398 fprintf(dst, "%*s", indent, "");
399 if (options->language == CLOOG_LANGUAGE_FORTRAN)
400 fprintf(dst,"END IF\n");
401 else
402 fprintf(dst,"}\n");
405 void pprint_for(struct cloogoptions *options, FILE *dst, int indent,
406 struct clast_for *f)
408 if (options->language == CLOOG_LANGUAGE_FORTRAN)
409 fprintf(dst, "DO ");
410 else
411 fprintf(dst, "for (");
413 if (f->LB) {
414 fprintf(dst, "%s=", f->iterator);
415 pprint_expr(options, dst, f->LB);
416 } else if (options->language == CLOOG_LANGUAGE_FORTRAN)
417 cloog_die("unbounded loops not allowed in FORTRAN.\n");
419 if (options->language == CLOOG_LANGUAGE_FORTRAN)
420 fprintf(dst,", ");
421 else
422 fprintf(dst,";");
424 if (f->UB) {
425 if (options->language != CLOOG_LANGUAGE_FORTRAN)
426 fprintf(dst,"%s<=", f->iterator);
427 pprint_expr(options, dst, f->UB);
428 } else if (options->language == CLOOG_LANGUAGE_FORTRAN)
429 cloog_die("unbounded loops not allowed in FORTRAN.\n");
431 if (options->language == CLOOG_LANGUAGE_FORTRAN) {
432 if (cloog_int_gt_si(f->stride, 1))
433 cloog_int_print(dst, f->stride);
434 fprintf(dst,"\n");
436 else {
437 if (cloog_int_gt_si(f->stride, 1)) {
438 fprintf(dst,";%s+=", f->iterator);
439 cloog_int_print(dst, f->stride);
440 fprintf(dst, ") {\n");
441 } else
442 fprintf(dst, ";%s++) {\n", f->iterator);
445 pprint_stmt_list(options, dst, indent + INDENT_STEP, f->body);
447 fprintf(dst, "%*s", indent, "");
448 if (options->language == CLOOG_LANGUAGE_FORTRAN)
449 fprintf(dst,"END DO\n") ;
450 else
451 fprintf(dst,"}\n") ;
454 void pprint_stmt_list(struct cloogoptions *options, FILE *dst, int indent,
455 struct clast_stmt *s)
457 for ( ; s; s = s->next) {
458 if (CLAST_STMT_IS_A(s, stmt_root))
459 continue;
460 fprintf(dst, "%*s", indent, "");
461 if (CLAST_STMT_IS_A(s, stmt_ass)) {
462 pprint_assignment(options, dst, (struct clast_assignment *) s);
463 if (options->language != CLOOG_LANGUAGE_FORTRAN)
464 fprintf(dst, ";");
465 fprintf(dst, "\n");
466 } else if (CLAST_STMT_IS_A(s, stmt_user)) {
467 pprint_user_stmt(options, dst, (struct clast_user_stmt *) s);
468 } else if (CLAST_STMT_IS_A(s, stmt_for)) {
469 pprint_for(options, dst, indent, (struct clast_for *) s);
470 } else if (CLAST_STMT_IS_A(s, stmt_guard)) {
471 pprint_guard(options, dst, indent, (struct clast_guard *) s);
472 } else if (CLAST_STMT_IS_A(s, stmt_block)) {
473 fprintf(dst, "{\n");
474 pprint_stmt_list(options, dst, indent + INDENT_STEP,
475 ((struct clast_block *)s)->body);
476 fprintf(dst, "%*s", indent, "");
477 fprintf(dst, "}\n");
478 } else {
479 assert(0);
485 /******************************************************************************
486 * Pretty Printing (dirty) functions *
487 ******************************************************************************/
489 void clast_pprint(FILE *foo, struct clast_stmt *root,
490 int indent, CloogOptions *options)
492 pprint_stmt_list(options, foo, indent, root);