PIPS
callgraph.c File Reference
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "linear.h"
#include "genC.h"
#include "ri.h"
#include "effects.h"
#include "text.h"
#include "text-util.h"
#include "constants.h"
#include "ri-util.h"
#include "workspace-util.h"
#include "misc.h"
#include "database.h"
#include "pipsdbm.h"
#include "resources.h"
#include "phases.h"
#include "pipsmake.h"
#include "callgraph.h"
+ Include dependency graph for callgraph.c:

Go to the source code of this file.

Data Structures

struct  gather_call_sites_t
 

Functions

list string_to_callees (const string module_name)
 callgraph.c More...
 
list entity_to_callees (entity mod)
 
bool module_is_called_by_main_program_p (entity mod)
 
static void gather_call_sites (call c, gather_call_sites_t *p)
 
static void gather_call_sites_in_block (statement s, gather_call_sites_t *p)
 
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 More...
 
list callers_to_statements (list callers)
 given a list callers of module name calling module called module return a list of their body More...
 
void sort_parameters (entity module, gen_cmp_func_t cmp)
 change the parameter order for function module using comparison function cmp both compilation unit and callers are touched SG: it may be put in ri-util, but this would create a dependency from callgraph ... More...
 
static void callgraph_module_name (entity module, FILE *fp, text(*module_to_text)(const string))
 
bool module_to_callgraph (entity module, text(*module_to_text)(const string))
 
static void add_call_to_callees (const call c, callees *current_callees)
 Add a call to a function to a callees list. More...
 
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. More...
 
callees compute_callees (const statement stat)
 Recompute the callees of a module statement. More...
 
static void transitive_positions (set vertices, hash_table arcs, hash_table position)
 Global computation of CALLERS, HEIGHT and DEPTH. More...
 
bool callgraph (const string name)
 callgraph computes the caller list of each module, using the callees list of them. More...
 

Function Documentation

◆ add_call_to_callees()

static void add_call_to_callees ( const call  c,
callees current_callees 
)
static

Add a call to a function to a callees list.

Definition at line 300 of file callgraph.c.

300  {
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 }
#define STRING(x)
Definition: genC.h:87
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
#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 pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define same_string_p(s1, s2)
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
#define type_functional_p(x)
Definition: ri.h:2950
#define value_code_p(x)
Definition: ri.h:3065
#define call_function(x)
Definition: ri.h:709
#define callees_callees(x)
Definition: ri.h:675
#define value_unknown_p(x)
Definition: ri.h:3077
#define entity_storage(x)
Definition: ri.h:2794
#define entity_undefined_p(x)
Definition: ri.h:2762
#define storage_rom_p(x)
Definition: ri.h:2525
#define entity_type(x)
Definition: ri.h:2792
#define entity_initial(x)
Definition: ri.h:2796
char * strdup()

References call_function, callees_callees, CONS, entity_initial, entity_local_name(), entity_storage, entity_type, entity_undefined_p, FOREACH, pips_assert, pips_debug, same_string_p, storage_rom_p, strdup(), STRING, type_functional_p, value_code_p, and value_unknown_p.

Referenced by compute_callees(), and declaration_statement_add_call_to_callees().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ callers_to_call_sites()

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

Parameters
callers_statementallers_statement
called_modulealled_module

Definition at line 149 of file callgraph.c.

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 }
static void gather_call_sites_in_block(statement s, gather_call_sites_t *p)
Definition: callgraph.c:134
static void gather_call_sites(call c, gather_call_sites_t *p)
Definition: callgraph.c:128
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
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
#define call_domain
newgen_callees_domain_defined
Definition: ri.h:58
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413

References call_domain, FOREACH, gather_call_sites(), gather_call_sites_in_block(), gen_context_multi_recurse(), gen_true2(), NIL, gather_call_sites_t::sites, STATEMENT, and statement_domain.

Referenced by do_linearize_array_manage_callers(), normalize_microcode(), and sort_parameters().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ callers_to_statements()

list callers_to_statements ( list  callers)

given a list callers of module name calling module called module return a list of their body

Parameters
callersallers

Definition at line 163 of file callgraph.c.

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 }
static const char * caller_name
Definition: alias_check.c:122
struct _newgen_struct_statement_ * statement
Definition: cloning.h:21
list gen_nreverse(list cp)
reverse a list in place
Definition: list.c:304
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
The structure used to build lists in NewGen.
Definition: newgen_list.h:41

References caller_name, CONS, db_get_memory_resource(), FOREACH, gen_nreverse(), NIL, STATEMENT, and STRING.

Referenced by delay_communications_interprocedurally(), do_linearize_array_manage_callers(), normalize_microcode(), and sort_parameters().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ callgraph()

