PIPS
module.c
Go to the documentation of this file.
1 /*
2 
3  $Id: module.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 #include <stdio.h>
28 #include <strings.h>
29 #include <string.h>
30 
31 #include "linear.h"
32 
33 #include "genC.h"
34 #include "ri.h"
35 
36 #include "ri-util.h"
37 #include "workspace-util.h"
38 #include "control.h"
39 #include "pipsdbm.h"
40 #include "text-util.h" // for set_prettyprint_language_from_property()
41 
42 #include "resources.h"
43 #include "properties.h"
44 
45 #include "misc.h"
46 
47 /* FI: a short-term solution to fix declarations lost due to
48  unstructured building by controlizer. */
50 {
51  /* Get all the declarations found (recursively) in the module */
52  list dl = statement_to_declarations(module_stat);
53  /* Get all the entities referenced in the module */
54  list vl = statement_to_referenced_entities(module_stat);
55  list fl = statement_to_called_user_entities(module_stat);
56  /* To preserve the order, it would be better to collect variables
57  and functions at the same time with a
58  statement_to_referenced_or_called_entities()*/
59  list vfl = gen_nconc(vl, fl);
60  list udl = NIL;
64 
65  /* Build a list of entities that are not declared anywhere: */
66  MAP(ENTITY, e, {
67  if(!gen_in_list_p(e, dl) && !gen_in_list_p(e, cudl)
68  && !gen_in_list_p(e, udl) && !formal_parameter_p(e)
69  && !member_entity_p(e))
70  udl = gen_nconc(udl, CONS(ENTITY, e, NIL));
71  }, vfl);
72  gen_free_list(dl);
73 
74  if(!ENDP(udl)) {
75  ifdebug(8) {
76  pips_debug(8, "Lost declarations: ");
77  print_entities(udl);
78  }
79  if(statement_block_p(module_stat))
80  statement_declarations(module_stat)
81  = gen_nconc(statement_declarations(module_stat), udl);
82  else if(statement_unstructured_p(module_stat)) {
83  // might be OK...
84  // should only done on blocks?
85  statement_declarations(module_stat)
86  = gen_nconc(statement_declarations(module_stat), udl);
87  }
88  else {
89  module_stat = make_block_statement(CONS(STATEMENT, module_stat, NIL));
90  statement_declarations(module_stat)
91  = gen_nconc(statement_declarations(module_stat), udl);
92  }
93  }
94  return module_stat;
95 }
96 
97 /* Transform a code with some goto and labels (typically generated by a
98  parser) into a code that is a hierarchical control flow graph, the
99  standard abstract syntax tree of PIPS (the RI).
100 
101  Interface for pipsdbm and pipsmake */
102 bool new_controlizer(const char* module_name)
103 {
104  if (getenv(USE_OLD_CONTROLIZER_ENV_VAR_NAME) != NULL) {
105  pips_user_warning("Force the use of the old controlizer because a '%s' environment variable is defined\n", USE_OLD_CONTROLIZER_ENV_VAR_NAME);
106  return controlizer(module_name);
107  }
108 
110  pips_assert("Module must be defined in symbol table",!entity_undefined_p(m));
111 
112  statement module_stat, parsed_mod_stat;
113 
114  // generate pragma string or expression using the correct language:
116  if(value_code_p(mv)) {
117  code c = value_code(mv);
119  } else {
120  /* Should never happen */
122  }
123 
125 
126  parsed_mod_stat = (statement) db_get_memory_resource(DBR_PARSED_CODE, module_name, true);
127  module_stat = copy_statement(parsed_mod_stat) ;
128  /* To have the debug in unspaghettify_statement() working: */
129  set_current_module_statement(module_stat);
130 
131  debug_on("CONTROL_DEBUG_LEVEL");
132  ifdebug(1){
133  statement_consistent_p(parsed_mod_stat);
134  statement_consistent_p(module_stat);
135  }
136 
137  /* The statement of a compilation unit is a long list of continue
138  statements and it takes a long time to restructure although
139  nothing is done in the end. So, let's skip this useless
140  processing.
141  SG:it may be ok to skip it, but we still need to call module_reorder ...
142  */
144  /* *module_stat can be re-used because control_graph reallocates
145  statements; do not show that to any student!
146  statement_instruction(module_stat) =
147  make_instruction(is_instruction_unstructured,
148  control_graph(module_stat));
149  Maintenant que je nettoie le code aussi avant le controlizer,
150  un programme sans instruction ne contient qu'un statement
151  RETURN, c'est a` dire un statement de CALL vers RETURN avec le
152  label 00000. Comme la ligne ci-dessus recycle le label et le
153  commentaire, on se retrouve avec un unstructured avec le label
154  et le commentaire du RETURN qu'il contient... En plus il y avait
155  une re'cursion de l'unstructured vers module_stat. :-(
156 
157  So now correct the label and the comment: */
158 
159  pips_assert("the module statement is consistent "
160  "before the controlizer is called",
161  statement_consistent_p(module_stat));
162 
163  module_stat = hcfg(module_stat);
164 
165  pips_assert("the module statement is consistent "
166  "after the controlizer call",
167  statement_consistent_p(module_stat));
168 
169  if (get_bool_property("FOR_TO_DO_LOOP_IN_CONTROLIZER")) {
170  gen_recurse(module_stat,
171  // Since for-loop statements can be nested,
172  // only restructure in a bottom-up way, :
175 
176  }
177 
178  if (get_bool_property("FOR_TO_WHILE_LOOP_IN_CONTROLIZER")) {
179  gen_recurse(module_stat,
180  // Since for-loop statements can be nested,
181  // only restructure in a bottom-up way, :
182  //forloop_domain, gen_true,
183  //transform_a_for_loop_into_a_while_loop);
186  }
187 
188  /* By setting this property, we try to unspaghettify the control graph
189  of the module: */
190  if (get_bool_property("UNSPAGHETTIFY_IN_CONTROLIZER"))
191  unspaghettify_statement(module_stat);
192 
193  /* With C code, some local declarations may have been lost by the
194  (current) restructurer. FI: not investigated; should be
195  useless by now.. */
196  if(c_module_p(m))
197  module_stat = update_unstructured_declarations(module_stat);
198 
199  }
200 
201  /* Reorder the module, because we have a new statement structure. */
202  module_reorder(module_stat);
203 
204  statement_consistent_p(module_stat);
205 
206  DB_PUT_MEMORY_RESOURCE(DBR_CODE, module_name, module_stat);
207 
210 
211  debug_off();
212 
213  return true;
214 }
215 
216 
217 /* The old controlizer user interface.
218 
219  Transform a code with some goto and labels (typically generated by a
220  parser) into a code that is a hierarchical control flow graph, the
221  standard abstract syntax tree of PIPS (the RI).
222 
223  Interface for pipsdbm and pipsmake */
224 bool controlizer(const char* module_name)
225 {
226  if (getenv(USE_NEW_CONTROLIZER_ENV_VAR_NAME) != NULL) {
227  pips_user_warning("Force the use of the new controlizer because a '%s' environment variable is defined\n", USE_NEW_CONTROLIZER_ENV_VAR_NAME);
229  }
230 
232  pips_assert("Module must be defined in symbol table",!entity_undefined_p(m));
233 
234  statement module_stat, parsed_mod_stat;
235 
236  // generate pragma string or expression using the correct language:
238  if(value_code_p(mv)) {
239  code c = value_code(mv);
241  } else {
242  /* Should never arise */
244  }
245 
247 
248  parsed_mod_stat = (statement) db_get_memory_resource(DBR_PARSED_CODE, module_name, true);
249  module_stat = copy_statement(parsed_mod_stat) ;
250  /* To have the debug in unspaghettify_statement() working: */
251  set_current_module_statement(module_stat);
252 
253  debug_on("CONTROL_DEBUG_LEVEL");
254  ifdebug(1){
255  statement_consistent_p(parsed_mod_stat);
256  statement_consistent_p(module_stat);
257  }
258 
259  /* The statement of a compilation unit is a long list of continue
260  statements and it takes a long time to restructure although
261  nothing is done in the end. So, let's skip this useless
262  processing.
263  SG:it may be ok to skip it, but we still need to call module_reorder ...
264  */
266  /* *module_stat can be re-used because control_graph reallocates
267  statements; do not show that to any student!
268  statement_instruction(module_stat) =
269  make_instruction(is_instruction_unstructured,
270  control_graph(module_stat));
271  Maintenant que je nettoie le code aussi avant le controlizer,
272  un programme sans instruction ne contient qu'un statement
273  RETURN, c'est a` dire un statement de CALL vers RETURN avec le
274  label 00000. Comme la ligne ci-dessus recycle le label et le
275  commentaire, on se retrouve avec un unstructured avec le label
276  et le commentaire du RETURN qu'il contient... En plus il y avait
277  une re'cursion de l'unstructured vers module_stat. :-(
278 
279  So now correct the label and the comment: */
280 
281  ifdebug(1) pips_assert("the module statement is consistent "
282  "before the controlizer is called",
283  statement_consistent_p(module_stat));
284 
285  module_stat = make_statement(entity_empty_label(),
287  MAKE_ORDERING(0,1),
290  control_graph(module_stat)),
291  NIL /* gen_copy_seq(statement_declarations(parsed_mod_stat))*/,
292  NULL,
295 
296  ifdebug(1) pips_assert("the module statement is consistent "
297  "after the controlizer call",
298  statement_consistent_p(module_stat));
299 
300  /* By setting this property, we try to unspaghettify the control graph
301  of the module: */
302  if (get_bool_property("UNSPAGHETTIFY_IN_CONTROLIZER"))
303  unspaghettify_statement(module_stat);
304 
305 
306  /* With C code, some local declarations may have been lost by the
307  (current) restructurer */
308  if(c_module_p(m))
309  module_stat = update_unstructured_declarations(module_stat);
310 
311  }
312 
313  /* Reorder the module, because we have a new statement structure. */
314  module_reorder(module_stat);
315 
316  ifdebug(1) statement_consistent_p(module_stat);
317 
318  DB_PUT_MEMORY_RESOURCE(DBR_CODE, module_name, module_stat);
319 
322 
323  debug_off();
324 
325  return true;
326 }
statement copy_statement(statement p)
STATEMENT.
Definition: ri.c:2186
bool statement_consistent_p(statement p)
Definition: ri.c:2195
statement make_statement(entity a1, intptr_t a2, intptr_t a3, string a4, instruction a5, list a6, string a7, extensions a8, synchronization a9)
Definition: ri.c:2222
instruction make_instruction(enum instruction_utype tag, void *val)
Definition: ri.c:1166
synchronization make_synchronization_none(void)
Definition: ri.c:2424
struct _newgen_struct_statement_ * statement
Definition: cloning.h:21
#define USE_OLD_CONTROLIZER_ENV_VAR_NAME
The name of the one to force the use of the old controlizer:
Definition: control-local.h:35
#define USE_NEW_CONTROLIZER_ENV_VAR_NAME
– control.h
Definition: control-local.h:33
bool controlizer(const char *module_name)
The old controlizer user interface.
Definition: module.c:224
static statement update_unstructured_declarations(statement module_stat)
FI: a short-term solution to fix declarations lost due to unstructured building by controlizer.
Definition: module.c:49
bool new_controlizer(const char *module_name)
Transform a code with some goto and labels (typically generated by a parser) into a code that is a hi...
Definition: module.c:102
void transform_a_for_loop_statement_into_a_while_loop(statement)
Same as above, but with no calls to ancestors.
void try_to_transform_a_for_loop_into_a_do_loop(forloop)
Try to to transform the C-like for-loops into Fortran-like do-loops.
void unspaghettify_statement(statement)
The real entry point of unspaghettify:
bool compilation_unit_p(const char *module_name)
The names of PIPS entities carry information about their nature.
Definition: entity_names.c:56
const char * module_name(const char *s)
Return the module part of an entity name.
Definition: entity_names.c:296
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
#define gen_recurse(start, domain_number, flt, rwt)
Definition: genC.h:283
statement make_block_statement(list)
Make a block statement from a list of statement.
Definition: statement.c:616
unstructured control_graph(statement)
CONTROL_GRAPH returns the control graph of the statement ST.
statement hcfg(statement)
Compute the hierarchical control flow graph (HCFG) of a statement.
Definition: controlizer.c:2621
void reset_current_module_entity(void)
Reset the current module entity.
Definition: static.c:97
void reset_current_module_statement(void)
Reset the current module statement.
Definition: static.c:221
statement set_current_module_statement(statement)
Set the current module statement.
Definition: static.c:165
entity set_current_module_entity(entity)
static.c
Definition: static.c:66
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
bool gen_true(__attribute__((unused)) gen_chunk *unused)
Return true and ignore the argument.
Definition: genClib.c:2780
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
#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
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327
bool gen_in_list_p(const void *vo, const list lx)
tell whether vo belongs to lx
Definition: list.c:734
#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
#define DB_PUT_MEMORY_RESOURCE(res_name, own_name, res_val)
conform to old interface.
Definition: pipsdbm-local.h:66
bool statement_unstructured_p(statement)
Definition: statement.c:369
list statement_to_referenced_entities(statement)
Get a list of all variables referenced recursively within a statement:
Definition: statement.c:3428
list statement_to_called_user_entities(statement)
Get a list of all user function called recursively within a statement:
Definition: statement.c:3478
list statement_to_declarations(void *)
Get a list of all variables declared recursively within a statement.
Definition: statement.c:3253
void set_prettyprint_language_from_property(enum language_utype native)
set the prettyprint language according to the property PRETTYPRINT_LANGUAGE @description If the prope...
Definition: language.c:103
#define debug_on(env)
Definition: misc-local.h:157
#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 pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define debug_off()
Definition: misc-local.h:160
bool module_reorder(statement body)
Reorder a module and recompute order to statement if any.
Definition: reorder.c:244
#define statement_block_p(stat)
#define STATEMENT_NUMBER_UNDEFINED
default values
#define MAKE_ORDERING(u, s)
On devrait utiliser Newgen pour cela, mais comme on ne doit pas les utiliser directement (mais via st...
#define empty_comments
Empty comments (i.e.
bool c_module_p(entity m)
Test if a module "m" is written in C.
Definition: entity.c:2777
entity module_name_to_entity(const char *mn)
This is an alias for local_name_to_top_level_entity.
Definition: entity.c:1479
entity entity_empty_label(void)
Definition: entity.c:1105
void print_entities(list l)
Definition: entity.c:167
bool member_entity_p(entity e)
Definition: entity.c:1921
extensions empty_extensions(void)
extension.c
Definition: extension.c:43
bool formal_parameter_p(entity)
Definition: variable.c:1489
#define forloop_domain
newgen_extensions_domain_defined
Definition: ri.h:178
#define value_code_p(x)
Definition: ri.h:3065
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
#define code_declarations(x)
Definition: ri.h:784
#define entity_undefined_p(x)
Definition: ri.h:2762
@ is_instruction_unstructured
Definition: ri.h:1475
#define value_code(x)
Definition: ri.h:3067
#define statement_declarations(x)
Definition: ri.h:2460
#define code_language(x)
Definition: ri.h:792
#define language_tag(x)
Definition: ri.h:1590
@ is_language_fortran
Definition: ri.h:1566
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
#define entity_initial(x)
Definition: ri.h:2796
#define ifdebug(n)
Definition: sg.c:47
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
entity module_entity_to_compilation_unit_entity(entity m)
Retrieve the compilation unit containing a module definition.
Definition: module.c:116