1#include <ctype.h>
2#include <stdio.h>
3#include <stdlib.h>
4#include "../include/cloog/cloog.h"
5
6#ifdef OSL_SUPPORT
7#include <osl/strings.h>
8#include <osl/extensions/scatnames.h>
9#include <osl/statement.h>
10#include <osl/scop.h>
11#endif
12
13#define ALLOC(type) (type*)malloc(sizeof(type))
14#define ALLOCN(type,n) (type*)malloc((n)*sizeof(type))
15
16void cloog_named_domain_list_free(CloogNamedDomainList *list)
17{
18	while (list != NULL) {
19		CloogNamedDomainList *temp = list->next;
20		cloog_domain_free(list->domain);
21		cloog_scattering_free(list->scattering);
22		free(list->name);
23		free(list);
24		list = temp;
25	}
26}
27
28CloogUnionDomain *cloog_union_domain_alloc(int nb_par)
29{
30	CloogUnionDomain *ud;
31
32	ud = ALLOC(CloogUnionDomain);
33	if (!ud)
34		cloog_die("memory overflow.\n");
35
36	ud->domain = NULL;
37	ud->next_domain = &ud->domain;
38
39	ud->n_name[CLOOG_PARAM] = nb_par;
40	ud->n_name[CLOOG_ITER] = 0;
41	ud->n_name[CLOOG_SCAT] = 0;
42
43	ud->name[CLOOG_PARAM] = NULL;
44	ud->name[CLOOG_ITER] = NULL;
45	ud->name[CLOOG_SCAT] = NULL;
46
47	return ud;
48}
49
50void cloog_union_domain_free(CloogUnionDomain *ud)
51{
52	int i;
53	int j;
54
55	if (!ud)
56		return;
57
58	for (i = 0; i < 3; ++i) {
59		if (!ud->name[i])
60			continue;
61		for (j = 0; j < ud->n_name[i]; ++j)
62			free(ud->name[i][j]);
63		free(ud->name[i]);
64	}
65
66	cloog_named_domain_list_free(ud->domain);
67
68	free(ud);
69}
70
71/**
72 * Add a domain with scattering function to the union of domains.
73 * name may be NULL and is duplicated if it is not.
74 * domain and scattering are taken over by the CloogUnionDomain.
75 * scattering may be NULL.
76 */
77CloogUnionDomain *cloog_union_domain_add_domain(CloogUnionDomain *ud,
78	const char *name, CloogDomain *domain, CloogScattering *scattering,
79	void *usr)
80{
81	CloogNamedDomainList *named;
82	int n;
83
84	if (!ud)
85		return NULL;
86
87	named = ALLOC(CloogNamedDomainList);
88	if (!named)
89		cloog_die("memory overflow.\n");
90
91	if (ud->name[CLOOG_ITER])
92		cloog_die("iterator names must be set after adding domains.\n");
93	if (ud->name[CLOOG_SCAT])
94		cloog_die("scattering names must be set after adding domains.\n");
95
96	n = cloog_domain_dimension(domain);
97	if (n > ud->n_name[CLOOG_ITER])
98		ud->n_name[CLOOG_ITER] = n;
99
100	if (scattering) {
101		n = cloog_scattering_dimension(scattering, domain);
102		if (n > ud->n_name[CLOOG_SCAT])
103			ud->n_name[CLOOG_SCAT] = n;
104	}
105
106	named->domain = domain;
107	named->scattering = scattering;
108	named->name = name ? strdup(name) : NULL;
109	named->usr = usr;
110	named->next = NULL;
111
112	*ud->next_domain = named;
113	ud->next_domain = &named->next;
114
115	return ud;
116}
117
118/**
119 * Set the name of parameter, iterator or scattering dimension
120 * at the specified position.  The name is duplicated.
121 */
122CloogUnionDomain *cloog_union_domain_set_name(CloogUnionDomain *ud,
123	enum cloog_dim_type type, int index, const char *name)
124{
125	int i;
126
127	if (!ud)
128		return ud;
129
130	if (type != CLOOG_PARAM &&
131	    type != CLOOG_ITER &&
132	    type != CLOOG_SCAT)
133		cloog_die("invalid dim type\n");
134
135	if (index < 0 || index >= ud->n_name[type])
136		cloog_die("index out of range\n");
137
138	if (!ud->name[type]) {
139		ud->name[type] = ALLOCN(char *, ud->n_name[type]);
140		if (!ud->name[type])
141			cloog_die("memory overflow.\n");
142		for (i = 0; i < ud->n_name[type]; ++i)
143			ud->name[type][i] = NULL;
144	}
145
146	free(ud->name[type][index]);
147	ud->name[type][index] = strdup(name);
148	if (!ud->name[type][index])
149		cloog_die("memory overflow.\n");
150
151	return ud;
152}
153
154static char *next_line(FILE *input, char *line, unsigned len)
155{
156	char *p;
157
158	do {
159		if (!(p = fgets(line, len, input)))
160			return NULL;
161		while (isspace(*p) && *p != '\n')
162			++p;
163	} while (*p == '#' || *p == '\n');
164
165	return p;
166}
167
168/**
169 * cloog_scattering_list_read
170 * Read in a list of scattering functions for the nb_statements
171 * domains in loop.
172 */
173static CloogScatteringList *cloog_scattering_list_read(FILE * foo,
174	CloogDomain **domain, int nb_statements, int nb_parameters)
175{
176    int nb_scat = 0;
177    char s[MAX_STRING];
178    CloogScatteringList *list = NULL, **next = &list;
179
180    /* We read first the number of scattering functions in the list. */
181    do {
182	if (!fgets(s, MAX_STRING, foo))
183	    break;
184    } while ((*s=='#' || *s=='\n') || (sscanf(s, " %d", &nb_scat) < 1));
185
186    if (nb_scat == 0)
187	return NULL;
188
189    if (nb_scat != nb_statements)
190	cloog_die("wrong number of scattering functions.\n");
191
192    while (nb_scat--) {
193	*next = (CloogScatteringList *)malloc(sizeof(CloogScatteringList));
194	(*next)->scatt = cloog_domain_read_scattering(*domain, foo);
195	(*next)->next = NULL;
196
197	next = &(*next)->next;
198	domain++;
199    }
200    return list;
201}
202
203static CloogUnionDomain *set_names_from_list(CloogUnionDomain *ud,
204	enum cloog_dim_type type, int n, char **names)
205{
206	int i;
207
208	if (!names)
209		return ud;
210
211	for (i = 0; i < n; ++i) {
212		ud = cloog_union_domain_set_name(ud, type, i, names[i]);
213		free(names[i]);
214	}
215	free(names);
216
217	return ud;
218}
219
220/**
221 * Fill up a CloogUnionDomain from information in a CLooG input file.
222 * The language and the context are assumed to have been read from
223 * the input file already.
224 */
225CloogUnionDomain *cloog_union_domain_read(FILE *file, int nb_par,
226	CloogOptions *options)
227{
228	int op1, op2, op3;
229	char line[MAX_STRING];
230	CloogDomain **domain;
231	CloogUnionDomain *ud;
232	CloogScatteringList *scatteringl;
233	int i;
234	int n_iter = -1;
235	int n_dom;
236	char **names;
237
238	ud = cloog_union_domain_alloc(nb_par);
239
240	names = cloog_names_read_strings(file, nb_par);
241	ud = set_names_from_list(ud, CLOOG_PARAM, nb_par, names);
242
243	/* We read the number of statements. */
244	if (!next_line(file, line, sizeof(line)))
245		cloog_die("Input error.\n");
246	if (sscanf(line, "%d", &n_dom) != 1)
247		cloog_die("Input error.\n");
248
249	domain = ALLOCN(CloogDomain *, n_dom);
250	if (!domain)
251		cloog_die("memory overflow.\n");
252
253	for (i = 0; i < n_dom; ++i) {
254		int dim;
255
256		domain[i] = cloog_domain_union_read(options->state, file,
257						    nb_par);
258		dim = cloog_domain_dimension(domain[i]);
259		if (dim > n_iter)
260			n_iter = dim;
261
262		/* To read that stupid "0 0 0" line. */
263		if (!next_line(file, line, sizeof(line)))
264			cloog_die("Input error.\n");
265		if (sscanf(line, " %d %d %d", &op1, &op2, &op3) != 3)
266			cloog_die("Input error.\n");
267	}
268
269	/* Reading of the iterator names. */
270	names = cloog_names_read_strings(file, n_iter);
271
272	/* Reading and putting the scattering data in program structure. */
273	scatteringl = cloog_scattering_list_read(file, domain, n_dom, nb_par);
274
275	if (scatteringl) {
276		CloogScatteringList *is, *next;
277
278		if (cloog_scattering_list_lazy_same(scatteringl))
279			cloog_msg(options, CLOOG_WARNING,
280				  "some scattering functions are similar.\n");
281
282		for (i = 0, is = scatteringl; i < n_dom; ++i, is = next) {
283			next = is->next;
284			ud = cloog_union_domain_add_domain(ud, NULL, domain[i],
285							      is->scatt, NULL);
286			free(is);
287		}
288	} else {
289		for (i = 0; i < n_dom; ++i)
290			ud = cloog_union_domain_add_domain(ud, NULL, domain[i],
291								NULL, NULL);
292	}
293
294	ud = set_names_from_list(ud, CLOOG_ITER, n_iter, names);
295
296	if (scatteringl) {
297		int n_scat = ud->n_name[CLOOG_SCAT];
298		names = cloog_names_read_strings(file, n_scat);
299		ud = set_names_from_list(ud, CLOOG_SCAT, n_scat, names);
300	}
301
302	free(domain);
303
304	return ud;
305}
306
307
308#ifdef OSL_SUPPORT
309/**
310 * Extracts a CloogUnionDomain from an openscop scop (the CloogUnionDomain
311 * corresponds more or less to the openscop statement).
312 * \param[in,out] state CLooG state.
313 * \param[in]     scop  OpenScop scop to convert.
314 * \return A new CloogUnionDomain corresponding the input OpenScop scop.
315 */
316CloogUnionDomain *cloog_union_domain_from_osl_scop(CloogState *state,
317                                                   osl_scop_p scop) {
318  int i, nb_parameters;
319  CloogDomain *domain = NULL;
320  CloogScattering *scattering = NULL;
321  CloogUnionDomain *ud = NULL;
322  osl_scop_p normalized;
323  osl_statement_p statement;
324  osl_scatnames_p scatnames;
325
326  /* Set the union of domains. */
327  nb_parameters = (scop->context == NULL) ? 0 : scop->context->nb_parameters;
328  ud = cloog_union_domain_alloc(nb_parameters);
329
330  /* - Set the parameter names. */
331  if (osl_generic_has_URI(scop->parameters, OSL_URI_STRINGS)) {
332    for (i = 0; i < osl_strings_size(scop->parameters->data); i++) {
333      ud = cloog_union_domain_set_name(ud, CLOOG_PARAM, i,
334        ((osl_strings_p)(scop->parameters->data))->string[i]);
335    }
336  }
337
338  /* - Set each statement (domain/scattering).
339   *   Since CLooG requires all number of scattering dimensions to be
340   *   equal, we normalize them first.
341   */
342  normalized = osl_scop_clone(scop);
343  osl_scop_normalize_scattering(normalized);
344  statement = normalized->statement;
345  while(statement != NULL) {
346    domain = cloog_domain_from_osl_relation(state, statement->domain);
347    scattering = cloog_scattering_from_osl_relation(state,
348                                                    statement->scattering);
349    ud = cloog_union_domain_add_domain(ud, NULL, domain, scattering, NULL);
350    statement = statement->next;
351  }
352  osl_scop_free(normalized);
353
354  /* - Set the scattering dimension names. */
355  scatnames = osl_generic_lookup(scop->extension, OSL_URI_SCATNAMES);
356  if ((scatnames != NULL) && (scatnames->names != NULL)) {
357    for (i = 0; (i < osl_strings_size(scatnames->names)) &&
358                (i < ud->n_name[CLOOG_SCAT]); i++) {
359      ud = cloog_union_domain_set_name(ud, CLOOG_SCAT, i,
360                                       scatnames->names->string[i]);
361    }
362  }
363
364  return ud;
365}
366#endif
367