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 
cloog_named_domain_list_free(CloogNamedDomainList * list)16 void 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 
cloog_union_domain_alloc(int nb_par)28 CloogUnionDomain *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 
cloog_union_domain_free(CloogUnionDomain * ud)50 void 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  */
cloog_union_domain_add_domain(CloogUnionDomain * ud,const char * name,CloogDomain * domain,CloogScattering * scattering,void * usr)77 CloogUnionDomain *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  */
cloog_union_domain_set_name(CloogUnionDomain * ud,enum cloog_dim_type type,int index,const char * name)122 CloogUnionDomain *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 
next_line(FILE * input,char * line,unsigned len)154 static 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  */
cloog_scattering_list_read(FILE * foo,CloogDomain ** domain,int nb_statements,int nb_parameters)173 static 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 
set_names_from_list(CloogUnionDomain * ud,enum cloog_dim_type type,int n,char ** names)203 static 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  */
cloog_union_domain_read(FILE * file,int nb_par,CloogOptions * options)225 CloogUnionDomain *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  */
cloog_union_domain_from_osl_scop(CloogState * state,osl_scop_p scop)316 CloogUnionDomain *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