bool callgraph ( const string  name)

callgraph computes the caller list of each module, using the callees list of them.

As a side effect, it also computes their heights and depths in the call graph and detects recursive call cycles.

callgraph is not able to generate missing source code.

Note: although callgraph is directly and internally used by pipsmake which needs to know about the callers of a module to chain its rules, it might be better to store it in a future (new) callgraph library (FI)

Argument "name" is not used. It is instantiated as a specific module by make() but this routine process the whole program.

Number of modules called whose source code is missing but synthesized by PIPS

Should we deal with strings or with entities?

Define the module_set and initialize the module callers, except for modules whose source code is missing.

Compute iteratively the callers from the callees. Synthesize missing codes if necessary and if the corresponding property is set.

The number of iterations depends on the order of the modules in the hash-tables.

Simple but inefficient implementation for Cathar-2

Should not be an error as PIPS can synthesize missing code and does it elsewhere...

set_pips_current_computation(DBR_CALLEES, module_called);

push_pips_current_computation(DBR_CALLEES, module_called);

It has no callees to exploit anyway; it does not matter that it is not looped over by the main loop. module_callers is going to be updated and will be used to store the results.

You cannot call pips_user_error() again, as it has just been called by rmake via apply_a_rule()

pop_pips_current_computation(DBR_CALLEES, module_called);

reset_pips_current_computation();

Since Fabien is not available to help with pipsdbm... Let's move on with Cathare-2!

Parameters
nameame

Definition at line 460 of file callgraph.c.

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
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
static void transitive_positions(set vertices, hash_table arcs, hash_table position)
Global computation of CALLERS, HEIGHT and DEPTH.
Definition: callgraph.c:370
void print_callees(callees)
print.c
Definition: print.c:52
const char * module_name(const char *s)
Return the module part of an entity name.
Definition: entity_names.c:296
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
#define POP(l)
Modify a list pointer to point on the next element of the list.
Definition: newgen_list.h:59
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
#define list_undefined
Undefined list definition :-)
Definition: newgen_list.h:69
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
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
#define pips_user_warning
Definition: misc-local.h:146
#define asprintf
Definition: misc-local.h:225
#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
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
intptr_t _int
_INT
Definition: newgen_types.h:53
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
struct _newgen_struct_callees_ * callees
Definition: ri.h:55
#define callees_undefined
Definition: ri.h:653
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
#define ifdebug(n)
Definition: sg.c:47
FI: I do not understand why the type is duplicated at the set level.
Definition: set.c:59
static int depth
la sequence de nids

References asprintf, called_modules, callees_callees, callees_undefined, CAR, CONS, db_get_memory_resource(), db_get_module_list(), DB_PUT_MEMORY_RESOURCE, depth, ENDP, fprintf(), gen_array_full_free(), gen_array_item(), gen_array_nitems(), gen_nconc(), hash_get(), HASH_MAP, hash_put(), hash_string, hash_table_free(), hash_table_make(), HASH_UNDEFINED_VALUE, ifdebug, list_undefined, make_callees(), module_name(), NIL, pips_assert, pips_debug, pips_user_warning, POP, print_callees(), reset_current_phase_context(), rmake(), set_add_element(), set_belong_p(), set_current_phase_context(), set_free(), set_make(), set_string, strdup(), STRING, and transitive_positions().

+ Here is the call graph for this function:

◆ callgraph_module_name()

static void callgraph_module_name ( entity  module,
FILE *  fp,
text(*)(const string module_to_text 
)
static

Definition at line 242 of file callgraph.c.

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 }
text make_text(list a)
Definition: text.c:107
#define CALLGRAPH_INDENT
list entity_to_callees(entity mod)
Definition: callgraph.c:89
void safe_append(FILE *out, char *file, int margin, bool but_comments)
Definition: file.c:679
void free(void *)
string concatenate(const char *,...)
Return the concatenation of the given strings.
Definition: string.c:183
char * string
STRING.
Definition: newgen_types.h:39
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
const char * module_resource_name(entity e)
Returns a pointer towards the resource name.
Definition: entity.c:593
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define MERGE_TEXTS(r, t)
void print_text(FILE *fd, text t)
Definition: print.c:195
@ full
Definition: union-local.h:65

References CALLGRAPH_INDENT, concatenate(), db_get_current_workspace_directory(), db_get_memory_resource(), ENTITY, entity_to_callees(), f(), FOREACH, fprintf(), free(), full, make_text(), MERGE_TEXTS, module, module_name(), module_resource_name(), NIL, print_text(), safe_append(), and strdup().

Referenced by module_to_callgraph().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ compute_callees()

callees compute_callees ( const statement  stat)

Recompute the callees of a module statement.

