PIPS
uninitialized_variables.c
Go to the documentation of this file.
1 /*
2 
3  $Id: uninitialized_variables.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  Verify the initializations of the variables of a module.
29 
30  Ronan.Keryell@cri.ensmp.fr
31 
32  */
33 
34 #include "local.h"
35 
38 
39 /* Build the tables relating a statement with the variables it uses
40  that have been initialized elsewhere.
41 
42  This function is heavily inspired by
43  build_statement_to_statement_dependence_mapping() in the use-def
44  elimination transformation: */
45 static void
47 {
49 
51  statement s1 = vertex_to_statement(a_vertex);
52 
53  pips_debug(7, "\tSuccessor list: %p for statement ordering %td\n",
54  vertex_successors(a_vertex),
56  FOREACH(SUCCESSOR, a_successor, vertex_successors(a_vertex)) {
57  vertex v2 = successor_vertex(a_successor);
59  dg_arc_label an_arc_label = successor_arc_label(a_successor);
60  pips_debug(7, "\t%p --> %p with conflicts\n", s1, s2);
61  /* Try to find at least one of the use-def chains between
62  s and a successor: */
63  FOREACH(CONFLICT, a_conflict,
64  dg_arc_label_conflicts(an_arc_label)) {
65  statement use;
66  statement def;
67  effect src_eff = conflict_source(a_conflict);
68  effect sink_eff = conflict_sink(a_conflict);
69 
70  ifdebug(7) {
71  fprintf(stderr, "\t\tfrom ");
72  print_words(stderr, words_effect(src_eff));
73  fprintf(stderr, " to ");
74  print_words(stderr, words_effect(sink_eff));
75  fprintf(stderr, "\n");
76  }
77 
78  /* Something is useful for the current statement if it writes
79  something that is used in the current statement: */
80  if (action_write_p(effect_action(src_eff))
81  && action_read_p(effect_action(sink_eff))) {
82  def = s1;
83  use = s2;
84  }
85  else
86  /* The dependance is not a use-def one, look forward... */
87  /* FI: it looks more like a def-use... */
88  continue;
89 
90  {
91  /* Mark that we will visit the node that defined a source
92  for this statement, if not already visited: */
93  /* FI: in Fortran, with static aliasing, this is not really
94  safe. a_variable is not uniquely defined */
96  set def_use_variables;
97 
98  def_use_variables = (set) hash_get(flint_statement_def_use_variables, (char *) use);
99 
100  if (def_use_variables == (set) HASH_UNDEFINED_VALUE) {
101  /* It is the first dependence found for use. Create the
102  set. */
103  def_use_variables = set_make(set_pointer);
104 
106  (char *) use,
107  (char *) def_use_variables);
108  }
109 
110  /* Mark the fact that s2 create something
111  useful for s1: */
112  set_add_element(def_use_variables,
113  def_use_variables,
114  (char *) a_variable);
115 
116  pips_debug(6, "\tUse: statement %p (%#tx). Def: statement %p (%#tx), variable \"%s\".\n",
117  use, (_uint) statement_ordering(use),
118  def, (_uint) statement_ordering(def),
120  }
121 
122  /* One use-def is enough for this variable
123  couple: */
124  break;
125  }
126  }
127  }
128 }
129 
130 
131 /* Remove the flint_statement_def_use_variables data structure: */
132 static void
134 {
135  HASH_MAP(a_statement, def_use_variables,
136  {
137  set_free((set) def_use_variables);
138  },
142 }
143 
144 
145 /* Return true if a_variable is not initialized elsewhere: */
146 static bool
149 {
150  set def_use_variables = (set) hash_get(flint_statement_def_use_variables,
151  (char *) s);
152  if (def_use_variables == (set) HASH_UNDEFINED_VALUE)
153  /* There is no variable for this statement with previously
154  initialized value. Just return TRUE: */
155  return true;
156 
157  if (set_belong_p(def_use_variables, (char *) a_variable))
158  /* OK, looks like the variable have been previously initialized: */
159  return false;
160 
161  return true;
162 }
163 
164 
165 /* Warn about uninitialized variables in this statement: */
166 static bool
168 {
169  list effects_list = load_proper_rw_effects_list(s);
170 
171  bool something_said_about_this_statement = false;
172 
173  /* It appears that effects are packed by statement number or
174  ordering. I assume that to factorize the prettyprint: */
175  MAP(EFFECT, an_effect,
176  {
177  reference a_reference = effect_any_reference(an_effect);
178  entity a_variable = reference_variable(a_reference);
179  if (action_read_p(effect_action(an_effect))
182  /* Nothing has been output yet: add a banner: */
183  raw_flint_message(false,
184  "\n\nNon-initialized variables:"
185  "\n--------------------------\n");
187  }
188  if (!something_said_about_this_statement) {
189  raw_flint_message(false,
190  "In statement number %d (%d.%d):\n",
191  statement_number(s),
194  something_said_about_this_statement = true;
195  }
196  raw_flint_message(true,
197  "\t\"%s\" used but not initialized.\n",
199  }
200  },
201  effects_list);
202 
203  /* Go on recursion... */
204  return true;
205 }
206 
207 
208 /* Warn about conservatively uninitialized variables in the module: */
209 void
211  statement module_stat)
212 {
215 
216  gen_recurse(module_stat,
219  gen_null);
220 
222  raw_flint_message(false,
223  "\n");
224 
226 }
static graph dependence_graph
Definition: delay.c:93
#define dg_vertex_label_statement(x)
Definition: dg.h:235
#define conflict_sink(x)
Definition: dg.h:167
#define CONFLICT(x)
CONFLICT.
Definition: dg.h:134
#define dg_arc_label_conflicts(x)
Definition: dg.h:201
#define conflict_source(x)
Definition: dg.h:165
list load_proper_rw_effects_list(statement)
list words_effect(effect)
#define effect_any_reference(e)
FI: cannot be used as a left hand side.
#define effect_action(x)
Definition: effects.h:642
#define action_write_p(x)
Definition: effects.h:314
#define action_read_p(x)
Definition: effects.h:311
#define EFFECT(x)
EFFECT.
Definition: effects.h:608
static entity a_variable
void raw_flint_message(bool count, char *fmt,...)
Same as flint_message but a bare bones version
Definition: flint.c:211
#define gen_recurse(start, domain_number, flt, rwt)
Definition: genC.h:283
#define successor_vertex(x)
Definition: graph.h:118
#define successor_arc_label(x)
Definition: graph.h:116
#define vertex_vertex_label(x)
Definition: graph.h:152
#define vertex_successors(x)
Definition: graph.h:154
#define SUCCESSOR(x)
SUCCESSOR.
Definition: graph.h:86
#define graph_vertices(x)
Definition: graph.h:82
#define VERTEX(x)
VERTEX.
Definition: graph.h:122
void gen_null(__attribute__((unused)) void *unused)
Ignore the argument.
Definition: genClib.c:2752
#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 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
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
statement vertex_to_statement(vertex v)
Vertex_to_statement looks for the statement that is pointed to by vertex v.
Definition: util.c:45
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
const char * entity_minimal_name(entity e)
Do preserve scope informations.
Definition: naming.c:214
#define HASH_MAP(k, v, code, ht)
Definition: newgen_hash.h:60
@ hash_pointer
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
struct _set_chunk * set
Definition: newgen_set.h:38
void set_free(set)
Definition: set.c:332
bool set_belong_p(const set, const void *)
Definition: set.c:194
@ set_pointer
Definition: newgen_set.h:44
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
uintptr_t _uint
Definition: newgen_types.h:54
#define ORDERING_NUMBER(o)
#define ORDERING_STATEMENT(o)
#define reference_variable(x)
Definition: ri.h:2326
#define statement_ordering(x)
Definition: ri.h:2454
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
#define statement_number(x)
Definition: ri.h:2452
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
s1
Definition: set.c:247
#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
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
void print_words(FILE *fd, cons *lw)
Definition: print.c:263
static void flint_initialize_statement_def_use_variables(graph dependence_graph)
Build the tables relating a statement with the variables it uses that have been initialized elsewhere...
static void flint_free_statement_def_use_variables()
Remove the flint_statement_def_use_variables data structure:
void flint_uninitialized_variables(graph dependence_graph, statement module_stat)
Warn about conservatively uninitialized variables in the module:
static bool flint_no_uninitialized_variable_ouput_yet
static hash_table flint_statement_def_use_variables
static bool flint_check_uninitialized_variables_in_statement(statement s)
Warn about uninitialized variables in this statement:
static bool flint_variable_uninitialize_elsewhere(statement s, entity a_variable)
Return true if a_variable is not initialized elsewhere: