| #include <ctype.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include "../include/cloog/cloog.h" |
| |
| #ifdef OSL_SUPPORT |
| #include <osl/strings.h> |
| #include <osl/extensions/scatnames.h> |
| #include <osl/statement.h> |
| #include <osl/scop.h> |
| #endif |
| |
| #define ALLOC(type) (type*)malloc(sizeof(type)) |
| #define ALLOCN(type,n) (type*)malloc((n)*sizeof(type)) |
| |
| void cloog_named_domain_list_free(CloogNamedDomainList *list) |
| { |
| while (list != NULL) { |
| CloogNamedDomainList *temp = list->next; |
| cloog_domain_free(list->domain); |
| cloog_scattering_free(list->scattering); |
| free(list->name); |
| free(list); |
| list = temp; |
| } |
| } |
| |
| CloogUnionDomain *cloog_union_domain_alloc(int nb_par) |
| { |
| CloogUnionDomain *ud; |
| |
| ud = ALLOC(CloogUnionDomain); |
| if (!ud) |
| cloog_die("memory overflow.\n"); |
| |
| ud->domain = NULL; |
| ud->next_domain = &ud->domain; |
| |
| ud->n_name[CLOOG_PARAM] = nb_par; |
| ud->n_name[CLOOG_ITER] = 0; |
| ud->n_name[CLOOG_SCAT] = 0; |
| |
| ud->name[CLOOG_PARAM] = NULL; |
| ud->name[CLOOG_ITER] = NULL; |
| ud->name[CLOOG_SCAT] = NULL; |
| |
| return ud; |
| } |
| |
| void cloog_union_domain_free(CloogUnionDomain *ud) |
| { |
| int i; |
| int j; |
| |
| if (!ud) |
| return; |
| |
| for (i = 0; i < 3; ++i) { |
| if (!ud->name[i]) |
| continue; |
| for (j = 0; j < ud->n_name[i]; ++i) |
| free(ud->name[i][j]); |
| free(ud->name[i]); |
| } |
| |
| cloog_named_domain_list_free(ud->domain); |
| |
| free(ud); |
| } |
| |
| /** |
| * Add a domain with scattering function to the union of domains. |
| * name may be NULL and is duplicated if it is not. |
| * domain and scattering are taken over by the CloogUnionDomain. |
| * scattering may be NULL. |
| */ |
| CloogUnionDomain *cloog_union_domain_add_domain(CloogUnionDomain *ud, |
| const char *name, CloogDomain *domain, CloogScattering *scattering, |
| void *usr) |
| { |
| CloogNamedDomainList *named; |
| int n; |
| |
| if (!ud) |
| return NULL; |
| |
| named = ALLOC(CloogNamedDomainList); |
| if (!named) |
| cloog_die("memory overflow.\n"); |
| |
| if (ud->name[CLOOG_ITER]) |
| cloog_die("iterator names must be set after adding domains.\n"); |
| if (ud->name[CLOOG_SCAT]) |
| cloog_die("scattering names must be set after adding domains.\n"); |
| |
| n = cloog_domain_dimension(domain); |
| if (n > ud->n_name[CLOOG_ITER]) |
| ud->n_name[CLOOG_ITER] = n; |
| |
| if (scattering) { |
| n = cloog_scattering_dimension(scattering, domain); |
| if (n > ud->n_name[CLOOG_SCAT]) |
| ud->n_name[CLOOG_SCAT] = n; |
| } |
| |
| named->domain = domain; |
| named->scattering = scattering; |
| named->name = name ? strdup(name) : NULL; |
| named->usr = usr; |
| named->next = NULL; |
| |
| *ud->next_domain = named; |
| ud->next_domain = &named->next; |
| |
| return ud; |
| } |
| |
| /** |
| * Set the name of parameter, iterator or scattering dimension |
| * at the specified position. The name is duplicated. |
| */ |
| CloogUnionDomain *cloog_union_domain_set_name(CloogUnionDomain *ud, |
| enum cloog_dim_type type, int index, const char *name) |
| { |
| int i; |
| |
| if (!ud) |
| return ud; |
| |
| if (type != CLOOG_PARAM && |
| type != CLOOG_ITER && |
| type != CLOOG_SCAT) |
| cloog_die("invalid dim type\n"); |
| |
| if (index < 0 || index >= ud->n_name[type]) |
| cloog_die("index out of range\n"); |
| |
| if (!ud->name[type]) { |
| ud->name[type] = ALLOCN(char *, ud->n_name[type]); |
| if (!ud->name[type]) |
| cloog_die("memory overflow.\n"); |
| for (i = 0; i < ud->n_name[type]; ++i) |
| ud->name[type][i] = NULL; |
| } |
| |
| free(ud->name[type][index]); |
| ud->name[type][index] = strdup(name); |
| if (!ud->name[type][index]) |
| cloog_die("memory overflow.\n"); |
| |
| return ud; |
| } |
| |
| static char *next_line(FILE *input, char *line, unsigned len) |
| { |
| char *p; |
| |
| do { |
| if (!(p = fgets(line, len, input))) |
| return NULL; |
| while (isspace(*p) && *p != '\n') |
| ++p; |
| } while (*p == '#' || *p == '\n'); |
| |
| return p; |
| } |
| |
| /** |
| * cloog_scattering_list_read |
| * Read in a list of scattering functions for the nb_statements |
| * domains in loop. |
| */ |
| static CloogScatteringList *cloog_scattering_list_read(FILE * foo, |
| CloogDomain **domain, int nb_statements, int nb_parameters) |
| { |
| int nb_scat = 0; |
| char s[MAX_STRING]; |
| CloogScatteringList *list = NULL, **next = &list; |
| |
| /* We read first the number of scattering functions in the list. */ |
| do { |
| if (!fgets(s, MAX_STRING, foo)) |
| break; |
| } while ((*s=='#' || *s=='\n') || (sscanf(s, " %d", &nb_scat) < 1)); |
| |
| if (nb_scat == 0) |
| return NULL; |
| |
| if (nb_scat != nb_statements) |
| cloog_die("wrong number of scattering functions.\n"); |
| |
| while (nb_scat--) { |
| *next = (CloogScatteringList *)malloc(sizeof(CloogScatteringList)); |
| (*next)->scatt = cloog_domain_read_scattering(*domain, foo); |
| (*next)->next = NULL; |
| |
| next = &(*next)->next; |
| domain++; |
| } |
| return list; |
| } |
| |
| static CloogUnionDomain *set_names_from_list(CloogUnionDomain *ud, |
| enum cloog_dim_type type, int n, char **names) |
| { |
| int i; |
| |
| if (!names) |
| return ud; |
| |
| for (i = 0; i < n; ++i) { |
| ud = cloog_union_domain_set_name(ud, type, i, names[i]); |
| free(names[i]); |
| } |
| free(names); |
| |
| return ud; |
| } |
| |
| /** |
| * Fill up a CloogUnionDomain from information in a CLooG input file. |
| * The language and the context are assumed to have been read from |
| * the input file already. |
| */ |
| CloogUnionDomain *cloog_union_domain_read(FILE *file, int nb_par, |
| CloogOptions *options) |
| { |
| int op1, op2, op3; |
| char line[MAX_STRING]; |
| CloogDomain **domain; |
| CloogUnionDomain *ud; |
| CloogScatteringList *scatteringl; |
| int i; |
| int n_iter = -1; |
| int n_dom; |
| char **names; |
| |
| ud = cloog_union_domain_alloc(nb_par); |
| |
| names = cloog_names_read_strings(file, nb_par); |
| ud = set_names_from_list(ud, CLOOG_PARAM, nb_par, names); |
| |
| /* We read the number of statements. */ |
| if (!next_line(file, line, sizeof(line))) |
| cloog_die("Input error.\n"); |
| if (sscanf(line, "%d", &n_dom) != 1) |
| cloog_die("Input error.\n"); |
| |
| domain = ALLOCN(CloogDomain *, n_dom); |
| if (!domain) |
| cloog_die("memory overflow.\n"); |
| |
| for (i = 0; i < n_dom; ++i) { |
| int dim; |
| |
| domain[i] = cloog_domain_union_read(options->state, file, |
| nb_par); |
| dim = cloog_domain_dimension(domain[i]); |
| if (dim > n_iter) |
| n_iter = dim; |
| |
| /* To read that stupid "0 0 0" line. */ |
| if (!next_line(file, line, sizeof(line))) |
| cloog_die("Input error.\n"); |
| if (sscanf(line, " %d %d %d", &op1, &op2, &op3) != 3) |
| cloog_die("Input error.\n"); |
| } |
| |
| /* Reading of the iterator names. */ |
| names = cloog_names_read_strings(file, n_iter); |
| |
| /* Reading and putting the scattering data in program structure. */ |
| scatteringl = cloog_scattering_list_read(file, domain, n_dom, nb_par); |
| |
| if (scatteringl) { |
| CloogScatteringList *is, *next; |
| |
| if (cloog_scattering_list_lazy_same(scatteringl)) |
| cloog_msg(options, CLOOG_WARNING, |
| "some scattering functions are similar.\n"); |
| |
| for (i = 0, is = scatteringl; i < n_dom; ++i, is = next) { |
| next = is->next; |
| ud = cloog_union_domain_add_domain(ud, NULL, domain[i], |
| is->scatt, NULL); |
| free(is); |
| } |
| } else { |
| for (i = 0; i < n_dom; ++i) |
| ud = cloog_union_domain_add_domain(ud, NULL, domain[i], |
| NULL, NULL); |
| } |
| |
| ud = set_names_from_list(ud, CLOOG_ITER, n_iter, names); |
| |
| if (scatteringl) { |
| int n_scat = ud->n_name[CLOOG_SCAT]; |
| names = cloog_names_read_strings(file, n_scat); |
| ud = set_names_from_list(ud, CLOOG_SCAT, n_scat, names); |
| } |
| |
| free(domain); |
| |
| return ud; |
| } |
| |
| |
| #ifdef OSL_SUPPORT |
| /** |
| * Extracts a CloogUnionDomain from an openscop scop (the CloogUnionDomain |
| * corresponds more or less to the openscop statement). |
| * \param[in,out] state CLooG state. |
| * \param[in] scop OpenScop scop to convert. |
| * \return A new CloogUnionDomain corresponding the input OpenScop scop. |
| */ |
| CloogUnionDomain *cloog_union_domain_from_osl_scop(CloogState *state, |
| osl_scop_p scop) { |
| int i, nb_parameters; |
| CloogDomain *domain = NULL; |
| CloogScattering *scattering = NULL; |
| CloogUnionDomain *ud = NULL; |
| osl_scop_p normalized; |
| osl_statement_p statement; |
| osl_scatnames_p scatnames; |
| |
| /* Set the union of domains. */ |
| nb_parameters = (scop->context == NULL) ? 0 : scop->context->nb_parameters; |
| ud = cloog_union_domain_alloc(nb_parameters); |
| |
| /* - Set the parameter names. */ |
| if (osl_generic_has_URI(scop->parameters, OSL_URI_STRINGS)) { |
| for (i = 0; i < osl_strings_size(scop->parameters->data); i++) { |
| ud = cloog_union_domain_set_name(ud, CLOOG_PARAM, i, |
| ((osl_strings_p)(scop->parameters->data))->string[i]); |
| } |
| } |
| |
| /* - Set each statement (domain/scattering). |
| * Since CLooG requires all number of scattering dimensions to be |
| * equal, we normalize them first. |
| */ |
| normalized = osl_scop_clone(scop); |
| osl_scop_normalize_scattering(normalized); |
| statement = normalized->statement; |
| while(statement != NULL) { |
| domain = cloog_domain_from_osl_relation(state, statement->domain); |
| scattering = cloog_scattering_from_osl_relation(state, |
| statement->scattering); |
| ud = cloog_union_domain_add_domain(ud, NULL, domain, scattering, NULL); |
| statement = statement->next; |
| } |
| osl_scop_free(normalized); |
| |
| /* - Set the scattering dimension names. */ |
| scatnames = osl_generic_lookup(scop->extension, OSL_URI_SCATNAMES); |
| if ((scatnames != NULL) && (scatnames->names != NULL)) { |
| for (i = 0; (i < osl_strings_size(scatnames->names)) && |
| (i < ud->n_name[CLOOG_SCAT]); i++) { |
| ud = cloog_union_domain_set_name(ud, CLOOG_SCAT, i, |
| scatnames->names->string[i]); |
| } |
| } |
| |
| return ud; |
| } |
| #endif |