Parameters
statis the module statement
Returns
the callees of the module
Parameters
stattat

Definition at line 355 of file callgraph.c.

355  {
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 }
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 add_call_to_callees(const call c, callees *current_callees)
Add a call to a function to a callees list.
Definition: callgraph.c:300
void gen_null(__attribute__((unused)) void *unused)
Ignore the argument.
Definition: genClib.c:2752

References add_call_to_callees(), call_domain, declaration_statement_add_call_to_callees(), gen_context_multi_recurse(), gen_null(), gen_true2(), make_callees(), NIL, and statement_domain.

Referenced by delay_communications(), delay_communications_interprocedurally(), delay_load_communications(), delay_store_communications(), do_isolate_statement_preconditions_satisified_p(), do_kernelize(), do_unfolding(), expression_substitution(), freia_compiler(), fsm_generation(), fsm_merge_states(), fsm_split_state(), full_fsm_generation(), full_spaghettify(), generate_starpu_pragma(), gpu_ify(), gpu_memory(), if_conversion(), inline_calls(), isolate_statement(), kernel_load_store_engine(), kernelize(), old__gpu_ify(), outline(), outliner_independent_recursively(), phrase_comEngine_distributor(), phrase_distributor(), phrase_distributor_control_code(), phrase_distributor_init(), pragma_outliner(), prepend_call(), process_reduced_loops(), redundant_load_store_elimination(), rename_operator(), safescale_distributor(), safescale_distributor_init(), scalopify(), scalopragma(), sesamify(), simd_remove_reductions(), simdizer(), spaghettify(), taskify(), and wrap_kernel_argument().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ declaration_statement_add_call_to_callees()

static bool declaration_statement_add_call_to_callees ( const statement  s,
callees current_callees 
)
static

Add calls hidden in variable declarations to the current callees list.

Definition at line 324 of file callgraph.c.

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 }
#define gen_context_recurse(start, ctxt, domain_number, flt, rwt)
Definition: genC.h:285
bool declaration_statement_p(statement)
Had to be optimized according to Beatrice Creusillet.
Definition: statement.c:224
#define statement_declarations(x)
Definition: ri.h:2460
#define value_expression_p(x)
Definition: ri.h:3080
#define type_variable_p(x)
Definition: ri.h:2947

References add_call_to_callees(), call_domain, declaration_statement_p(), ENTITY, entity_initial, entity_type, FOREACH, gen_context_recurse, gen_true2(), statement_declarations, type_variable_p, and value_expression_p.

Referenced by compute_callees().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ entity_to_callees()

list entity_to_callees ( entity  mod)
Parameters
modod

Definition at line 89 of file callgraph.c.

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 }
list string_to_callees(const string module_name)
callgraph.c
Definition: callgraph.c:69
entity module_name_to_entity(const char *mn)
This is an alias for local_name_to_top_level_entity.
Definition: entity.c:1479
#define entity_name(x)
Definition: ri.h:2790

References CONS, ENTITY, entity_name, FOREACH, module_name(), module_name_to_entity(), NIL, STRING, and string_to_callees().

Referenced by callgraph_module_name().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ gather_call_sites()

static void gather_call_sites ( call  c,
gather_call_sites_t p 
)
static

Definition at line 128 of file callgraph.c.

129 {
130  if(same_entity_p(call_function(c), p->m))
131  p->sites=CONS(CALL,c,p->sites);
132 }
bool same_entity_p(entity e1, entity e2)
predicates on entities
Definition: entity.c:1321
#define CALL(x)
CALL.
Definition: ri.h:679

References CALL, call_function, CONS, gather_call_sites_t::m, same_entity_p(), and gather_call_sites_t::sites.

Referenced by callers_to_call_sites(), and gather_call_sites_in_block().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ gather_call_sites_in_block()

static void gather_call_sites_in_block ( statement  s,
gather_call_sites_t p 
)
static

Definition at line 134 of file callgraph.c.

135 {
136  if(declaration_statement_p(s)) {
140  }
141  }
142 }

References call_domain, declaration_statement_p(), ENTITY, entity_initial, FOREACH, gather_call_sites(), gen_context_recurse, gen_true2(), and statement_declarations.

Referenced by callers_to_call_sites().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ module_is_called_by_main_program_p()

bool module_is_called_by_main_program_p ( entity  mod)
Parameters
modod

Definition at line 103 of file callgraph.c.

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 }
static entity current_caller
Definition: alias_check.c:121
bool module_is_called_by_main_program_p(entity mod)
Definition: callgraph.c:103
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
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

References callees_callees, caller_name, CAR, CDR, current_caller, db_get_memory_resource(), ENDP, entity_main_module_p(), module_local_name(), module_name_to_entity(), and STRING.

