diff options
Diffstat (limited to 'source/pprint.c')
-rw-r--r-- | source/pprint.c | 407 |
1 files changed, 407 insertions, 0 deletions
diff --git a/source/pprint.c b/source/pprint.c new file mode 100644 index 0000000..66ad83e --- /dev/null +++ b/source/pprint.c @@ -0,0 +1,407 @@ + + /**-------------------------------------------------------------------** + ** CLooG ** + **-------------------------------------------------------------------** + ** pprint.c ** + **-------------------------------------------------------------------** + ** First version: october 26th 2001 ** + **-------------------------------------------------------------------**/ + + +/****************************************************************************** + * CLooG : the Chunky Loop Generator (experimental) * + ****************************************************************************** + * * + * Copyright (C) 2001-2005 Cedric Bastoul * + * * + * This is free software; you can redistribute it and/or modify it under the * + * terms of the GNU General Public License as published by the Free Software * + * Foundation; either version 2 of the License, or (at your option) any later * + * version. * + * * + * This software is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * + * for more details. * + * * + * You should have received a copy of the GNU General Public License along * + * with software; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + * * + * CLooG, the Chunky Loop Generator * + * Written by Cedric Bastoul, Cedric.Bastoul@inria.fr * + * * + ******************************************************************************/ +/* CAUTION: the english used for comments is probably the worst you ever read, + * please feel free to correct and improve it ! + */ + +/* June 22nd 2005: General adaptation for GMP. + * October 26th 2005: General adaptation from CloogDomain to CloogMatrix data + * structure for all constraint systems. + * October 27th 2005: General adaptation from CloogEqual to CloogMatrix data + * structure for equality spreading. + */ + +# include <stdlib.h> +# include <stdio.h> +# include <string.h> +#include <assert.h> +# include "../include/cloog/cloog.h" + + +/****************************************************************************** + * Types * + ******************************************************************************/ + + + +/** + * This function returns a string containing the printing of a value (possibly + * an iterator or a parameter with its coefficient or a constant). + * - val is the coefficient or constant value, + * - name is a string containing the name of the iterator or of the parameter, + */ +static void pprint_term(FILE *dst, struct clast_term *t) +{ + if (t->var) { + if (value_one_p(t->val)) + fprintf(dst, "%s", t->var); + else if (value_mone_p(t->val)) + fprintf(dst, "-%s", t->var); + else { + value_print(dst, VALUE_FMT, t->val); + fprintf(dst, "*%s", t->var); + } + } else + value_print(dst, VALUE_FMT, t->val); +} + +static void pprint_sum(FILE *dst, struct clast_reduction *r) +{ + int i; + struct clast_term *t; + + assert(r->n >= 1); + assert(r->elts[0]->type == expr_term); + t = (struct clast_term *) r->elts[0]; + pprint_term(dst, t); + + for (i = 1; i < r->n; ++i) { + assert(r->elts[i]->type == expr_term); + t = (struct clast_term *) r->elts[i]; + if (value_pos_p(t->val)) + fprintf(dst, "+"); + pprint_term(dst, t); + } +} + +static void pprint_expr(struct cloogoptions *i, FILE *dst, struct clast_expr *e); + +static void pprint_binary(struct cloogoptions *i, FILE *dst, struct clast_binary *b) +{ + const char *s1 = NULL, *s2 = NULL, *s3 = NULL; + int group = b->LHS->type == expr_red && + ((struct clast_reduction*) b->LHS)->n > 1; + if (i->language == LANGUAGE_FORTRAN) { + switch (b->type) { + case clast_bin_fdiv: + s1 = "FLOOR(REAL(", s2 = ")/REAL(", s3 = "))"; + break; + case clast_bin_cdiv: + s1 = "CEILING(REAL(", s2 = ")/REAL(", s3 = "))"; + break; + case clast_bin_div: + if (group) + s1 = "(", s2 = ")/", s3 = ""; + else + s1 = "", s2 = "/", s3 = ""; + break; + case clast_bin_mod: + s1 = "MOD(", s2 = ", ", s3 = ")"; + break; + } + } else { + switch (b->type) { + case clast_bin_fdiv: + s1 = "floord(", s2 = ",", s3 = ")"; + break; + case clast_bin_cdiv: + s1 = "ceild(", s2 = ",", s3 = ")"; + break; + case clast_bin_div: + if (group) + s1 = "(", s2 = ")/", s3 = ""; + else + s1 = "", s2 = "/", s3 = ""; + break; + case clast_bin_mod: + if (group) + s1 = "(", s2 = ")%", s3 = ""; + else + s1 = "", s2 = "%", s3 = ""; + break; + } + } + fprintf(dst, "%s", s1); + pprint_expr(i, dst, b->LHS); + fprintf(dst, "%s", s2); + value_print(dst, VALUE_FMT, b->RHS); + fprintf(dst, "%s", s3); +} + +static void pprint_minmax_f(struct cloogoptions *info, FILE *dst, struct clast_reduction *r) +{ + int i; + if (r->n == 0) + return; + fprintf(dst, r->type == clast_red_max ? "MAX(" : "MIN("); + pprint_expr(info, dst, r->elts[0]); + for (i = 1; i < r->n; ++i) { + fprintf(dst, ","); + pprint_expr(info, dst, r->elts[i]); + } + fprintf(dst, ")"); +} + +static void pprint_minmax_c(struct cloogoptions *info, FILE *dst, struct clast_reduction *r) +{ + int i; + for (i = 1; i < r->n; ++i) + fprintf(dst, r->type == clast_red_max ? "max(" : "min("); + if (r->n > 0) + pprint_expr(info, dst, r->elts[0]); + for (i = 1; i < r->n; ++i) { + fprintf(dst, ","); + pprint_expr(info, dst, r->elts[i]); + fprintf(dst, ")"); + } +} + +static void pprint_reduction(struct cloogoptions *i, FILE *dst, struct clast_reduction *r) +{ + switch (r->type) { + case clast_red_sum: + pprint_sum(dst, r); + break; + case clast_red_min: + case clast_red_max: + if (r->n == 1) { + pprint_expr(i, dst, r->elts[0]); + break; + } + if (i->language == LANGUAGE_FORTRAN) + pprint_minmax_f(i, dst, r); + else + pprint_minmax_c(i, dst, r); + break; + default: + assert(0); + } +} + +void pprint_expr(struct cloogoptions *i, FILE *dst, struct clast_expr *e) +{ + if (!e) + return; + switch (e->type) { + case expr_term: + pprint_term(dst, (struct clast_term*) e); + break; + case expr_red: + pprint_reduction(i, dst, (struct clast_reduction*) e); + break; + case expr_bin: + pprint_binary(i, dst, (struct clast_binary*) e); + break; + default: + assert(0); + } +} + +static void pprint_equation(struct cloogoptions *i, FILE *dst, struct clast_equation *eq) +{ + pprint_expr(i, dst, eq->LHS); + if (eq->sign == 0) + fprintf(dst, " == "); + else if (eq->sign > 0) + fprintf(dst, " >= "); + else + fprintf(dst, " <= "); + pprint_expr(i, dst, eq->RHS); +} + +static void pprint_assignment(struct cloogoptions *i, FILE *dst, + struct clast_assignment *a) +{ + if (a->LHS) + fprintf(dst, "%s = ", a->LHS); + pprint_expr(i, dst, a->RHS); +} + +static void pprint_user_stmt(struct cloogoptions *options, FILE *dst, + struct clast_user_stmt *u) +{ + struct clast_stmt *t; + fprintf(dst, "S%d", cloog_statement_number (u->statement)); + if (options->cpp || u->substitutions) + fprintf(dst, "("); + for (t = u->substitutions; t; t = t->next) { + assert(CLAST_STMT_IS_A(t, stmt_ass)); + pprint_assignment(options, dst, (struct clast_assignment *)t); + if (t->next) + fprintf(dst, ","); + } + if (options->cpp || u->substitutions) + fprintf(dst, ")"); + if (options->language != LANGUAGE_FORTRAN) + fprintf(dst, " ;"); + fprintf(dst, "\n"); +} + +void pprint_stmt_list(struct cloogoptions *options, FILE *dst, int indent, + struct clast_stmt *s); + +static void pprint_guard(struct cloogoptions *options, FILE *dst, int indent, + struct clast_guard *g) +{ + int k; + if (options->language == LANGUAGE_FORTRAN) + fprintf(dst,"IF "); + else + fprintf(dst,"if "); + if (g->n > 1) + fprintf(dst,"("); + for (k = 0; k < g->n; ++k) { + if (k > 0) { + if (options->language == LANGUAGE_FORTRAN) + fprintf(dst," .AND. "); + else + fprintf(dst," && "); + } + fprintf(dst,"("); + pprint_equation(options, dst, &g->eq[k]); + fprintf(dst,")"); + } + if (g->n > 1) + fprintf(dst,")"); + if (options->language == LANGUAGE_FORTRAN) + fprintf(dst," THEN\n"); + else + fprintf(dst," {\n"); + + pprint_stmt_list(options, dst, indent + INDENT_STEP, g->then); + + fprintf(dst, "%*s", indent, ""); + if (options->language == LANGUAGE_FORTRAN) + fprintf(dst,"END IF\n"); + else + fprintf(dst,"}\n"); +} + +static void pprint_for(struct cloogoptions *options, FILE *dst, int indent, + struct clast_for *f) +{ + if (options->language == LANGUAGE_FORTRAN) + fprintf(dst, "DO "); + else + fprintf(dst, "for ("); + + if (f->LB) { + fprintf(dst, "%s=", f->iterator); + pprint_expr(options, dst, f->LB); + } else if (options->language == LANGUAGE_FORTRAN) { + fprintf(stderr,"[CLooG]ERROR: unbounded loops not allowed in FORTRAN.\n"); + exit(1); + } + + if (options->language == LANGUAGE_FORTRAN) + fprintf(dst,", "); + else + fprintf(dst,";"); + + if (f->UB) { + if (options->language != LANGUAGE_FORTRAN) + fprintf(dst,"%s<=", f->iterator); + pprint_expr(options, dst, f->UB); + } else if (options->language == LANGUAGE_FORTRAN) { + fprintf(stderr,"[CLooG]ERROR: unbounded loops not allowed in FORTRAN.\n"); + exit(1); + } + + if (options->language == LANGUAGE_FORTRAN) { + if (value_gt_si(f->stride, 1)) + value_print(dst, VALUE_FMT, f->stride); + fprintf(dst,"\n"); + } + else { + if (value_gt_si(f->stride, 1)) { + fprintf(dst,";%s+=", f->iterator); + value_print(dst, VALUE_FMT") {\n", f->stride); + } else + fprintf(dst, ";%s++) {\n", f->iterator); + } + + pprint_stmt_list(options, dst, indent + INDENT_STEP, f->body); + + fprintf(dst, "%*s", indent, ""); + if (options->language == LANGUAGE_FORTRAN) + fprintf(dst,"END DO\n") ; + else + fprintf(dst,"}\n") ; +} + +void pprint_stmt_list(struct cloogoptions *options, FILE *dst, int indent, + struct clast_stmt *s) +{ + for ( ; s; s = s->next) { + if (CLAST_STMT_IS_A(s, stmt_root)) + continue; + fprintf(dst, "%*s", indent, ""); + if (CLAST_STMT_IS_A(s, stmt_ass)) { + pprint_assignment(options, dst, (struct clast_assignment *) s); + if (options->language != LANGUAGE_FORTRAN) + fprintf(dst, " ;"); + fprintf(dst, "\n"); + } else if (CLAST_STMT_IS_A(s, stmt_user)) { + pprint_user_stmt(options, dst, (struct clast_user_stmt *) s); + } else if (CLAST_STMT_IS_A(s, stmt_for)) { + pprint_for(options, dst, indent, (struct clast_for *) s); + } else if (CLAST_STMT_IS_A(s, stmt_guard)) { + pprint_guard(options, dst, indent, (struct clast_guard *) s); + } else if (CLAST_STMT_IS_A(s, stmt_block)) { + fprintf(dst, "{\n"); + pprint_stmt_list(options, dst, indent + INDENT_STEP, + ((struct clast_block *)s)->body); + fprintf(dst, "%*s", indent, ""); + fprintf(dst, "}\n"); + } else { + assert(0); + } + } +} + +/****************************************************************************** + * Memory leaks hunting * + ******************************************************************************/ + +/** + * These global variables are devoted to memory leaks hunting: we + * want to know at each moment how many Value variables have been allocated + * since in GMP mode they have to be freed (see domain.c for the declaration). + * - July 3rd->11th 2003: first version (memory leaks hunt and correction). + */ + +extern int cloog_value_allocated ; +extern int cloog_value_freed ; +extern int cloog_value_max ; + + +/****************************************************************************** + * Pretty Printing (dirty) functions * + ******************************************************************************/ + +void pprint(FILE *foo, struct clast_stmt *root, int indent, CloogOptions *options) +{ + pprint_stmt_list(options, foo, indent, root); +} |