PIPS
callgraph.c
Go to the documentation of this file.
1 /*
2 
3  $Id: callgraph.c 23495 2018-10-24 09:19:47Z coelho $
4 
5  Copyright 1989-2016 MINES ParisTech
6 
7  This file is part of PIPS.
8 
9  PIPS is free software: you can redistribute it and/or modify it
10  under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  any later version.
13 
14  PIPS is distributed in the hope that it will be useful, but WITHOUT ANY
15  WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  FITNESS FOR A PARTICULAR PURPOSE.
17 
18  See the GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with PIPS. If not, see <http://www.gnu.org/licenses/>.
22 
23 */
24 #ifdef HAVE_CONFIG_H
25  #include "pips_config.h"
26 #endif
27 /* callgraph.c
28 
29  Entry point:
30 
31  Pierre Berthomier, May 1990
32  Lei Zhou, January 1991
33  Guillaume Oget, June 1995
34 */
35 
36 /* To have asprintf(): */
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 
42 #include "linear.h"
43 
44 #include "genC.h"
45 
46 #include "ri.h"
47 #include "effects.h"
48 #include "text.h"
49 #include "text-util.h"
50 #include "constants.h"
51 #include "ri-util.h"
52 #include "workspace-util.h"
53 #include "misc.h"
54 #include "database.h" /* DB_PUT_FILE_RESOURCE is defined there */
55 #include "pipsdbm.h"
56 #include "resources.h"
57 
58 #include "phases.h"
59 #include "pipsmake.h"
60 
61 #include "callgraph.h"
62 
63 /* get all the callees of the module module_name,return the no-empty
64  list of string.
65  if the module has callee(s),the first element of the return list
66  is the mudule's last callee.
67 */
68 list
70 {
72 
73  if(false && static_module_name_p(module_name))
74  cl = (callees)db_get_memory_resource(DBR_CALLEES,module_name,true);
75  else {
76  // Should be dealt with in ri-util
77  // string ln = global_name_to_user_name(module_name);
78  const char* ln = local_name(module_name);
79  ln += strspn(ln, MAIN_PREFIX)
80  + strspn(ln, BLOCKDATA_PREFIX)
81  + strspn(ln, COMMON_PREFIX);
82  cl = (callees)db_get_memory_resource(DBR_CALLEES,ln,true);
83  }
84  return callees_callees(cl);
85 }
86 
87 
88 list
90 {
91  list callees_list=NIL;
92  const string module_name = entity_name(mod);
93  list rl = NIL;
94 
95  callees_list = string_to_callees(module_name);
96 
97  FOREACH(STRING, e,callees_list)
98  rl = CONS(ENTITY, module_name_to_entity(e), rl);
99 
100  return rl;
101 }
102 
104 {
105  if (!entity_main_module_p(mod))
106  {
107  const char* mod_name = module_local_name(mod);
108  callees callers =
109  (callees) db_get_memory_resource(DBR_CALLERS,mod_name,true);
110  list l_callers = callees_callees(callers);
111  while (!ENDP(l_callers))
112  {
113  string caller_name = STRING(CAR(l_callers));
116  l_callers = CDR(l_callers);
117  }
118  return false;
119  }
120  return true;
121 }
122 
123 typedef struct {
127 
129 {
130  if(same_entity_p(call_function(c), p->m))
131  p->sites=CONS(CALL,c,p->sites);
132 }
133 
135 {
136  if(declaration_statement_p(s)) {
140  }
141  }
142 }
143 
144 /**
145  * given a list @p callers_statement of module statements
146  * returns a list of calls to module @p called_module
147  *
148  */
149 list callers_to_call_sites(list callers_statement, entity called_module)
150 {
151  gather_call_sites_t p ={ NIL,called_module };
152  FOREACH(STATEMENT,caller_statement,callers_statement)
153  gen_context_multi_recurse(caller_statement,&p,
156  return p.sites;
157 }
158 
159 /**
160  * given a list @p callers of module name calling module @p called module
161  * return a list of their body
162  */
164 {
165  list statements = NIL;
166  FOREACH(STRING,caller_name,callers)
167  {
168  statement caller_statement =
169  (statement) db_get_memory_resource(DBR_CODE, caller_name, true);
170  statements = CONS(STATEMENT, caller_statement, statements);
171  }
172  return gen_nreverse(statements);
173 }
174 
175 /* change the parameter order for function @p module
176  * using comparison function @p cmp
177  * both compilation unit and callers are touched
178  * SG: it may be put in ri-util, but this would create a dependency from callgraph ...
179  */
181 {
182  /* retrieve the formal parameters */
184  /* order them */
185  gen_sort_list(fn,cmp);
186  /* update offset */
187  intptr_t offset=0;
188  // holds correspondence between old and new offset
189  int reordering[gen_length(fn)];
190  FOREACH(ENTITY,f,fn) {
193  }
194  /* update parameter list */
196  list new_parameters = NIL;
197  for(size_t i=0;i<gen_length(fn);i++) {
198  new_parameters =
199  CONS(PARAMETER,PARAMETER(gen_nth((int)reordering[i],parameters)),
200  new_parameters);
201  }
202  new_parameters=gen_nreverse(new_parameters);
203  module_functional_parameters(module)=new_parameters;
204  /* change call sites */
205  list callers = callees_callees(
207  true));
208  list callers_statement = callers_to_statements(callers);
209  list call_sites = callers_to_call_sites(callers_statement,module);
210  /* for each call site , reorder arguments according to table reordering */
211  FOREACH(CALL,c,call_sites) {
212  list args = call_arguments(c);
213  list new_args = NIL;
214  for(size_t i=0;i<gen_length(fn);i++) {
215  new_args = CONS(EXPRESSION, EXPRESSION(gen_nth((int)reordering[i],args)),
216  new_args);
217  }
218  new_args=gen_nreverse(new_args);
219  gen_free_list(args);
220  call_arguments(c)=new_args;
221  }
222  /* tell dbm of the update */
223  for(list citer=callers, siter=callers_statement;
224  !ENDP(citer); POP(citer), POP(siter))
225  DB_PUT_MEMORY_RESOURCE(DBR_CODE, STRING(CAR(citer)),STATEMENT(CAR(siter)));
226  db_touch_resource(DBR_CODE,
228 
229  /* yes! some people use free in pips ! */
230  gen_free_list(call_sites);
231  gen_free_list(callers_statement);
232 
233  gen_free_list(fn);
234  gen_free_list(parameters);
235 }
236 
237 
238 /*
239  callgraph_module_name(margin, module, fp)
240 */
241 static void
243  entity module,
244  FILE * fp,
245  text (*module_to_text)(const string))
246 {
247  const string module_name = (const string) module_resource_name(module);
248  string dir = db_get_current_workspace_directory();
249  text r = make_text(NIL);
250 
251  if (module_to_text)
252  MERGE_TEXTS(r, (*module_to_text)(module_name));
253 
254  print_text(fp, r);
255  fprintf(fp, " %s\n", module_name);
256 
258  {
259  const string n = (const string) module_resource_name(e);
260  string f = db_get_memory_resource(DBR_CALLGRAPH_FILE, n, true);
261  string full = strdup(concatenate(dir, "/", f, NULL));
262  safe_append(fp, full, CALLGRAPH_INDENT, true);
263  free(full);
264  }
265 
266  free(dir);
267 }
268 
269 bool
271  entity module,
272  text (*module_to_text)(const string))
273 {
274  string dir, local, full;
275  FILE * fp;
276 
277  const string name = (const string) module_resource_name(module);
278  local = db_build_file_resource_name(DBR_CALLGRAPH_FILE, name, ".cg");
280  full = strdup(concatenate(dir, "/", local, NULL));
281  free(dir);
282 
283  fp = safe_fopen(full, "w");
284  callgraph_module_name(module, fp, module_to_text);
285  safe_fclose(fp, full);
286  free(full);
287 
288  DB_PUT_FILE_RESOURCE(DBR_CALLGRAPH_FILE, name, local);
289  return true;
290 }
291 
292 
293 
294 /************************************************************ UPDATE CALLEES */
295 
296 
297 /** Add a call to a function to a callees list
298  */
299 static void
300 add_call_to_callees(const call c, callees *current_callees) {
301  entity called = call_function(c);
302  pips_assert("defined entity", !entity_undefined_p(called));
303  pips_debug(8,"considering: %s ->", entity_local_name(called));
304  if (type_functional_p(entity_type(called)) &&
305  storage_rom_p(entity_storage(called)) &&
306  (value_code_p(entity_initial(called)) ||
307  value_unknown_p(entity_initial(called)))) {
308  const char* name = entity_local_name(called);
309  // Only add the callee if not already here:
310  FOREACH(STRING, s, callees_callees(*current_callees))
311  if (same_string_p(name, s))
312  return;
313  pips_debug(8,"adding: %s", entity_local_name(called));
314  callees_callees(*current_callees) =
315  CONS(STRING, strdup(name), callees_callees(*current_callees));
316  }
317  pips_debug(8,"\n");
318 }
319 
320 /**
321  Add calls hidden in variable declarations to the current callees list
322  */
323 static bool
325  const statement s, callees *current_callees)
326 {
327  bool decl_p = declaration_statement_p(s);
328 
329  if (decl_p)
330  {
332  {
334  {
335  value v_init = entity_initial(e);
336  if (value_expression_p(v_init))
337  {
338  gen_context_recurse(v_init, current_callees,
340  }
341  }
342  }
343  }
344  // currently, declarations are attached to CONTINUE statements
345  return !decl_p;
346 }
347 
348 /** Recompute the callees of a module statement.
349 
350  @param stat is the module statement
351 
352  @return the callees of the module
353 */
354 callees
356  callees current_callees = make_callees(NIL);
357  // Visit all the call site of the module:
358  gen_context_multi_recurse(stat, &current_callees,
361  NULL);
362  return current_callees;
363 }
364 
365 
366 /* Global computation of CALLERS, HEIGHT and DEPTH
367  */
368 
369 
371  set vertices,
372  hash_table arcs,
373  hash_table position)
374 {
375  _int n = 1; /* Number of modules processed at the previous iteration */
376  _int iter = 0;
377  _int nvertices = 0;
378 
379  while(n>0) {
380  n = 0;
381  iter++;
382 
383  SET_FOREACH(string,v1,vertices) {
384  _int cmp = 0; /* current module position */
385  string source_module = (string) v1; /* gdb does not access v1 */
386  callees c = (callees) hash_get(arcs, (void *) v1);
387  list destinations = list_undefined;
388 
389  if(c == (callees) HASH_UNDEFINED_VALUE) {
390  pips_internal_error("Arcs undefined for module %s", source_module);
391  }
392  else {
393  destinations = callees_callees(c);
394  }
395 
396  if(hash_get(position, v1) != HASH_UNDEFINED_VALUE)
397  /* already processed */
398  ;
399  else if(ENDP(destinations)) {
400  hash_put(position, v1, (void *) cmp);
401  n++;
402  nvertices++;
403  }
404  else {
405  FOREACH(STRING, v2,destinations) {
406  _int p = 0;
407 
408  if((p = (_int) hash_get(position, v2)) == (_int) HASH_UNDEFINED_VALUE)
409  goto next;
410  cmp = p+1>cmp? p+1 : cmp;
411  }
412  /* do not know when to perform a put or an update... */
413  hash_put(position, v1, (void *) cmp);
414  n++;
415  nvertices++;
416  next: ;
417  }
418  }
419  pips_debug(1, "Iteration %td completed with %td vertices processed\n"
420  "(total number of vertices processed: %td)\n",
421  iter, n, nvertices);
422  }
423 
424  /* Check that all vertices are associated to a position... which only is
425  true if no recursive cycle exists. */
426  ifdebug(7) {
427  SET_FOREACH(string,v1,vertices) {
428  _int p = (_int)hash_get(position, v1);
429  pips_assert("p is defined", p != (_int) HASH_UNDEFINED_VALUE);
430  }
431  }
432 
433  n = 0;
434  SET_FOREACH(string,v1,vertices) {
435  if(hash_get(position, v1) == HASH_UNDEFINED_VALUE) {
436  pips_user_warning("Module %s might be part of a recursive call cycle\n", v1);
437  n++;
438  }
439  }
440  if(n!=0)
441  pips_user_warning("%td module could not be given a position in the call graph,"
442  " probably because of a recursive call cycle.\n", n);
443 }
444 
445 
446 /* callgraph computes the caller list of each module, using the callees
447  * list of them. As a side effect, it also computes their heights and
448  * depths in the call graph and detects recursive call cycles.
449  *
450  * callgraph is not able to generate missing source code.
451  *
452  * Note: although callgraph is directly and internally used by pipsmake
453  * which needs to know about the callers of a module to chain its rules,
454  * it might be better to store it in a future (new) callgraph library (FI)
455  *
456  * Argument "name" is not used. It is instantiated as a specific module
457  * by make() but this routine process the whole program.
458  *
459  */
460 bool callgraph(const string name)
461 {
462  gen_array_t module_array = db_get_module_list();
463  int nmodules = gen_array_nitems(module_array);
464  int i = 0;
465  int n_new_modules = 0; /* Number of modules called whose source code is
466  missing but synthesized by PIPS */
467  /* Should we deal with strings or with entities? */
468  set modules = set_make(set_string);
469  hash_table module_callers = hash_table_make(hash_string, 2*nmodules);
470  hash_table module_callees = hash_table_make(hash_string, 2*nmodules);
471  hash_table module_depth = hash_table_make(hash_string, 2*nmodules);
472  hash_table module_height = hash_table_make(hash_string, 2*nmodules);
473 
474  pips_assert("To silence gcc", name==name);
475  pips_assert("The workspace contains at least one module", nmodules>0);
476 
477  /* Define the module_set and initialize the module callers, except for
478  modules whose source code is missing. */
479  for(i=0; i<nmodules; i++) {
480  const char* module_name = gen_array_item(module_array, i);
482 
483  set_add_element(modules, modules, module_name);
484 
485  c = make_callees(NIL);
486  hash_put(module_callers, (void *) module_name, (void *) c);
487  }
488 
489  /* Compute iteratively the callers from the callees. Synthesize missing
490  * codes if necessary and if the corresponding property is set.
491  *
492  * The number of iterations depends on the order of the modules in the
493  * hash-tables.
494  *
495  * Simple but inefficient implementation for Cathar-2
496  */
497  for(i=0; i<nmodules; i++) {
498  const char* module_name = gen_array_item(module_array, i);
500  list ccm = list_undefined;
501 
503  db_get_memory_resource(DBR_CALLEES, module_name, true);
504  hash_put(module_callees, (void *) module_name, (void *) called_modules);
505 
506  for( ccm = callees_callees(called_modules);
507  !ENDP(ccm);
508  POP(ccm)) {
509  string module_called = STRING(CAR(ccm));
511  bool found = set_belong_p(modules, module_called);
512 
513  /* Should not be an error as PIPS can synthesize missing code
514  and does it elsewhere... */
515  if(!found) {
516 
517  pips_user_warning("no source file for module %s, let's try so synthesize code\n",
518  module_called);
520 
521  /* set_pips_current_computation(DBR_CALLEES, module_called); */
522  /* push_pips_current_computation(DBR_CALLEES, module_called); */
523  if(rmake(DBR_CALLEES, module_called)) {
524  /* It has no callees to exploit anyway; it does not matter that
525  it is not looped over by the main loop. module_callers is
526  going to be updated and will be used to store the results. */
528 
529  n_new_modules++;
530 
531  set_add_element(modules, modules, module_called);
532 
533  c = make_callees(NIL);
534  hash_put(module_callers, (void *) module_called, (void *) c);
535  c = (callees)
536  db_get_memory_resource(DBR_CALLEES, module_called, true);
537  hash_put(module_callees, (void *) module_called, (void *) c);
538  rmake(DBR_CALLERS, module_called);
539  }
540  else {
541  /* You cannot call pips_user_error() again, as it has just been
542  called by rmake via apply_a_rule()*/
543  /*
544  pips_user_error("Provide or let PIPS synthesize source code for module %s\n",
545  module_called);*/
546  set_current_phase_context(BUILDER_CALLGRAPH, name);
547 
548  return false;
549  }
550  /* pop_pips_current_computation(DBR_CALLEES, module_called); */
551  /* reset_pips_current_computation(); */
552  set_current_phase_context(BUILDER_CALLGRAPH, name);
553  }
554 
555  c = (callees) hash_get(module_callers, (void *) module_called);
556  pips_assert("callers are always initialized",
558  callees_callees(c) =
561  }
562  }
563 
564  pips_debug(1, "Compute heights from callee arcs");
565  transitive_positions(modules, module_callees, module_height);
566  pips_debug(1, "Compute depths from caller arcs");
567  transitive_positions(modules, module_callers, module_depth);
568 
569  ifdebug(7) {
570  HASH_MAP(module_name, callers,
571  {
572  pips_debug(7, "adding %p as %s for module %s\n",
573  callers, DBR_CALLERS, (string) module_name);
574  print_callees((callees) callers);
575  fprintf(stderr, "HEIGHT = %td\n", (_int) hash_get(module_height, (string) module_name));
576  fprintf(stderr, "DEPTH = %td\n", (_int) hash_get(module_depth, (string) module_name));
577  }, module_callers);
578  }
579 
580  /* Since Fabien is not available to help with pipsdbm... Let's move on with Cathare-2! */
581  /*
582  if(true) {
583  FILE * h_file = safe_fopen("height", "w");
584  FILE * d_file = safe_fopen("depth", "w");
585  HASH_MAP(module_name, callers,
586  {
587  fprintf(h_file,"%s\t%d\n", (string) module_name,
588  (int) hash_get(module_height, (string) module_name));
589  fprintf(d_file,"%s\t%d\n", (string) module_name,
590  (int) hash_get(module_depth, (string) module_name));
591  }, module_callers);
592  safe_fclose(h_file, "height");
593  safe_fclose(d_file, "depth");
594  }
595  */
596 
597  i=0;
598 
599  HASH_MAP(module_name, callers,
600  {
601  char *depth;
602  char *height;
603 
604  DB_PUT_MEMORY_RESOURCE(DBR_CALLERS, (string) module_name, (void *) callers);
605 
606  asprintf(&depth,"%td", (_int) hash_get(module_depth, (string) module_name));
607  DB_PUT_MEMORY_RESOURCE(DBR_DEPTH, (string) module_name, (void *) depth);
608 
609  asprintf(&height,"%td", (_int) hash_get(module_height, (string) module_name));
610  DB_PUT_MEMORY_RESOURCE(DBR_HEIGHT, (string) module_name, (void *) height);
611  i++;
612  }, module_callers);
613 
614  pips_assert("The number of modules is unchanged", i==nmodules+n_new_modules);
615 
616  hash_table_free(module_callees);
617  hash_table_free(module_callers);
618  hash_table_free(module_height);
619  hash_table_free(module_depth);
620  set_free(modules);
621  gen_array_full_free(module_array);
622  return true;
623 }
callees make_callees(list a)
Definition: ri.c:227
text make_text(list a)
Definition: text.c:107
bool db_touch_resource(const char *rname, const char *oname)
touch logical time for resource[owner], possibly behind the back of pipsdbm.
Definition: database.c:538
static entity current_caller
Definition: alias_check.c:121
static const char * caller_name
Definition: alias_check.c:122
size_t gen_array_nitems(const gen_array_t a)
Definition: array.c:131
void gen_array_full_free(gen_array_t a)
Definition: array.c:77
void * gen_array_item(const gen_array_t a, size_t i)
Definition: array.c:143
#define CALLGRAPH_INDENT
list callers_to_call_sites(list callers_statement, entity called_module)
given a list callers_statement of module statements returns a list of calls to module called_module
Definition: callgraph.c:149
bool callgraph(const string name)
callgraph computes the caller list of each module, using the callees list of them.
Definition: callgraph.c:460
static void callgraph_module_name(entity module, FILE *fp, text(*module_to_text)(const string))
Definition: callgraph.c:242
void sort_parameters(entity module, gen_cmp_func_t cmp)
change the parameter order for function module using comparison function cmp both compilation unit an...
Definition: callgraph.c:180
static bool declaration_statement_add_call_to_callees(const statement s, callees *current_callees)
Add calls hidden in variable declarations to the current callees list.
Definition: callgraph.c:324
static void gather_call_sites_in_block(statement s, gather_call_sites_t *p)
Definition: callgraph.c:134
list callers_to_statements(list callers)
given a list callers of module name calling module called module return a list of their body
Definition: callgraph.c:163
list entity_to_callees(entity mod)
Definition: callgraph.c:89
static void transitive_positions(set vertices, hash_table arcs, hash_table position)
Global computation of CALLERS, HEIGHT and DEPTH.
Definition: callgraph.c:370
static void add_call_to_callees(const call c, callees *current_callees)
Add a call to a function to a callees list.
Definition: callgraph.c:300
static void gather_call_sites(call c, gather_call_sites_t *p)
Definition: callgraph.c:128
callees compute_callees(const statement stat)
Recompute the callees of a module statement.
Definition: callgraph.c:355
list string_to_callees(const string module_name)
callgraph.c
Definition: callgraph.c:69
bool module_to_callgraph(entity module, text(*module_to_text)(const string))
Definition: callgraph.c:270
bool module_is_called_by_main_program_p(entity mod)
Definition: callgraph.c:103
void print_callees(callees)
print.c
Definition: print.c:52
struct _newgen_struct_statement_ * statement
Definition: cloning.h:21
string compilation_unit_of_module(const char *)
The output is undefined if the module is referenced but not defined in the workspace,...
Definition: module.c:350
static Value offset
Definition: translation.c:283
bool static_module_name_p(const char *name)
Check if the given name is a static module name.
Definition: entity_names.c:122
const char * local_name(const char *s)
Does not take care of block scopes and returns a pointer.
Definition: entity_names.c:221
const char * module_name(const char *s)
Return the module part of an entity name.
Definition: entity_names.c:296
FILE * safe_fopen(const char *filename, const char *what)
Definition: file.c:67
int safe_fclose(FILE *stream, const char *filename)
Definition: file.c:77
void safe_append(FILE *out, char *file, int margin, bool but_comments)
Definition: file.c:679
#define gen_context_recurse(start, ctxt, domain_number, flt, rwt)
Definition: genC.h:285
#define STRING(x)
Definition: genC.h:87
void free(void *)
const char * get_current_module_name(void)
Get the name of the current module.
Definition: static.c:121
void gen_context_multi_recurse(void *o, void *context,...)
Multi-recursion with context function visitor.
Definition: genClib.c:3373
bool gen_true2(__attribute__((unused)) gen_chunk *u1, __attribute__((unused)) void *u2)
Definition: genClib.c:2785
void gen_null(__attribute__((unused)) void *unused)
Ignore the argument.
Definition: genClib.c:2752
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
list gen_nreverse(list cp)
reverse a list in place
Definition: list.c:304
#define POP(l)
Modify a list pointer to point on the next element of the list.
Definition: newgen_list.h:59
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
size_t gen_length(const list l)
Definition: list.c:150
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
list gen_nconc(list cp1, list cp2)
physically concatenates CP1 and CP2 but do not duplicates the elements
Definition: list.c:344
#define CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327
#define FOREACH(_fe_CASTER, _fe_item, _fe_list)
Apply/map an instruction block on all the elements of a list.
Definition: newgen_list.h:179
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
gen_chunk gen_nth(int n, const list l)
to be used as ENTITY(gen_nth(3, l))...
Definition: list.c:710
#define list_undefined
Undefined list definition :-)
Definition: newgen_list.h:69
void gen_sort_list(list l, gen_cmp_func_t compare)
Sorts a list of gen_chunks in place, to avoid allocations...
Definition: list.c:796
string db_get_memory_resource(const char *rname, const char *oname, bool pure)
Return the pointer to the resource, whatever it is.
Definition: database.c:755
gen_array_t db_get_module_list(void)
Get an array of all the modules (functions, procedures and compilation units) of a workspace.
Definition: database.c:1266
#define DB_PUT_MEMORY_RESOURCE(res_name, own_name, res_val)
conform to old interface.
Definition: pipsdbm-local.h:66
#define DB_PUT_FILE_RESOURCE
Put a file resource into the current workspace database.
Definition: pipsdbm-local.h:85
bool declaration_statement_p(statement)
Had to be optimized according to Beatrice Creusillet.
Definition: statement.c:224
hash_table hash_table_make(hash_key_type key_type, size_t size)
Definition: hash.c:294
void * hash_get(const hash_table htp, const void *key)
this function retrieves in the hash table pointed to by htp the couple whose key is equal to key.
Definition: hash.c:449
void hash_put(hash_table htp, const void *key, const void *val)
This functions stores a couple (key,val) in the hash table pointed to by htp.
Definition: hash.c:364
void hash_table_free(hash_table htp)
this function deletes a hash table that is no longer useful.
Definition: hash.c:327
string db_build_file_resource_name(const char *rname, const char *oname, const char *suffix)
returns an allocated file name for a file resource.
Definition: lowlevel.c:169
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
#define pips_user_warning
Definition: misc-local.h:146
#define asprintf
Definition: misc-local.h:225
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define pips_internal_error
Definition: misc-local.h:149
#define COMMON_PREFIX
Definition: naming-local.h:34
#define MAIN_PREFIX
Definition: naming-local.h:32
#define BLOCKDATA_PREFIX
Definition: naming-local.h:35
string concatenate(const char *,...)
Return the concatenation of the given strings.
Definition: string.c:183
#define HASH_MAP(k, v, code, ht)
Definition: newgen_hash.h:60
@ hash_string
Definition: newgen_hash.h:32
#define HASH_UNDEFINED_VALUE
value returned by hash_get() when the key is not found; could also be called HASH_KEY_NOT_FOUND,...
Definition: newgen_hash.h:56
#define same_string_p(s1, s2)
#define SET_FOREACH(type_name, the_item, the_set)
enumerate set elements in their internal order.
Definition: newgen_set.h:78
void set_free(set)
Definition: set.c:332
bool set_belong_p(const set, const void *)
Definition: set.c:194
@ set_string
Definition: newgen_set.h:42
set set_make(set_type)
Create an empty set of any type but hash_private.
Definition: set.c:102
set set_add_element(set, const set, const void *)
Definition: set.c:152
char * string
STRING.
Definition: newgen_types.h:39
intptr_t _int
_INT
Definition: newgen_types.h:53
int(* gen_cmp_func_t)(const void *, const void *)
Definition: newgen_types.h:114
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
static char * module
Definition: pips.c:74
string db_get_current_workspace_directory(void)
Definition: workspace.c:96
void set_current_phase_context(const char *rname, const char *oname)
cproto-generated files
Definition: pipsmake.c:89
void reset_current_phase_context(void)
Definition: pipsmake.c:96
bool rmake(const char *rname, const char *oname)
recursive make resource.
Definition: pipsmake.c:919
static list called_modules
list of called subroutines or functions
Definition: procedure.c:57
#define module_functional_parameters(func)
const char * entity_local_name(entity e)
entity_local_name modified so that it does not core when used in vect_fprint, since someone thought t...
Definition: entity.c:453
bool same_entity_p(entity e1, entity e2)
predicates on entities
Definition: entity.c:1321
entity module_name_to_entity(const char *mn)
This is an alias for local_name_to_top_level_entity.
Definition: entity.c:1479
bool entity_main_module_p(entity e)
Definition: entity.c:700
const char * module_local_name(entity e)
Returns the module local user name.
Definition: entity.c:582
const char * module_resource_name(entity e)
Returns a pointer towards the resource name.
Definition: entity.c:593
list module_formal_parameters(entity func)
list module_formal_parameters(entity func) input : an entity representing a function.
Definition: module.c:327
#define type_functional_p(x)
Definition: ri.h:2950
#define formal_offset(x)
Definition: ri.h:1408
#define value_code_p(x)
Definition: ri.h:3065
struct _newgen_struct_callees_ * callees
Definition: ri.h:55
#define callees_undefined
Definition: ri.h:653
#define call_function(x)
Definition: ri.h:709
#define callees_callees(x)
Definition: ri.h:675
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define value_unknown_p(x)
Definition: ri.h:3077
#define entity_storage(x)
Definition: ri.h:2794
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
#define call_domain
newgen_callees_domain_defined
Definition: ri.h:58
#define storage_formal(x)
Definition: ri.h:2524
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define entity_undefined_p(x)
Definition: ri.h:2762
#define entity_name(x)
Definition: ri.h:2790
#define PARAMETER(x)
PARAMETER.
Definition: ri.h:1788
#define statement_declarations(x)
Definition: ri.h:2460
#define CALL(x)
CALL.
Definition: ri.h:679
#define storage_rom_p(x)
Definition: ri.h:2525
#define call_arguments(x)
Definition: ri.h:711
#define entity_type(x)
Definition: ri.h:2792
#define value_expression_p(x)
Definition: ri.h:3080
#define type_variable_p(x)
Definition: ri.h:2947
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
#define entity_initial(x)
Definition: ri.h:2796
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
char * strdup()
#define ifdebug(n)
Definition: sg.c:47
#define intptr_t
Definition: stdint.in.h:294
FI: I do not understand why the type is duplicated at the set level.
Definition: set.c:59
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
#define MERGE_TEXTS(r, t)
void print_text(FILE *fd, text t)
Definition: print.c:195
static int depth
la sequence de nids
@ full
Definition: union-local.h:65