Referenced by alias_propagation(), and alias_propagation_callers().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ module_to_callgraph()

bool module_to_callgraph ( entity  module,
text(*)(const string module_to_text 
)
Parameters
moduleodule

Definition at line 270 of file callgraph.c.

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 }
static void callgraph_module_name(entity module, FILE *fp, text(*module_to_text)(const string))
Definition: callgraph.c:242
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
#define DB_PUT_FILE_RESOURCE
Put a file resource into the current workspace database.
Definition: pipsdbm-local.h:85
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

References callgraph_module_name(), concatenate(), db_build_file_resource_name(), db_get_current_workspace_directory(), DB_PUT_FILE_RESOURCE, free(), full, module, module_resource_name(), safe_fclose(), safe_fopen(), and strdup().

Referenced by print_decorated_call_graph().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ sort_parameters()

void sort_parameters ( entity  module,
gen_cmp_func_t  cmp 
)

change the parameter order for function module using comparison function cmp both compilation unit and callers are touched SG: it may be put in ri-util, but this would create a dependency from callgraph ...

retrieve the formal parameters

order them

update offset

update parameter list

change call sites

for each call site , reorder arguments according to table reordering

tell dbm of the update

yes! some people use free in pips !

Parameters
moduleodule
cmpmp

Definition at line 180 of file callgraph.c.

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 }
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
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
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
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
const char * get_current_module_name(void)
Get the name of the current module.
Definition: static.c:121
size_t gen_length(const list l)
Definition: list.c:150
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327
gen_chunk gen_nth(int n, const list l)
to be used as ENTITY(gen_nth(3, l))...
Definition: list.c:710
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
#define module_functional_parameters(func)
list module_formal_parameters(entity func)
list module_formal_parameters(entity func) input : an entity representing a function.
Definition: module.c:327
#define formal_offset(x)
Definition: ri.h:1408
#define storage_formal(x)
Definition: ri.h:2524
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define PARAMETER(x)
PARAMETER.
Definition: ri.h:1788
#define call_arguments(x)
Definition: ri.h:711
#define intptr_t
Definition: stdint.in.h:294

References CALL, call_arguments, callees_callees, callers_to_call_sites(), callers_to_statements(), CAR, compilation_unit_of_module(), CONS, db_get_memory_resource(), DB_PUT_MEMORY_RESOURCE, db_touch_resource(), ENDP, ENTITY, entity_storage, EXPRESSION, f(), FOREACH, formal_offset, gen_free_list(), gen_length(), gen_nreverse(), gen_nth(), gen_sort_list(), get_current_module_name(), intptr_t, module, module_formal_parameters(), module_functional_parameters, NIL, offset, PARAMETER, POP, STATEMENT, storage_formal, and STRING.

Referenced by normalize_microcode_parameter_orders().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ string_to_callees()

list string_to_callees ( const string  module_name)

callgraph.c

CALLGRAPH_INCLUDED.

Entry point:

Pierre Berthomier, May 1990 Lei Zhou, January 1991 Guillaume Oget, June 1995 To have asprintf(): DB_PUT_FILE_RESOURCE is defined there get all the callees of the module module_name,return the no-empty list of string. if the module has callee(s),the first element of the return list is the mudule's last callee.

Parameters
module_nameodule_name

Definition at line 69 of file callgraph.c.

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 }
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
#define COMMON_PREFIX
Definition: naming-local.h:34
#define MAIN_PREFIX
Definition: naming-local.h:32
#define BLOCKDATA_PREFIX
Definition: naming-local.h:35

References BLOCKDATA_PREFIX, callees_callees, callees_undefined, COMMON_PREFIX, db_get_memory_resource(), local_name(), MAIN_PREFIX, module_name(), and static_module_name_p().

Referenced by entity_to_callees().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ transitive_positions()

static void transitive_positions ( set  vertices,
hash_table  arcs,
hash_table  position 
)
static

Global computation of CALLERS, HEIGHT and DEPTH.

Number of modules processed at the previous iteration

current module position

gdb does not access v1

already processed

do not know when to perform a put or an update...

Check that all vertices are associated to a position... which only is true if no recursive cycle exists.

Definition at line 370 of file callgraph.c.

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 }
#define pips_internal_error
Definition: misc-local.h:149
#define SET_FOREACH(type_name, the_item, the_set)
enumerate set elements in their internal order.
Definition: newgen_set.h:78

References callees_callees, ENDP, FOREACH, hash_get(), hash_put(), HASH_UNDEFINED_VALUE, ifdebug, list_undefined, pips_assert, pips_debug, pips_internal_error, pips_user_warning, SET_FOREACH, and STRING.

Referenced by callgraph().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: