Clan  0.8.1
symbol.c
Go to the documentation of this file.
1 
2  /*+------- <| --------------------------------------------------------**
3  ** A Clan **
4  **--- /.\ -----------------------------------------------------**
5  ** <| [""M# symbol.c **
6  **- A | # -----------------------------------------------------**
7  ** /.\ [""M# First version: 01/05/2008 **
8  **- [""M# | # U"U#U -----------------------------------------------**
9  | # | # \ .:/
10  | # | #___| #
11  ****** | "--' .-" ******************************************************
12  * |"-"-"-"-"-#-#-## Clan : the Chunky Loop Analyzer (experimental) *
13  **** | # ## ###### *****************************************************
14  * \ .::::'/ *
15  * \ ::::'/ Copyright (C) 2008 University Paris-Sud 11 *
16  * :8a| # # ## *
17  * ::88a ### This is free software; you can redistribute it *
18  * ::::888a 8a ##::. and/or modify it under the terms of the GNU Lesser *
19  * ::::::::888a88a[]::: General Public License as published by the Free *
20  *::8:::::::::SUNDOGa8a::. Software Foundation, either version 2.1 of the *
21  *::::::::8::::888:Y8888:: License, or (at your option) any later version. *
22  *::::':::88::::888::Y88a::::::::::::... *
23  *::'::.. . ..... .. ... . *
24  * This software is distributed in the hope that it will be useful, but *
25  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
26  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
27  * for more details. *
28  * *
29  * You should have received a copy of the GNU Lesser General Public License *
30  * along with software; if not, write to the Free Software Foundation, Inc., *
31  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
32  * *
33  * Clan, the Chunky Loop Analyzer *
34  * Written by Cedric Bastoul, Cedric.Bastoul@u-psud.fr *
35  * *
36  ******************************************************************************/
37 
38 
39 #include <stdlib.h>
40 #include <stdio.h>
41 #include <ctype.h>
42 #include <string.h>
43 
44 #include <osl/macros.h>
45 #include <osl/strings.h>
46 #include <osl/generic.h>
47 #include <osl/relation.h>
48 #include <osl/relation_list.h>
49 #include <osl/extensions/arrays.h>
50 #include <clan/macros.h>
51 #include <clan/symbol.h>
52 
53 
54 void yyerror(char*);
55 
56 
57 /*+****************************************************************************
58  * Structure display function *
59  ******************************************************************************/
60 
61 
73 void clan_symbol_print_structure(FILE* file, clan_symbol_p symbol, int level) {
74  int i, j, first = 1, number = 1;
75 
76  if (symbol != NULL) {
77  // Go to the right level.
78  for(j = 0; j < level; j++)
79  fprintf(file, "|\t");
80  fprintf(file, "+-- clan_symbol_t (node %d)\n", number);
81  } else {
82  // Go to the right level.
83  for(j = 0; j < level; j++)
84  fprintf(file, "|\t");
85  fprintf(file, "+-- NULL symbol\n");
86  }
87 
88  while (symbol != NULL) {
89  if (!first) {
90  // Go to the right level.
91  for (j = 0; j < level; j++)
92  fprintf(file, "|\t");
93  fprintf(file, "| clan_symbol_t (node %d)\n", number);
94  } else {
95  first = 0;
96  }
97 
98  // A blank line.
99  for (j = 0; j <= level + 1; j++)
100  fprintf(file, "|\t");
101  fprintf(file, "\n");
102 
103  // Go to the right level and print the key.
104  for (j = 0; j <= level; j++)
105  fprintf(file, "|\t");
106  fprintf(file, "Key: %d\n", symbol->key);
107 
108  // A blank line.
109  for (j = 0; j <= level+1; j++)
110  fprintf(file, "|\t");
111  fprintf(file, "\n");
112 
113  // Print the identifier.
114  for (i = 0; i <= level; i++)
115  fprintf(file, "|\t");
116  if (symbol->identifier != NULL)
117  fprintf(file, "+-- Identifier: %s\n", symbol->identifier);
118  else
119  fprintf(file, "+-- No identifier\n");
120 
121  // A blank line.
122  for(j = 0; j <= level + 1; j++)
123  fprintf(file, "|\t") ;
124  fprintf(file, "\n") ;
125 
126  // Go to the right level and print the type.
127  for (j = 0; j <= level; j++)
128  fprintf(file, "|\t") ;
129  fprintf(file, "Type: ") ;
130  switch (symbol->type) {
131  case CLAN_TYPE_ITERATOR : fprintf(file, "Iterator\n"); break;
132  case CLAN_TYPE_PARAMETER: fprintf(file, "Parameter\n"); break;
133  case CLAN_TYPE_ARRAY : fprintf(file, "Array\n"); break;
134  case CLAN_TYPE_FUNCTION : fprintf(file, "Function\n"); break;
135  default : fprintf(file, "Unknown\n") ;
136  }
137 
138  // A blank line.
139  for (j = 0; j <= level + 1; j++)
140  fprintf(file, "|\t");
141  fprintf(file, "\n");
142 
143  // Go to the right level and print the rank.
144  for (j = 0; j <= level; j++)
145  fprintf(file, "|\t");
146  fprintf(file, "Rank: %d\n", symbol->rank);
147 
148  // A blank line.
149  for (j = 0; j <= level + 1; j++)
150  fprintf(file, "|\t");
151  fprintf(file, "\n");
152 
153  symbol = symbol->next;
154  number++;
155 
156  // Next line.
157  if (symbol != NULL) {
158  for (j = 0; j <= level; j++)
159  fprintf(file, "|\t");
160  fprintf(file, "V\n");
161  }
162  }
163 
164  // The last line.
165  for(j = 0; j <= level; j++)
166  fprintf(file, "|\t");
167  fprintf(file, "\n");
168 }
169 
170 
178 void clan_symbol_print(FILE* file, clan_symbol_p symbol) {
179  clan_symbol_print_structure(file, symbol, 0);
180 }
181 
182 
183 /*+****************************************************************************
184  * Memory allocation/deallocation function *
185  ******************************************************************************/
186 
187 
196  clan_symbol_p symbol;
197 
198  CLAN_malloc(symbol, clan_symbol_p, sizeof(clan_symbol_t));
199  symbol->key = CLAN_UNDEFINED;
200  symbol->identifier = NULL;
201  symbol->type = CLAN_UNDEFINED;
202  symbol->rank = CLAN_UNDEFINED;
203  symbol->next = NULL;
204 
205  return symbol;
206 }
207 
208 
215  clan_symbol_p next;
216 
217  while (symbol != NULL) {
218  next = symbol->next;
219  free(symbol->identifier);
220  free(symbol);
221  symbol = next;
222  }
223 }
224 
225 
226 /*+****************************************************************************
227  * Processing functions *
228  ******************************************************************************/
229 
230 
240 clan_symbol_p clan_symbol_lookup(clan_symbol_p symbol, char* identifier) {
241  while (symbol != NULL) {
242  if (strcmp(symbol->identifier, identifier) == 0)
243  return symbol;
244  else
245  symbol = symbol->next;
246  }
247  return NULL;
248 }
249 
250 
261  while (symbol != NULL) {
262  if (symbol->key == key)
263  return symbol;
264  else
265  symbol = symbol->next;
266  }
267  return NULL;
268 }
269 
270 
277 static
279  int key = CLAN_KEY_START;
280 
281  while (table != NULL) {
282  if (table->key >= key)
283  key = table->key + 1;
284  table = table->next;
285  }
286  return key;
287 }
288 
289 
299  clan_symbol_p tmp = *table;
300 
301  // We put the symbol at the end of the table.
302  if (*table == NULL) {
303  *table = symbol;
304  } else {
305  while (tmp->next != NULL)
306  tmp = tmp->next;
307  tmp->next = symbol;
308  }
309 }
310 
311 
323 clan_symbol_p clan_symbol_add(clan_symbol_p* table, char* identifier,
324  int type) {
325  clan_symbol_p symbol;
326 
327  // If the identifier is already in the table, do nothing.
328  symbol = clan_symbol_lookup(*table, identifier);
329  if (symbol != NULL)
330  return symbol;
331 
332  // Else, we allocate and fill a new clan_symbol_t node.
333  symbol = clan_symbol_malloc();
334  symbol->key = clan_symbol_generate_new_key(*table);
335  symbol->identifier = strdup(identifier);
336  symbol->type = type;
337 
338  // We put the new symbol at the end of the table.
339  clan_symbol_push_at_end(table, symbol);
340 
341  return symbol;
342 }
343 
344 
354 int clan_symbol_get_key(clan_symbol_p symbol, char* identifier) {
355  while (symbol != NULL) {
356  if (strcmp(symbol->identifier,identifier) == 0)
357  return symbol->key;
358  else
359  symbol = symbol->next;
360  }
361  return CLAN_UNDEFINED;
362 }
363 
364 
374 int clan_symbol_get_rank(clan_symbol_p symbol, char* identifier) {
375  while (symbol != NULL) {
376  if (strcmp(symbol->identifier,identifier) == 0)
377  return symbol->rank;
378  else
379  symbol = symbol->next;
380  }
381  return CLAN_UNDEFINED;
382 }
383 
384 
394 int clan_symbol_get_type(clan_symbol_p symbol, char* identifier) {
395  while (symbol != NULL) {
396  if (strcmp(symbol->identifier,identifier) == 0)
397  return symbol->type;
398  else
399  symbol = symbol->next;
400  }
401  return CLAN_UNDEFINED;
402 }
403 
404 
417 osl_strings_p clan_symbol_array_to_strings(clan_symbol_p* sarray, int size,
418  int* depths, int* labels) {
419  int i, j, xfor_index = 0, xfor_index_reuse = 0;
420  clan_symbol_p symbol;
421  osl_strings_p strings = osl_strings_malloc();
422 
423  // Fill the array of strings.
424  for (i = 0; i < size; i++) {
425  symbol = sarray[i];
426  // If symbol has a non-NULL next field, it means it corresponds to
427  // an xfor index that we have to select conveniently:
428  if (symbol->next != NULL) {
429  // -1. Select the convenient symbol thanks to the xfor label.
430  for (j = 0; j < labels[xfor_index]; j++)
431  symbol = symbol->next;
432 
433  // -2. Increment the number of times we used that symbol.
434  xfor_index_reuse++;
435 
436  // -3. If we reached the current xfor depth, the next xfor index
437  // will be found in the next xfor loop nest.
438  if (xfor_index_reuse >= depths[xfor_index]) {
439  xfor_index++;
440  xfor_index_reuse = 0;
441  }
442  }
443  osl_strings_add(strings, symbol->identifier);
444  }
445 
446  return strings;
447 }
448 
449 
458 int clan_symbol_nb_of_type(clan_symbol_p symbol, int type) {
459  int nb = 0;
460 
461  while (symbol != NULL) {
462  if (symbol->type == type)
463  nb++;
464  symbol = symbol->next;
465  }
466 
467  return nb;
468 }
469 
470 
483 osl_generic_p clan_symbol_to_strings(clan_symbol_p symbol, int type) {
484  osl_strings_p strings = NULL;
485  osl_generic_p generic;
486 
487  if (clan_symbol_nb_of_type(symbol, type) == 0)
488  return NULL;
489 
490  // We scan the table a second time to fill the identifier array
491  // Not optimal to act this way but overkills are worse!
492  strings = osl_strings_malloc();
493  while (symbol != NULL) {
494  if (symbol->type == type) {
495  osl_strings_add(strings, symbol->identifier);
496  }
497  symbol = symbol->next;
498  }
499 
500  // Embed the strings in a generic shell.
501  generic = osl_generic_shell(strings, osl_strings_interface());
502  return generic;
503 }
504 
505 
515 
516  if (symbol->identifier != NULL)
517  clone->identifier = strdup(symbol->identifier);
518  clone->type = symbol->type;
519  clone->rank = symbol->rank;
520 
521  return clone;
522 }
523 
524 
533 osl_generic_p clan_symbol_to_arrays(clan_symbol_p symbol) {
534  int i;
535  int nb_arrays = 0;
536  osl_arrays_p arrays = NULL;
537  osl_generic_p generic = NULL;
538  clan_symbol_p top = symbol;
539 
540  // A first scan to know how many arrays there are.
541  while (symbol != NULL) {
542  nb_arrays++;
543  symbol = symbol->next;
544  }
545 
546  // Build the arrays extension.
547  if (nb_arrays > 0) {
548  arrays = osl_arrays_malloc();
549  CLAN_malloc(arrays->id, int*, nb_arrays * sizeof(int));
550  CLAN_malloc(arrays->names, char**, nb_arrays * sizeof(char *));
551  arrays->nb_names = nb_arrays;
552  symbol = top;
553  i = 0;
554  while (symbol != NULL) {
555  arrays->id[i] = symbol->key;
556  CLAN_strdup(arrays->names[i], symbol->identifier);
557  i++;
558  symbol = symbol->next;
559  }
560 
561  // Embed the arrays in a generic shell.
562  generic = osl_generic_shell(arrays, osl_arrays_interface());
563  }
564 
565  return generic;
566 }
567 
568 
582  char* id, int depth) {
583  clan_symbol_p symbol;
584  symbol = clan_symbol_add(table, id, CLAN_TYPE_ITERATOR);
585 
586  // Ensure that the returned symbol was either a new one, or of the same type.
587  if (symbol->type != CLAN_TYPE_ITERATOR) {
588  yyerror("a loop iterator was previously used for something else");
589  return 0;
590  }
591 
592  // Update the rank, in case the symbol already exists.
593  if (symbol->rank != depth + 1)
594  symbol->rank = depth + 1;
595 
596  clan_symbol_push_at_end(&array[depth], clan_symbol_clone_one(symbol));
597  return 1;
598 }
599 
600 
615 int clan_symbol_update_type(clan_symbol_p table, osl_relation_list_p access,
616  int type) {
617  int key;
618  int relation_type;
619  clan_symbol_p symbol;
620 
621  if (table == NULL)
622  CLAN_error("cannot even try to update type: NULL symbol table");
623  if (access == NULL)
624  CLAN_error("cannot even try to update type: NULL access list");
625 
626  // We will only consider the last reference in the list.
627  while (access->next != NULL)
628  access = access->next;
629 
630  // Get the key (with some cheating with the relation type to be able to use
631  // osl_relation_get_array_id), find the corresponding symbol and update.
632  relation_type = access->elt->type;
633  access->elt->type = OSL_TYPE_READ;
634  key = osl_relation_get_array_id(access->elt);
635  access->elt->type = relation_type;
636  symbol = clan_symbol_lookup_by_key(table, key);
637  if (symbol == NULL)
638  CLAN_error("no symbol corresponding to the key");
639 
640  if ((symbol->type == CLAN_TYPE_ITERATOR) && (type != CLAN_TYPE_ITERATOR)) {
641  yyerror("illegal use of an iterator (update or reference) in a statement");
642  return 0;
643  }
644 
645  if ((symbol->type == CLAN_TYPE_PARAMETER) && (type != CLAN_TYPE_PARAMETER)) {
646  yyerror("illegal use of a parameter (update or reference) in a statement");
647  return 0;
648  }
649 
650  symbol->type = type;
651  return 1;
652 }
static int clan_symbol_generate_new_key(clan_symbol_p table)
Definition: symbol.c:278
osl_strings_p clan_symbol_array_to_strings(clan_symbol_p *sarray, int size, int *depths, int *labels)
Definition: symbol.c:417
clan_symbol_p clan_symbol_add(clan_symbol_p *table, char *identifier, int type)
Definition: symbol.c:323
int clan_symbol_get_rank(clan_symbol_p symbol, char *identifier)
Definition: symbol.c:374
void clan_symbol_free(clan_symbol_p symbol)
Definition: symbol.c:214
struct clan_symbol * next
Definition: symbol.h:60
void yyerror(char *)
int rank
Definition: symbol.h:59
clan_symbol_p clan_symbol_clone_one(clan_symbol_p symbol)
Definition: symbol.c:513
clan_symbol_p clan_symbol_lookup_by_key(clan_symbol_p symbol, int key)
Definition: symbol.c:260
int clan_symbol_get_type(clan_symbol_p symbol, char *identifier)
Definition: symbol.c:394
int clan_symbol_nb_of_type(clan_symbol_p symbol, int type)
Definition: symbol.c:458
clan_symbol_p clan_symbol_malloc()
Definition: symbol.c:195
osl_generic_p clan_symbol_to_arrays(clan_symbol_p symbol)
Definition: symbol.c:533
int type
Definition: symbol.h:58
int clan_symbol_update_type(clan_symbol_p table, osl_relation_list_p access, int type)
Definition: symbol.c:615
clan_symbol_p clan_symbol_lookup(clan_symbol_p symbol, char *identifier)
Definition: symbol.c:240
osl_generic_p clan_symbol_to_strings(clan_symbol_p symbol, int type)
Definition: symbol.c:483
void clan_symbol_print_structure(FILE *file, clan_symbol_p symbol, int level)
Definition: symbol.c:73
void clan_symbol_print(FILE *file, clan_symbol_p symbol)
Definition: symbol.c:178
int clan_symbol_get_key(clan_symbol_p symbol, char *identifier)
Definition: symbol.c:354
char * identifier
Definition: symbol.h:57
int clan_symbol_new_iterator(clan_symbol_p *table, clan_symbol_p *array, char *id, int depth)
Definition: symbol.c:581
void clan_symbol_push_at_end(clan_symbol_p *table, clan_symbol_p symbol)
Definition: symbol.c:298
int key
Definition: symbol.h:56