PIPS
flatten_code.c
Go to the documentation of this file.
1 /*
2 
3  $Id: flatten_code.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 
25 #ifdef HAVE_CONFIG_H
26  #include "pips_config.h"
27 #endif
28 
29 /* Flatten code
30 
31  Francois Irigoin, Fabien Coelho, Laurent Daverio.
32 
33  */
34 #include <stdlib.h>
35 #include <stdio.h>
36 
37 #include "genC.h"
38 #include "linear.h"
39 
40 #include "misc.h"
41 #include "properties.h"
42 #include "pipsdbm.h"
43 
44 #include "ri.h"
45 #include "ri-util.h"
46 #include "prettyprint.h" // for debugging
47 
48 #include "control.h" // clean_up_sequences, module_reorder
49 
50 #include "transformations.h" // full_loop_unroll...
51 
52 /* gen_multi_recurse callback on exiting a variable reference:
53  if var needs renaming, rename this reference.
54  */
55 static void rename_reference(reference r, hash_table renamings)
56 {
57  entity var = reference_variable(r);
58  bool replaced = false; // Keep track of any replacement
59  if (hash_defined_p(renamings, var)) {
60  entity nvar = (entity)hash_get(renamings, var);
61  if(nvar!=var) {
62  pips_debug(1, "Reference %s renamed as %s\n",
64  reference_variable(r) = nvar;
65  replaced = true;
66  }
67  }
68 
69  if(replaced) {
70  /* we need to unormalize the uppermost parent of this expression
71  * otherwise its normalized field gets incorrect */
72  expression next=(expression)r,parent = NULL;
73  while((next=(expression) gen_get_ancestor(expression_domain,next))) {
74  parent=next;
75  }
76  if(parent) {
77  unnormalize_expression(parent); /* otherwise field normalized get wrong */
78  }
79  }
80 }
81 
82 /* gen_multi_recurse callback on exiting a loop:
83  * if loop index needs renaming, rename this occurrence.
84  *
85  * Take advantage of this opportunity to serialize the loop in order
86  * to avoid any inconsistency. Local variables moved out of the loop
87  * may require a privatization after flattening of the loop is to be
88  * kept parallel.
89  */
90 static void rename_loop_index(loop l, hash_table renamings)
91 {
92  entity var = loop_index(l);
93 
94  execution ex = loop_execution(l);
95  if(execution_parallel_p(ex))
97 
98  if (hash_defined_p(renamings, var)) {
99  entity nvar = (entity)hash_get(renamings, var);
100  if(nvar!=var) {
101  pips_debug(1, "Loop index %s renamed as %s\n",
103  loop_index(l) = nvar;
104  }
105  }
106 }
107 
108 /* If the type of variable var is a typedefed type, it may have been
109  renamed and the symbol table must be updated. */
110 static void rename_variable_type(entity var, hash_table renamings)
111 {
112  type t = entity_type(var);
113  if(typedef_type_p(t)) {
114  variable v = type_variable(t);
115  basic b = variable_basic(v);
116  entity tt = basic_typedef(b);
117  entity ntt = (entity)hash_get(renamings, tt);
118  if(!entity_undefined_p(ntt))
119  basic_typedef(b) = ntt;
120  }
121  else if(struct_type_p(t) || union_type_p(t) || enum_type_p(t)){
122  variable v = type_variable(t);
123  basic b = variable_basic(v);
124  entity tt = basic_derived(b);
125  entity nst = (entity)hash_get(renamings, tt);
126  if(!entity_undefined_p(nst))
127  basic_typedef(b) = nst;
128  }
129 }
130 
131 /* gen_multi_recurse callback on exiting a statement: recompute the
132  declaration list for statement s and transform initializations into
133  assignments when required according to the renaming map
134  "renamings". Renaming may be neutral to handle external
135  variables. The initial values are used to specify if an assignment
136  must be created or not. */
138 {
139  if (declaration_statement_p(s)) {
140  list inits = NIL;
141  list decls = statement_declarations(s); // Non-recursive
143  list ndecls = NIL;
144  list tmp = NIL; /* holds the entity to remove from declarations */
145 
146  pips_debug(1, "Begin for statement %p\n", s);
147 
148  FOREACH(ENTITY, var, decls) {
149  entity nvar = (entity)hash_get(renamings, var);
150 
151  if(entity_undefined_p(nvar)) {
152  /* Well, we could synthesize a new function to perform the
153  initialization. */
154  pips_debug(1, "Local variable %s is preserved because its initial value "
155  "is not assignable\n", entity_local_name(var));
156  ndecls = gen_nconc(ndecls, CONS(ENTITY, var, NIL));
157  replace_entities(entity_type(var),renamings);
158  }
159  else if(var!=nvar) {
160  /* If the new variable declaration does not contain the
161  initial value of the variable declaration, an
162  initialization statement must be inserted */
164  && value_unknown_p(entity_initial(nvar))) {
167  gen_context_recurse(ie,renamings,
169  replace_entities(entity_type(nvar),renamings);
170 
171  inits = gen_nconc(inits, CONS(statement, is, NIL));
172 
173  pips_debug(1, "Initialize var %s with initial value of var %s: ",
175  );
176  ifdebug(1){
177  print_expression(ie);
178  fprintf(stderr, "\n");
179  }
180  }
181  tmp=CONS(ENTITY,var,tmp);
182  }
183  else {
184  /* FI: The comment below used to be true before we used
185  declaration statements... */
186  /* Do nothing and the local declaration will be lost */
187  pips_debug(1, "Declaration for external variable \"%s\" moved.\n",
188  entity_name(var));
189  }
190  /* Should we worry that the type itself has been renamed because
191  a typedef is used? */
192  rename_variable_type(var, renamings);
193  }
194 
195  /* calling RemoveLocalEntityFromDeclarations will tidy the
196  declarations and the declaration_statements */
197  FOREACH(ENTITY,e,tmp)
199  gen_free_list(tmp);
200 
201  if(!ENDP(inits)) {
202  /* Insert the list of initialisation statements as a sequence at
203  the beginning of s.
204  */
205  inits = gen_nconc(inits,
207  ifdebug(1)
208  print_statements(inits);
209 #if 0
210  if(get_bool_property("C89_CODE_GENERATION")) {
211  /* The initializations must be inserted at the right place,
212  which may prove impossible if some of the initializations
213  cannot be moved but are used. Example:
214 
215  int a[] = {1, 2, 3};
216  int i = a[1];
217  */
218  pips_internal_error("C89 flattened code not generated yet");
219  }
220  else
221 #endif
222  { /* C99*/
225  /* FI: why kill he initial statement number? */
228  string c = statement_comments(s);
229  statement fs = STATEMENT(CAR(inits));
230  statement_comments(fs) = c;
231  /* FI: should be a call to defined_empty_comments() or
232  something like it. Currently, empty_comments is a macro
233  and its value is string_undefined:-( */
234  statement_comments(s) = strdup("");
235  }
236  }
237  }
238 
239  //gen_free_list(statement_declarations(s));
240 
241  statement_declarations(s) = ndecls;
242 
243  pips_debug(1, "End. Local declarations %s.\n",
244  ENDP(ndecls)? "removed" : "updated");
245  }
246 }
247 
248 /* To generate the new variables, we need to know:
249  *
250  * - if there is an enclosing control cycle
251  *
252  * - what is the (current) statement to be used for declaration
253  *
254  * - the current scope corresponding to that statement
255  *
256  * - the current module name (get_current_module_name() could be used
257  * instead)
258  *
259  * - and the renaming map
260  *
261  * This data structure is private to flatten_code.c
262  */
263 typedef struct redeclaration_context {
266  const char* scope;
267  const char* module_name;
270 
271 /* This function makes the key decision about the renaming: should
272  the variable be renamed? Are the renaming and declaration move
273  compatible with its initialization expression and its control
274  context? */
276 {
278 
279  /* Are we entering a (potential) cycle? Do we have a function to
280  detect unstructured with no cycles? */
281  if(instruction_loop_p(i)
285  rdcp->cycle_depth++;
288  const char* mn = rdcp->module_name;
289  string vn = entity_name(v);
290  const char* vmn = module_name(vn);
291 
292  if (hash_defined_p(rdcp->renamings, v)) {
293  pips_debug(5, "Skipping the already processed variable \"%s\" \n",
294  entity_user_name(v));
295  continue;
296  }
297 
298  if(strcmp(mn, vmn)!=0) {
299  /* This is not a local variable. Its declaration can be
300  moved if not already there. */
301  statement ds = rdcp->declaration_statement;
302  list dv = statement_declarations(ds);
303 
304  if(!entity_is_argument_p(v, dv)) {
305  pips_debug(5, "Entity is not an argument\n");
307  }
308  hash_put_or_update(rdcp->renamings, v, v);
309  }
310  else { /* This is a block local stack allocated or static
311  variable or a derived type or a typedef type */
312  /* FI: the case of static variables is not taken into account
313  properly. */
315  bool redeclare_p = false;
316  bool move_initialization_p = false;
317 
318  /* Can we move or transform the initialization? */
320 
321  /* No initialization issue, let's move the declaration */
322  redeclare_p = true;
323  move_initialization_p = true;
324  }
325  else if(rdcp->cycle_depth>0) {
326  /* We are in a control cycle. The initial value must be
327  reassigned where the declaration was, if the variable is
328  not static. */
329  if(variable_static_p(v)) {
330  redeclare_p = true;
331  move_initialization_p = true;
332  }
333  else if(expression_is_C_rhs_p(ie)) { // This function is not yet precise enough
334  redeclare_p = true;
335  move_initialization_p = false;
336  }
337  else {
338  /* It could be redeclared if a small function was
339  synthesized to perform the assignment
340  dynamically. Basically, a loop nest over the array
341  dimensions. */
342  redeclare_p = false;
343  move_initialization_p = false;
344  }
345  }
346  else {
347  /* We are not in a control cycle. The initial value
348  expression, if constant, can be moved with the
349  new declaration. This avoids problem with non-assignable
350  expressions such as brace expressions used in
351  initializations at declaration. */
353  redeclare_p = true;
354  move_initialization_p = true;
355  }
356  else if(expression_is_C_rhs_p(ie)) {
357  redeclare_p = true;
358  move_initialization_p = false;
359  }
360  else {
361  redeclare_p = false;
362  move_initialization_p = false;
363  }
364  }
365 
366  if(redeclare_p) {
367 
368  /* Build the new variable */
369  /* const char* eun = entity_user_name(v); */
370  /* string negn = typedef_entity_p(v)? */
371  /* strdup(concatenate(mn, MODULE_SEP_STRING, rdcp->scope, */
372  /* TYPEDEF_PREFIX, eun, NULL)) */
373  /* : */
374  /* strdup(concatenate(mn, MODULE_SEP_STRING, rdcp->scope, eun, NULL)); */
375  // const char* eun = entity_name_without_scope(v);
376  const char* eun = strrchr(entity_name(v), BLOCK_SEP_CHAR);
377  if(eun==NULL)
378  eun = strrchr(entity_name(v), MODULE_SEP_CHAR);
379  string negn =
380  strdup(concatenate(mn, MODULE_SEP_STRING, rdcp->scope, eun+1, NULL));
382  //list unused_nvs = NIL;
383 
384  /* When renaming the variable, we must make sure that we are
385  not creating a user name conflict at source-code
386  level. For now we will keep regenerating nv and checking
387  it against the list of all entities used in the
388  statement, until no conflict remains.
389  */
390 
391  statement ds = rdcp->declaration_statement;
392  /* FI: I do not undestand why we look for references instead
393  of declarations... (02/11/2014) */
395  bool is_same_name = false;
396 
397  ifdebug(8) {
398  pips_debug(8, "Entities found in declaration statement: ");
399  print_entities(dselist);
400  fprintf(stderr, "\n");
401  }
402 
403  /* We iterate over suffixes (_0, _1, _2, ...) and test if we
404  generate a conflict */
405  do {
406  nv = make_entity_copy_with_new_name(v, negn, move_initialization_p);
407  FOREACH(ENTITY, dv, dselist) {
408 
409  if (dv == v)
410  {
411  pips_debug(8, "Skipping the variable \"%s\" we are working on\n",
412  entity_user_name(v));
413  continue;
414  }
415 
416  is_same_name =
417  strcmp(entity_user_name(dv), entity_user_name(nv)) == 0;
418  if (is_same_name) {
419  pips_debug(1, "Proposed variable \"%s\" "
420  "conflicts with references in declaration statement\n",
421  entity_name(nv));
422  break;
423  }
424  }
425  if (is_same_name) {
426  // WARNING: We must remember to free the newly declared nv when it's not used!
427  //unused_nvs = CONS(ENTITY, nv, unused_nvs);
428  }
429  } while (is_same_name);
430 
431  /* FI: what happens to external entities whose declarations
432  is moved, but the name unchanged? */
435  rdcp->declaration_statement);
436  hash_put_or_update(rdcp->renamings, v, nv);
437  pips_debug(1, "Variable %s renamed as %s\n", entity_name(v), entity_name(nv));
438  }
439  }
440  }
441  }
442 
443  return true;
444 }
445 
446 /* Keep track of cycle exit in the hierarchical control flow graph */
449 {
451 
452  /* Are entering a (potential) cycle? */
453  if(instruction_loop_p(i)
457  rdcp->cycle_depth--;
458 }
459 
460 /* FI: added to wrap up the use of redeclaration context... */
461 static void compute_renamings(
462  statement s, const char* sc, const char* mn, hash_table renamings)
463 {
464  string mnc = strdup(mn);
465  redeclaration_context_t rdc = { 0, s, sc, mnc, renamings};
466 
468  &rdc,
472 
473  free(mnc);
474 }
475 
476 /*
477  This functions locates all variable declarations in embedded blocks,
478  and moves them to the top-level block when possible, renaming them
479  in case of conflicts.
480 
481  First, we are going to loop through each declaration in the
482  statement instruction (no in the statement itself) and its
483  sub-blocks, and build a renaming map: an (entity-> new entity) hash
484  of pointers to keep track of renamed variables
485 
486  Not all variable declarations can be moved and/or renamed. Not all
487  initializations can be transformed into assignments. And some
488  variables declared locally are not variables local to the block.
489 
490  If a variable with the name we would like for the renamed variable
491  is already in the symbol table, we have a naming conflict. In that case, we
492  create a new entity sharing the same properties as the conflicting
493  one, but with a derived name (original name + numerical suffix), and
494  we update the hashtable with the new entity
495 
496  When the renaming map is computed, we can then use it to update
497  the statement via a gen_multi_recurse. Specifically, we need to:
498 
499  - rename variable references
500 
501  - rename loop indexes
502 
503  - replace declaration statements
504 
505  @return false if the initial condition are not met, i.e. no parent block
506 
507  FIXME : the return false is not implemented !
508 */
510 {
511  /* For the time being, we handle only blocks with declarations */
512  if (statement_block_p(s)) {
514  // Recursive
516  bool renaming_p = false;
517  string cs = string_undefined;
518  int csl = INT_MAX;
519 
520  /* Can we find out what the local scope of statement s is? */
521  /* FI: Shouldn't it be "0`"? */
522  const char* cmn = entity_user_name(module);
524  string sen = entity_name(se);
525  const char* seln = entity_local_name(se);
526  string cs_se = local_name_to_scope(seln); /* current scope for se */
527  const char* mn = module_name(sen);
528 
529  if(same_string_p(mn, cmn)) {
530  renaming_p = true;
531  int cs_se_l = strlen(cs_se);
532  if(cs_se_l>0 && cs_se_l<csl) {
533  csl = cs_se_l;
534  cs = cs_se;
535  }
536  else {
537  free(cs_se);
538  }
539  }
540  else {
541  free(cs_se);
542  }
543  }
544  if (renaming_p) {
545  compute_renamings(s, cs, cmn, renamings);
546  // FC: 2014-12-20 kludge to avoid a coredump
547  if (cs != string_undefined) {
548  free(cs);
549  cs = string_undefined;
550  }
551  }
552 
553  if(renaming_p) {
554  ifdebug(1)
555  hash_table_fprintf(stderr,
556  // The warning will disappear when Fabien
557  // updates Newgen
558  //(char * (*)(void *)) entity_local_name,
559  //(char * (*)(void *)) entity_local_name,
562  renamings);
563 
564  //char *(*key_to_string)(void*),
565  //char *(*value_to_string)(void*),
566 
568  statement_instruction(s), renamings,
572  NULL);
573 
574  // This look like a bad hack, partially redundant with previous
575  // replacement but... only partially ! For instance extensions was not
576  // handled previously.
577  // Probably that there's need for factoring, but it'll be another time !
578  replace_entities(s,renamings);
579 
580  gen_free_list(declarations), declarations = NIL;
581  hash_table_free(renamings), renamings = NULL;
582  }
583  else {
584  pips_debug(2,"Code flattening fails because the statement does"
585  " not contain any local declaration\n");
586  }
587  }
588  return true;
589 }
590 
592 
593  if (statement_loop_p(s)) {
594  loop l = statement_loop(s);
595 
597  full_loop_unroll(s);
598  }
599 }
600 
602 {
605 
606  FOREACH(ENTITY,e,decls)
607  {
608  bool decl_stat_found = false;
610  {
611  if(( decl_stat_found = ( declaration_statement_p(s) && !gen_chunk_undefined_p(gen_find_eq(e,statement_declarations(s))) ) ) )
612  break;
613  }
614  if(!decl_stat_found)
616  }
617  gen_free_list(decls);
618 }
619 
621 {
623 }
624 
625 
626 /* Pipsmake 'flatten_code' phase.
627 
628  This function is be composed of several steps:
629 
630  1 flatten declarations inside statement: declarations are moved as
631  high as possible in the control structure; this may serialize
632  parallel loops, but this pass was designed for sequential code.
633 
634  2 clean_up_sequences: remove useless braces when they are nested.
635 
636  3 unroll looops with statically known iteration number.
637 
638  4 clean_up_sequences: remove useless braces when they are nested.
639 
640  It is assumed that the function main statement will contain at
641  least one local variable. This is used to preserve the scoping
642  mechanism used by the parser. Thus, "void foo(void){{{}}}" cannot
643  be flatten. Note that clean_up_sequences could be used first to
644  avoid such cases. Function "void foo(void){{{extern int i;}}}"
645  cannot be flatten either, but clean_up_sequences might help.
646 
647  */
648 bool flatten_code(const string module_name)
649 {
650  bool good_result_p = true;
651 
655  code c = value_code(mv); // No check on value's kind
656  list dl = code_declarations(c);
657 
658  debug_on("FLATTEN_CODE_DEBUG_LEVEL");
659  pips_debug(1, "begin\n");
660 
661  // Step 0: the algorithms used do not deal with dependent or
662  // variable-length array (VLA) types unless they are formal parameters
663  // or appear at top-level... (see TRAC ticket 751)
664  // Declarations are moved to the top, without any regard to data dependencies
665  FOREACH(ENTITY, v, dl) {
666  if(!entity_formal_p(v)) {
667  type t = entity_type(v);
668  if(dependent_type_p(t)) {
669  string eln = (string) entity_local_name(v);
670  string s = local_name_to_scope(eln);
671  /* Is it a top-level entity? */
672  if(strlen(s)>2) {
673  good_result_p = false;
674  break;
675  }
676  else {
677  pips_user_warning("Code generated by pass Flatten_code may be wrong"
678  " because of VLA type of variable \"%s\"\n",
679  entity_user_name(v));
680  }
681  }
682  }
683  }
684 
685  if(!good_result_p) {
686  pips_user_warning("Module \"%s\" could not be flattened because it uses a variable-length array (VLA).\n", entity_user_name(module));
687  }
688  else {
690  db_get_memory_resource(DBR_CODE, module_name, true) );
691  statement module_stat = get_current_module_statement();
692 
693  // Step 1 and 2: flatten declarations and clean up sequences
694  if ((good_result_p=statement_flatten_declarations(module,module_stat)))
695  {
696  statement_purge_declarations(module_stat);
697  // call sequence flattening as some declarations may have been moved up
698  clean_up_sequences(module_stat);
699 
700  // Step 3 and 4: unroll loops and clean up sequences
701  if(get_bool_property("FLATTEN_CODE_UNROLL"))
702  {
703  gen_recurse(module_stat,
705  clean_up_sequences(module_stat); // again
706  }
707 
708  // This might not be necessary, thanks to clean_up_sequences
709  module_reorder(module_stat);
710  // Save modified code to database
711  DB_PUT_MEMORY_RESOURCE(DBR_CODE, strdup(module_name), module_stat);
712  }
714  }
715 
716  pips_debug(1, "end\n");
717  debug_off();
718 
720 
721  return good_result_p;
722 }
723 
724 ␌
725 /* Recurse through the statements of s and split local declarations.
726  For the time being, we handle only blocks with declarations.
727 
728  NOTE: Statement s is modified in-place.
729 
730  This function can be called from another module to apply
731  transformation directly.
732 */
734 {
736  /* Is it still useful? */
738 }
739 
740 /* Pipsmake 'split_initializations' phase
741  */
743 {
744  statement module_stat;
745  bool good_result_p = true;
746 
749  db_get_memory_resource(DBR_CODE, module_name, true) );
750  module_stat = get_current_module_statement();
751 
752  debug_on("SPLIT_INITIALIZATIONS_DEBUG_LEVEL");
753  pips_debug(1, "begin\n");
754 
755  // Do split !
756  statement_split_initializations(module_stat);
757 
758  pips_debug(1, "end\n");
759  debug_off();
760 
761  /* Save modified code to database */
762  module_reorder(module_stat);
763  DB_PUT_MEMORY_RESOURCE(DBR_CODE, strdup(module_name), module_stat);
764 
767 
768  return (good_result_p);
769 }
770 
771 
773 {
774  entity op = call_function(c);
775  list args = call_arguments(c);
777  if(!entity_undefined_p(new_op))
778  {
779  if(ENTITY_PLUS_C_P(new_op)||ENTITY_MINUS_C_P(new_op))
780  {
781  bool has_pointer =false;
783  {
785  if(basic_pointer_p(b)) { has_pointer=true;}
786  free_basic(b);
787  }
788  if(!has_pointer) {
791  }
792  }
793  ifdebug(1){
795  pips_debug(1,"changed expression \n");
796  print_expression(tmp);
798  free_expression(tmp);
799  }
800 
802  expression lhs = binary_call_lhs(c);
803  expression rhs = binary_call_rhs(c);
804  CAR(CDR(args)).p=(gen_chunkp)MakeBinaryCall(
805  new_op,
806  copy_expression(lhs),
807  rhs);
808 
809  ifdebug(1){
811  pips_debug(1,"into expression \n");
812  print_expression(tmp);
814  free_expression(tmp);
815  }
816  }
817 }
818 
819 static void
821 {
822  /* FI: this should be guarded by a declaration_statement_p(s),
823  shouldn't it? */
824  if(declaration_statement_p(s)) {
826  {
827  value v = entity_initial(e);
828  if( !value_undefined_p(v) && value_expression_p( v ) )
830  }
831  }
832 }
833 
835 {
838  debug_on("SPLIT_UPDATE_OPERATOR_DEBUG_LEVEL");
839  pips_debug(1, "begin\n");
840 
844  NULL);
845 
846  pips_debug(1, "end\n");
847  debug_off();
848 
849  /* Save modified code to database */
851 
854  return true;
855 }
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
instruction make_instruction_sequence(sequence _field_)
Definition: ri.c:1169
void free_expression(expression p)
Definition: ri.c:853
void free_basic(basic p)
Definition: ri.c:107
sequence make_sequence(list a)
Definition: ri.c:2125
struct _newgen_struct_entity_ * entity
Definition: abc_private.h:14
struct _newgen_struct_expression_ * expression
Definition: alias_private.h:21
bool entity_is_argument_p(entity e, cons *args)
Definition: arguments.c:150
bool clean_up_sequences(statement s)
Recursively clean up the statement sequences by fusing them if possible and by removing useless one.
struct _newgen_struct_statement_ * statement
Definition: cloning.h:21
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....
static void statement_purge_declarations_walker(sequence seq)
Definition: flatten_code.c:601
static void split_update_operator_statement_walker(statement s)
Definition: flatten_code.c:820
static void rename_loop_index(loop l, hash_table renamings)
gen_multi_recurse callback on exiting a loop: if loop index needs renaming, rename this occurrence.
Definition: flatten_code.c:90
struct redeclaration_context redeclaration_context_t
To generate the new variables, we need to know:
void statement_split_initializations(statement s)
Recurse through the statements of s and split local declarations.
Definition: flatten_code.c:733
bool split_initializations(const char *module_name)
Pipsmake 'split_initializations' phase.
Definition: flatten_code.c:742
void split_update_call(call c)
Definition: flatten_code.c:772
bool statement_flatten_declarations(entity module, statement s)
flatten_code.c
Definition: flatten_code.c:509
static void statement_purge_declarations(statement s)
Definition: flatten_code.c:620
static void unroll_loops_in_statement(statement s)
Definition: flatten_code.c:591
static void rename_statement_declarations(statement s, hash_table renamings)
gen_multi_recurse callback on exiting a statement: recompute the declaration list for statement s and...
Definition: flatten_code.c:137
static void compute_renamings(statement s, const char *sc, const char *mn, hash_table renamings)
FI: added to wrap up the use of redeclaration context...
Definition: flatten_code.c:461
static void redeclaration_exit_statement(statement s, redeclaration_context_t *rdcp)
Keep track of cycle exit in the hierarchical control flow graph.
Definition: flatten_code.c:447
bool split_update_operator(const char *module_name)
Definition: flatten_code.c:834
static bool redeclaration_enter_statement(statement s, redeclaration_context_t *rdcp)
This function makes the key decision about the renaming: should the variable be renamed?...
Definition: flatten_code.c:275
static void rename_variable_type(entity var, hash_table renamings)
If the type of variable var is a typedefed type, it may have been renamed and the symbol table must b...
Definition: flatten_code.c:110
bool flatten_code(const string module_name)
Pipsmake 'flatten_code' phase.
Definition: flatten_code.c:648
static void rename_reference(reference r, hash_table renamings)
Flatten code.
Definition: flatten_code.c:55
#define gen_chunk_undefined_p(c)
Definition: genC.h:75
#define gen_context_recurse(start, ctxt, domain_number, flt, rwt)
Definition: genC.h:285
#define gen_recurse(start, domain_number, flt, rwt)
Definition: genC.h:283
union gen_chunk * gen_chunkp
void free(void *)
statement instruction_to_statement(instruction)
Build a statement from a give instruction.
Definition: statement.c:597
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
statement get_current_module_statement(void)
Get the current module statement.
Definition: static.c:208
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
void replace_entities(void *s, hash_table ht)
Recursively substitute a set of entities in a statement.
Definition: replace.c:91
void gen_multi_recurse(void *o,...)
Multi recursion visitor function.
Definition: genClib.c:3428
void gen_context_multi_recurse(void *o, void *context,...)
Multi-recursion with context function visitor.
Definition: genClib.c:3373
gen_chunk * gen_get_ancestor(int, const void *)
return the first ancestor object found of the given type.
Definition: genClib.c:3560
bool gen_true2(__attribute__((unused)) gen_chunk *u1, __attribute__((unused)) void *u2)
Definition: genClib.c:2785
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
void gen_remove_once(list *pl, const void *o)
Remove the first occurence of o in list pl:
Definition: list.c:691
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
list gen_copy_seq(list l)
Copy a list structure.
Definition: list.c:501
#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
void * gen_find_eq(const void *item, const list seq)
Definition: list.c:422
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
loop statement_loop(statement)
Get the loop of a statement.
Definition: statement.c:1374
bool statement_loop_p(statement)
Definition: statement.c:349
statement make_assign_statement(expression, expression)
Definition: statement.c:583
list statement_to_referenced_entities(statement)
Get a list of all variables referenced recursively within a statement:
Definition: statement.c:3428
list instruction_to_declarations(instruction)
Get a list of all variables declared recursively within an instruction.
Definition: statement.c:3279
bool statement_with_empty_comment_p(statement)
Return true if the statement has an empty statement:
Definition: statement.c:126
bool declaration_statement_p(statement)
Had to be optimized according to Beatrice Creusillet.
Definition: statement.c:224
void hash_table_fprintf(FILE *f, gen_string_func_t key_to_string, gen_string_func_t value_to_string, const hash_table htp)
This function prints the content of the hash_table pointed to by htp on file descriptor f,...
Definition: hash.c:548
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_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
bool loop_fully_unrollable_p(loop l)
Definition: loop_unroll.c:753
void full_loop_unroll(statement loop_statement)
get rid of the loop by body replication;
Definition: loop_unroll.c:788
#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_internal_error
Definition: misc-local.h:149
#define debug_off()
Definition: misc-local.h:160
#define BLOCK_SEP_CHAR
Definition: naming-local.h:51
#define MODULE_SEP_CHAR
Definition: naming-local.h:28
#define MODULE_SEP_STRING
Definition: naming-local.h:30
string concatenate(const char *,...)
Return the concatenation of the given strings.
Definition: string.c:183
@ hash_pointer
Definition: newgen_hash.h:32
#define hash_put_or_update(h, k, v)
Definition: newgen_hash.h:80
#define HASH_DEFAULT_SIZE
Definition: newgen_hash.h:26
#define same_string_p(s1, s2)
string(* gen_string_func_t)(const void *)
Definition: newgen_types.h:111
#define string_undefined
Definition: newgen_types.h:40
char * string
STRING.
Definition: newgen_types.h:39
void unnormalize_expression(void *st)
void unnormalize_expression(expression exp): puts all the normalized field of expressions in "st" to ...
Definition: normalize.c:452
static char * module
Definition: pips.c:74
void print_expression(expression e)
no file descriptor is passed to make is easier to use in a debugging stage.
Definition: expression.c:58
void print_statements(list)
Definition: statement.c:103
bool module_reorder(statement body)
Reorder a module and recompute order to statement if any.
Definition: reorder.c:244
#define binary_call_rhs(c)
#define MINUS_OPERATOR_NAME
#define PLUS_OPERATOR_NAME
#define statement_block_p(stat)
#define STATEMENT_NUMBER_UNDEFINED
default values
#define entity_declarations(e)
MISC: newgen shorthands.
#define ENTITY_PLUS_C_P(e)
#define ENTITY_MINUS_C_P(e)
#define binary_call_lhs(c)
#define ASSIGN_OPERATOR_NAME
Definition: ri-util-local.h:95
void split_initializations_in_statement(statement s)
Transform a declaration with an initialization statement into 2 parts, a declaration statement and an...
Definition: declarations.c:437
const char * entity_user_name(entity e)
Since entity_local_name may contain PIPS special characters such as prefixes (label,...
Definition: entity.c:487
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 entity_formal_p(entity p)
is p a formal parameter?
Definition: entity.c:1935
entity update_operator_to_regular_operator(entity op)
Returns the binary operator associated to a C update operator such as +=.
Definition: entity.c:2154
entity module_name_to_entity(const char *mn)
This is an alias for local_name_to_top_level_entity.
Definition: entity.c:1479
string local_name_to_scope(const char *ln)
allocates a new string
Definition: entity.c:563
void print_entities(list l)
Definition: entity.c:167
entity entity_intrinsic(const char *name)
FI: I do not understand this function name (see next one!).
Definition: entity.c:1292
entity make_entity_copy_with_new_name(entity e, string global_new_name, bool move_initialization_p)
Create a copy of an entity, with (almost) identical type, storage and initial value if move_initializ...
Definition: entity.c:2463
bool expression_is_C_rhs_p(expression exp)
Not all expressions can be used as right-hand side (rhs) in C assignments.
Definition: expression.c:2582
expression entity_to_expression(entity e)
if v is a constant, returns a constant call.
Definition: expression.c:165
expression MakeBinaryCall(entity f, expression eg, expression ed)
Creates a call expression to a function with 2 arguments.
Definition: expression.c:354
bool extended_expression_constant_p(expression exp)
Returns true if the value of the expression does not depend syntactically on the current store.
Definition: expression.c:2461
expression call_to_expression(call c)
Build an expression that call a function or procedure.
Definition: expression.c:309
basic basic_of_expression(expression)
basic basic_of_expression(expression exp): Makes a basic of the same basic as the expression "exp".
Definition: type.c:1383
bool dependent_type_p(type)
A type is dependent in many ways according to definitions given in Wikipedia.
Definition: type.c:5849
bool entity_static_variable_p(entity)
return true if the entity is declared with the keyword static
Definition: variable.c:1146
void AddLocalEntityToDeclarations(entity, entity, statement)
Add the variable entity e to the list of variables of the function module.
Definition: variable.c:233
bool enum_type_p(type)
Returns true if t is of type derived and if the derived type is a enum.
Definition: type.c:3172
void RemoveLocalEntityFromDeclarations(entity, entity, statement)
Definition: variable.c:120
bool union_type_p(type)
Returns true if t is of type derived and if the derived type is a union.
Definition: type.c:3151
expression variable_initial_expression(entity)
Returns a copy of the initial (i.e.
Definition: variable.c:1899
bool struct_type_p(type)
Returns true if t is of type derived and if the derived type is a struct.
Definition: type.c:3121
bool typedef_type_p(type)
Returns true if t is a typedefED type.
Definition: type.c:3189
bool variable_static_p(entity)
true if v appears in a SAVE statement, or in a DATA statement, or is declared static i C.
Definition: variable.c:1579
#define value_undefined_p(x)
Definition: ri.h:3017
#define execution_tag(x)
Definition: ri.h:1207
#define expression_domain
newgen_execution_domain_defined
Definition: ri.h:154
#define instruction_sequence_p(x)
Definition: ri.h:1512
#define loop_execution(x)
Definition: ri.h:1648
#define instruction_loop_p(x)
Definition: ri.h:1518
#define call_function(x)
Definition: ri.h:709
#define reference_variable(x)
Definition: ri.h:2326
#define loop_domain
newgen_language_domain_defined
Definition: ri.h:218
#define basic_derived(x)
Definition: ri.h:640
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define value_unknown_p(x)
Definition: ri.h:3077
#define type_variable(x)
Definition: ri.h:2949
#define basic_pointer_p(x)
Definition: ri.h:635
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
#define code_declarations(x)
Definition: ri.h:784
#define call_domain
newgen_callees_domain_defined
Definition: ri.h:58
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define basic_typedef(x)
Definition: ri.h:643
#define instruction_forloop_p(x)
Definition: ri.h:1536
#define entity_undefined_p(x)
Definition: ri.h:2762
#define reference_domain
newgen_range_domain_defined
Definition: ri.h:338
#define entity_undefined
Definition: ri.h:2761
#define entity_name(x)
Definition: ri.h:2790
#define sequence_statements(x)
Definition: ri.h:2360
#define value_code(x)
Definition: ri.h:3067
#define syntax_call(x)
Definition: ri.h:2736
#define instruction_unstructured_p(x)
Definition: ri.h:1530
#define expression_undefined_p(x)
Definition: ri.h:1224
#define statement_declarations(x)
Definition: ri.h:2460
#define statement_instruction(x)
Definition: ri.h:2458
#define statement_comments(x)
Definition: ri.h:2456
#define instruction_whileloop_p(x)
Definition: ri.h:1521
@ is_execution_sequential
Definition: ri.h:1189
#define call_arguments(x)
Definition: ri.h:711
#define entity_type(x)
Definition: ri.h:2792
#define call_undefined
Definition: ri.h:685
#define statement_number(x)
Definition: ri.h:2452
#define value_expression_p(x)
Definition: ri.h:3080
#define expression_syntax(x)
Definition: ri.h:1247
#define sequence_domain
newgen_reference_domain_defined
Definition: ri.h:346
#define execution_parallel_p(x)
Definition: ri.h:1211
#define loop_index(x)
Definition: ri.h:1640
#define variable_basic(x)
Definition: ri.h:3120
#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
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
To generate the new variables, we need to know:
Definition: flatten_code.c:263
const char * module_name
Definition: flatten_code.c:267
statement declaration_statement
Definition: flatten_code.c:265
#define exp
Avoid some warnings from "gcc -Wshadow".
Definition: vasnprintf.c:207