PIPS
graph.c
Go to the documentation of this file.
1 /*
2 
3  $Id: graph.c 23065 2016-03-02 09:05:50Z 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 /*
28  * Build a graph for the callgraph, instead of a tree.
29  *
30  * this SHOULD use the dot format
31  *
32  * Code by Corinne Ancourt and Fabien Coelho.
33  */
34 
35 #include <stdio.h>
36 #include <string.h>
37 
38 #include "linear.h"
39 
40 #include "genC.h"
41 #include "misc.h"
42 
43 #include "pipsdbm.h"
44 
45 #include "ri.h"
46 #include "ri-util.h"
47 
48 #define DV_SUFFIX ".daVinci"
49 
50 /* Build for module name a node and link to its successors.
51  * It could be a per module resource, however the callgraph
52  * is not expected to change often, and we can avoid to manipulate
53  * the many small files.
54  */
55 static void
56 node(FILE * out, string name)
57 {
58  bool first=true;
59  list lcallees = NIL;
60 
61  if (db_resource_p(DBR_CALLEES, name)) /* lazy callees. */
62  lcallees = callees_callees
63  ((callees) db_get_memory_resource(DBR_CALLEES, name, true));
64 
65  /* daVinci node prolog. */
66  fprintf(out, "l(\"%s\",n(\"\",[a(\"OBJECT\",\"%s\")],[", name, name);
67 
68  /* one edge per callee */
69  MAP(STRING, module_called,
70  {
71  if (!first) fprintf(out, ",\n");
72  else { fprintf(out, "\n"); first=false; }
73  fprintf(out, " l(\"%s->%s\",e(\"\",[],r(\"%s\")))",
74  name, module_called, module_called);
75  },
76  lcallees);
77 
78  /* node epilog */
79  fprintf(out, "]))");
80 }
81 
82 /* static function to store whether a module has been seen during the
83  * recursive generation of the daVinci file.
84  */
86 static bool first_seen = false;
87 static void init_seen(void) { first_seen = false;
89 static void close_seen(void) {
91 static void set_as_seen(string m) { hash_put(seen, (char*) m, (char*) 1); }
92 static bool seen_p(string m){ return hash_defined_p(seen, (char*)m); }
93 
94 /* generates into "out" a davinci node for module "name",
95  * and recurse to its not yet seen callees.
96  */
97 static void
98 recursive_append(FILE* out, string name)
99 {
100  if (seen_p(name)) return;
101  /* else */
102  if (first_seen) fprintf(out, ",\n");
103  else first_seen = true;
104  node(out, name);
105  set_as_seen(name);
106 
107  /* the resource may not have been defined, for instance if the
108  * code was not parsed, because the %ALL dependence is limited.
109  */
110  if (db_resource_p(DBR_CALLEES, name))
111  {
112  callees l = (callees) db_get_memory_resource(DBR_CALLEES, name, true);
114  }
115 }
116 
117 /* to be called by pipsmake.
118  * builds the daVinci file for module "name".
119  */
120 bool graph_of_calls(const string name)
121 {
122  FILE * out;
123  string dir_name, file_name, full_name;
125  file_name = db_build_file_resource_name(DBR_DVCG_FILE, name, DV_SUFFIX);
126  full_name = strdup(concatenate(dir_name, "/", file_name, NULL));
127  free(dir_name), dir_name = NULL;
128  out = safe_fopen(full_name, "w");
129  init_seen();
130 
131  /* do the job here. */
132  fprintf(out, "[\n");
133  recursive_append(out, name);
134  fprintf(out, "]\n");
135 
136  close_seen();
138  free(full_name), full_name = NULL;
139  DB_PUT_FILE_RESOURCE(DBR_DVCG_FILE, name, file_name);
140 
141  return true;
142 }
143 
144 /* To be called by pipsmake.
145  * Generate a global resource, hence name is ignored.
146  */
147 bool full_graph_of_calls(string name)
148 {
149  gen_array_t modules = db_get_module_list();
150  int n = gen_array_nitems(modules), i;
151  FILE * out;
152  bool first = true;
153  string dir_name, file_name, full_name;
154 
155  pips_debug(7, "global call graph requested for %s (PROGRAM)\n", name);
156 
157  /* build file name... and open it. */
159 
161  (DBR_DVCG_FILE, PROGRAM_RESOURCE_OWNER, DV_SUFFIX);
162 
163  full_name = strdup(concatenate(dir_name, "/", file_name, NULL));
164 
165  out = safe_fopen(full_name, "w");
166 
167  /* prolog, per module stuff, epilog. */
168  fprintf(out, "[\n");
169 
170  for (i=0; i<n; i++)
171  {
172  if (!first) fprintf(out, ",\n");
173  first=false;
174  node(out, gen_array_item(modules, i));
175  }
176 
177  fprintf(out, "]\n");
178 
179  /* close and clean... */
181  gen_array_free(modules);
182  free(dir_name), dir_name=NULL;
183  free(full_name), full_name=NULL;
184 
185  /* put resulting resource into pipsdbm. */
187 
188  return true;
189 }
static hash_table seen
static function to store whether a module has been seen during the recursive generation of the daVinc...
Definition: graph.c:85
static void init_seen(void)
Definition: graph.c:87
static void close_seen(void)
Definition: graph.c:89
static bool seen_p(string m)
Definition: graph.c:92
static void set_as_seen(string m)
Definition: graph.c:91
#define DV_SUFFIX
Definition: graph.c:48
static bool first_seen
Definition: graph.c:86
bool graph_of_calls(const string name)
to be called by pipsmake.
Definition: graph.c:120
bool full_graph_of_calls(string name)
To be called by pipsmake.
Definition: graph.c:147
static void recursive_append(FILE *out, string name)
generates into "out" a davinci node for module "name", and recurse to its not yet seen callees.
Definition: graph.c:98
static void node(FILE *out, string name)
Build for module name a node and link to its successors.
Definition: graph.c:56
bool db_resource_p(const char *rname, const char *oname)
true if exists and in loaded or stored state.
Definition: database.c:524
static FILE * out
Definition: alias_check.c:128
size_t gen_array_nitems(const gen_array_t a)
Definition: array.c:131
void * gen_array_item(const gen_array_t a, size_t i)
Definition: array.c:143
void gen_array_free(gen_array_t a)
Definition: array.c:70
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 STRING(x)
Definition: genC.h:87
void free(void *)
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
#define MAP(_map_CASTER, _map_item, _map_code, _map_list)
Apply/map an instruction block on all the elements of a list (old fashioned)
Definition: newgen_list.h:226
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_FILE_RESOURCE
Put a file resource into the current workspace database.
Definition: pipsdbm-local.h:85
hash_table hash_table_make(hash_key_type key_type, size_t size)
Definition: hash.c:294
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
bool hash_defined_p(const hash_table htp, const void *key)
true if key has e value in htp.
Definition: hash.c:484
#define full_name(dir, name)
Definition: compile.c:414
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
string concatenate(const char *,...)
Return the concatenation of the given strings.
Definition: string.c:183
@ hash_string
Definition: newgen_hash.h:32
#define hash_table_undefined
Value of an undefined hash_table.
Definition: newgen_hash.h:49
#define PROGRAM_RESOURCE_OWNER
Definition: pipsdbm-local.h:29
string db_get_current_workspace_directory(void)
Definition: workspace.c:96
struct _newgen_struct_callees_ * callees
Definition: ri.h:55
#define callees_callees(x)
Definition: ri.h:675
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
char * strdup()
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
static string file_name