PIPS
clean_up_sequences.c
Go to the documentation of this file.
1 /*
2  $Id: clean_up_sequences.c 23495 2018-10-24 09:19:47Z coelho $
3 
4  Copyright 1989-2016 MINES ParisTech
5 
6  This file is part of PIPS.
7 
8  PIPS is free software: you can redistribute it and/or modify it
9  under the terms of the GNU General Public License as published by
10  the Free Software Foundation, either version 3 of the License, or
11  any later version.
12 
13  PIPS is distributed in the hope that it will be useful, but WITHOUT ANY
14  WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  FITNESS FOR A PARTICULAR PURPOSE.
16 
17  See the GNU General Public License for more details.
18 
19  You should have received a copy of the GNU General Public License
20  along with PIPS. If not, see <http://www.gnu.org/licenses/>.
21 
22 */
23 #ifdef HAVE_CONFIG_H
24 #include "pips_config.h"
25 #endif
26 
27 /* Clean up the sequences and their contents by fusing them or
28  removing useless continues or empty instructions.
29  Ronan Keryell
30 */
31 
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 
36 #include "linear.h"
37 
38 #include "genC.h"
39 #include "ri.h"
40 #include "ri-util.h"
41 #include "properties.h"
42 #include "misc.h"
43 
44 
45 /* To store the statistics: */
46 
50 
52 
53 void
55 {
59 }
60 
61 void
63 {
64  if (get_bool_property("CLEAN_UP_SEQUENCES_DISPLAY_STATISTICS")
65  &&
69  user_log("Statistics about cleaning up sequences:\n");
71  user_log("\t%d empty sequence%s or useless CONTINUE removed.\n",
73  clean_up_empty_block_removed==1? "" : "s");
75  user_log("\t%d %s been fused.\n",
77  clean_up_fused_sequences==1? "sequence has" : "sequences have");
79  user_log("\t%d sequence%s of only 1 statement have been removed.\n",
81  clean_up_1_statement_sequence==1? "" : "s");
82  }
83 }
84 
85 /* Clean up sequences context */
86 
87 
88 // beware: by construction l_ref contains references which may have indices
89 // with references themselves contained in l_ref
90 // these references are all program references and must not be freed
91 typedef struct {
92  list l_ref; // references of the outermost statement
93  list l_loops; // loops of the outermost statement
94  list l_decl; // declarations of the outermost statement
96  bool changed; // whether anything was changed
97 } cusq_context;
98 
99 static bool
101 {
102  p_ctxt->l_ref = CONS(REFERENCE, ref, p_ctxt->l_ref);
103  return true;
104 }
105 
106 static bool
108 {
109  p_ctxt->l_loops = CONS(LOOP, l, p_ctxt->l_loops);
110  return true;
111 }
112 
113 static bool
115 {
116  if (declaration_statement_p(st))
117  {
119  {
120  value init_val = entity_initial(decl);
121  if (! value_undefined_p(init_val))
122  {
123  gen_context_recurse(init_val, p_ctxt,
125  }
126  }
127  }
128  return true;
129 }
130 
131 
132 static void
134 {
136  get_bool_property("CLEAN_UP_SEQUENCES_WITH_DECLARATIONS");
137  p_ctxt->l_ref = NIL;
138  p_ctxt->l_loops = NIL;
139  p_ctxt->l_decl = NIL;
140  p_ctxt->changed = false;
141 
143  {
145  s, p_ctxt,
149  NULL);
150  p_ctxt->l_decl = statement_to_declarations(s);
151  // gen_copy_seq(statement_declarations(s));
152  }
153 
154  ifdebug(1)
155  {
156  pips_debug(1, "outermost declarations:");
157  print_entities(p_ctxt->l_decl);
158  fprintf(stderr, "\n");
159  pips_debug(1, "%s merge sequences with declarations\n",
160  p_ctxt->merge_sequences_with_declarations? "":"do not");
161  }
162 }
163 
164 static void
166 {
167  gen_free_list(p_ctxt->l_loops);
168  p_ctxt->l_loops = NIL;
169 
170  gen_free_list(p_ctxt->l_ref);
171  p_ctxt->l_ref = NIL;
172 
173  gen_free_list(p_ctxt->l_decl);
174  p_ctxt->l_decl = NIL;
175 }
176 
177 /**
178  * replace entities in the module references and loop indices and loop locals
179  * stored in the input cusq_context using the input old/new entities mapping
180  */
181 static void
183 {
184  FOREACH(REFERENCE, ref, p_ctxt->l_ref)
185  {
186  entity new_ent = hash_get(ht, reference_variable(ref));
187  if (new_ent != HASH_UNDEFINED_VALUE)
188  {
189  pips_debug(6, "new entity found: %s \n", entity_name(new_ent));
190  reference_variable(ref) = new_ent;
191  p_ctxt->changed = true;
192  }
193  }
194 
195  FOREACH(LOOP, l, p_ctxt->l_loops)
196  {
197  entity new_index = hash_get(ht, loop_index(l));
198  if (new_index != entity_undefined)
199  {
200  loop_index(l) = new_index;
201  p_ctxt->changed = true;
202  }
203 
204  for(list l_locals = loop_locals(l); !ENDP(l_locals); POP(l_locals))
205  {
206  entity new_local = hash_get(ht, ENTITY(CAR(l_locals)));
207  if (new_local != entity_undefined)
208  {
209  CAR(l_locals).p = (gen_chunkp) new_local;
210  p_ctxt->changed = true;
211  }
212  }
213  }
214 }
215 
216 
217 /* End: clean up sequences context */
218 
219 /* Add a couple (statement -> GOTO) to the map statement_to_goto_table: */
220 bool
222 {
223  if (instruction_goto_p(i))
224  {
226 
227  pips_debug(7, "Adding GOTO from instruction %p to statement %p.\n",
228  i, s);
229 
230  if (!hash_defined_p(statement_to_goto_table, (char *) s)) {
232  (char *) s,
233  (char *) CONS(INSTRUCTION, i, NIL));
234  }
235  else {
237  (char *) s,
238  (char *) CONS(INSTRUCTION,
239  i,
241  (char *) s)));
242  }
243  // There is nothing to recurse into:
244  return false;
245  }
246  return true;
247 }
248 
249 
250 /* Since clean_up_sequences() is called before the controlizer, there
251  may be some GOTO. GOTOs are in fact pointer to the target
252  statement, hence when target statements are moved around, some
253  GOTOs need to be updated. For this purpose, we build a list of
254  GOTOs per target statement.
255 */
256 void
258 {
259  pips_assert("Map statement_to_goto_table should be uninitialized.\n",
260  statement_to_goto_table == NULL);
261 
264 }
265 
266 
267 /* Discard the statement_to_goto_table map: */
268 void
270 {
271  HASH_MAP(k, v, {
272  // Discard every GOTO list:
273  gen_free_list((list) v);
277 }
278 
279 
280 /* Adjust all the GOTOs pointing s1 to s2: */
281 void
283  statement s2)
284 {
285  if (s1 == s2)
286  // Nothing to do:
287  return;
288 
290  {
292  {
293  pips_assert("The GOTO should point to s1.\n",
294  instruction_goto(i) == s1);
295  instruction_goto(i) = s2;
296  pips_debug(6, "Adjusting GOTO from instruction %p -> statement %p to "
297  "statement %p.\n",
298  i, s1, s2);
299  }
300  }
301 }
302 
303 
304 static void
305 deal_with_pending_comment(statement s, string * the_comments)
306 {
307  if (*the_comments != NULL) {
308  /* There is a pending comment to be added on this statement: */
309  insert_comments_to_statement(s, *the_comments);
310  free(*the_comments);
311  *the_comments = NULL;
312  }
313 }
314 
315 /**
316  * change the declarations of declaration statements directly
317  * contained in input sequence according to the input old/new entity mapping
318  *
319  * @param seq is the input sequence
320  * @param renamings is an old/new entity mapping
321  */
322 static bool
324 {
325  bool changed = false;
326 
328  {
330  {
331  list l_decl = statement_declarations(stmt);
332  while (!ENDP(l_decl))
333  {
334  entity decl = ENTITY(CAR(l_decl));
335  entity new_decl = hash_get(renamings, decl);
336  if(new_decl != HASH_UNDEFINED_VALUE) // we have found the old declaration
337  {
338  pips_debug(5, "replacing entity %s by %s\n",
339  entity_name(decl), entity_name(new_decl));
340  CAR(l_decl).p = (gen_chunkp) new_decl;
341  changed = true;
342  hash_del(renamings, decl);
343  }
344  POP(l_decl);
345  }
346  }
347  }
348 
349  return changed;
350 }
351 
352 
353 static void
355 {
357 
358  // nothing to do
359  if (!instruction_sequence_p(i))
360  return;
361 
362  /* Delete empty instruction and fuse blocks of instructions : */
363  list useful_sts, delete_sts;
364  string the_comments = NULL;
365 
366  useful_sts = delete_sts = NIL;
367 
370  && unlabelled_statement_p(s)))
371  {
372  user_log("Statement %s\n"
373  "Number=%d, label=\"%s\", comment=\"%s\"\n",
377  "" : statement_comments(s));
378  pips_internal_error("This block statement should be labelless, numberless"
379  " and commentless.\n");
380  }
381 
382  /*
383  pips_assert("This statement should be labelless, numberless and commentless.",
384  statement_with_empty_comment_p(s)
385  && statement_number(s) == STATEMENT_NUMBER_UNDEFINED
386  && unlabelled_statement_p(s));
387  */
388 
389  pips_debug(3, "A sequence of %zd statements with %zd declarations\n",
392 
393  list l_new_decls = NIL; // newly declared entities if need be.
395 
397  {
399  ifdebug(8)
400  fprintf(stderr, "[ Empty statement or continue ]\n");
401 
403  // Keep the comment to put it on the next useful statement:
404  if (the_comments == NULL)
405  // No comment has been gathered up to now:
406  the_comments = statement_comments(st);
407  else {
408  string nc = statement_comments(st);
409  // FI: apparently, no need to insert a LF between two fused comments.
410  // I suppose that non-empty comments end up with LF
411  string new_comments =
412  strdup(concatenate(the_comments, nc, NULL));
413  free(the_comments);
414  the_comments = new_comments;
415  }
417  }
418  // Unused instructions can be deleted in any order... :-)
419  delete_sts = CONS(STATEMENT, st, delete_sts);
420  pips_debug(3, "Empty block removed...\n");
422  p_ctxt->changed = true;
423  }
424  else
425  {
426  // take care of declarations from the statements directly in the internal sequence
427  list l_internal_proper_decls = statement_to_direct_declarations(st);
428 
429  ifdebug(4){
430  pips_debug(4, "l_internal_proper_decls = \n");
431  print_entities(l_internal_proper_decls);
432  fprintf(stderr, "\n");
433  pips_debug(4, "internal statement declarations");
435  fprintf(stderr, "\n");
436  }
437 
438  if (statement_sequence_p(st)
439  && !empty_statement_p(st)) {
440  // Let fix a special case: an empty sequence with non-empty declarations
441  sequence internal_sequence = statement_sequence(st);
442  list l_stmt_to_be_merged = sequence_statements(internal_sequence);
443  if (ENDP(l_stmt_to_be_merged)) {
444  // If it is not an empty statement, it must contain some declarations.
447  // Now st is an empty statement
448  }
449  }
450 
451  if (statement_sequence_p(st)
452  && !empty_statement_p(st)
453  // The next two tests should be useless
454  // The sequence can be cleaned up even when declarations
455  // and extensions are present
456  // FI: the second part of this test is awful but the
457  // controlizer seems to rely on it... See flatten_code01
458  && ( p_ctxt->merge_sequences_with_declarations ||
459  ENDP(l_internal_proper_decls) || ENDP(statement_declarations(st)))
461 
462  // A sequence with or without declarations in a sequence:
463  // they can be fused:
464  sequence internal_sequence = statement_sequence(st);
465  list l_stmt_to_be_merged = sequence_statements(internal_sequence);
466 
467  if (p_ctxt->merge_sequences_with_declarations &&
468  !ENDP(l_internal_proper_decls))
469  {
471 
472  FOREACH(ENTITY, decl, l_internal_proper_decls)
473  {
474  pips_debug(3, "dealing with declaration: %s\n", entity_name(decl));
475 
476  // check if there is already a variable with the same user name
477  // used in the outermost sequence
478  const char * decl_user_name = entity_user_name(decl);
479  bool parent_decl_with_same_name = false;
480  FOREACH(ENTITY, parent_decl, p_ctxt->l_decl)
481  {
482  // arghh, this is costly, we should at least memoize user_names...
483  if (parent_decl != decl
484  && strcmp(entity_user_name(parent_decl), decl_user_name) == 0)
485  {
486  parent_decl_with_same_name = true;
487  break;
488  }
489  }
490 
491  // find another non-conflicting name and take care of scope
492  bool top_level_entity_with_same_name_p = (FindEntity(TOP_LEVEL_MODULE_NAME, decl_user_name) != entity_undefined);
493  string decl_name = entity_name(decl);
494  string decl_without_module_and_scope = strrchr(decl_name, BLOCK_SEP_CHAR);
495  string new_name = string_undefined;
496  entity new_decl = entity_undefined;
497 
498  pips_debug(6, "decl name without module+scope: %s\n", decl_without_module_and_scope);
499 
500  if (decl_without_module_and_scope == NULL)
501  {
502  // this should generate an error; however, names are sometimes
503  // generated by PIPS phases without scope
504  pips_debug(6, "non consistant variable scope\n");
505  if (top_level_entity_with_same_name_p)
506  new_decl = make_entity_copy_with_new_name_and_suffix(decl, decl_name, true);
507  }
508  else if (decl_without_module_and_scope[-1]=='0' &&
509  decl_without_module_and_scope[-2]== MODULE_SEP_STRING[0])
510  {
511  pips_debug(6, "Entity already at the uppermost scope level\n");
512  if (top_level_entity_with_same_name_p)
513  new_decl = make_entity_copy_with_new_name_and_suffix(decl, decl_name, true);
514  }
515  else
516  {
517  // duplicate the scope, minus the last scope
518  string module_and_new_scope = string_undefined;
519 
520  int i = 2;
521  while (decl_without_module_and_scope[-i] != BLOCK_SEP_CHAR)
522  {
523  if (decl_without_module_and_scope[-i] == MODULE_SEP_STRING[0])
524  pips_internal_error("unexpected MODULE_SEP_STRING, no BLOCK_SEP_CHAR FOUND\n");
525  i++;
526  }
527  if (decl_without_module_and_scope[-i] == BLOCK_SEP_CHAR)
528  module_and_new_scope = strndup(decl_name, decl_without_module_and_scope-decl_name-i+1);
529 
530  pips_debug(6, "module+scope of new decl: %s\n", module_and_new_scope);
531  new_name = strdup(concatenate(module_and_new_scope, decl_user_name, NULL));
532  free(module_and_new_scope);
533 
534  pips_debug(6, "new decl name: %s\n", new_name);
535 
536  if (parent_decl_with_same_name ||
537  top_level_entity_with_same_name_p )
538  new_decl = make_entity_copy_with_new_name_and_suffix(decl, new_name, false);
539  else
540  new_decl = make_entity_copy_with_new_name(decl, new_name, false);
541 
542  // We have to keep the original initial value, because it contains references
543  // which have been gathered in p_ctxt->l_decl and which may have to be renamed.
544  if (!value_undefined_p(entity_initial(decl)))
545  {
546  entity_initial(new_decl) = entity_initial(decl);
548  }
549 
550  pips_debug(3, "new declaration: %s\n", entity_name(new_decl));
551  // add the correspondance for further actual renaming
552  hash_put(renamings, decl, new_decl);
553  l_new_decls = CONS(ENTITY, new_decl, l_new_decls);
554  }
555 
556  if (!entity_undefined_p(new_decl))
557  {
558  // after the merge, the new entity is used in the outermost statement:
559  p_ctxt->l_decl = CONS(ENTITY, new_decl, p_ctxt->l_decl);
560  // the old entity is not used anymore in the module,
561  // in the current statement and in the outermost statement
564  gen_remove(&p_ctxt->l_decl, decl);
565  p_ctxt->changed = true;
566  }
567  } // FOREACH(ENTITY, decl, l_internal_proper_decls)
568 
569  // replace the old entity by the new one in the references of the
570  // outermost statement as well as the loop indices and loop locals
571  // ! does not change the declarations themselves
572  replace_entities_in_cusq_context(p_ctxt, renamings);
573  // change the declarations in place with new names
574  p_ctxt->changed |=
575  sequence_proper_declarations_rename_in_place(internal_sequence, renamings);
576  hash_table_free(renamings);
577  } // if (p_ctxt->merge_sequences_with_declarations && !ENDP(l_internal_proper_decls))
578 
579  statement first = STATEMENT(CAR(l_stmt_to_be_merged));
580  // Unlink the innermost sequence:
581  sequence_statements(internal_sequence) = NIL;
582  // Keep the sequence:
583  useful_sts = gen_nconc(useful_sts, l_stmt_to_be_merged);
584 
585  pips_debug(3, "2 nested sequences fused...\n");
587  p_ctxt->changed = true;
588  // Think to delete the sequence parent:
589  delete_sts = CONS(STATEMENT, st, delete_sts);
590  // To deal with a pending comment:
591  st = first;
592 
593  } // if (statement_sequence_p(st) && !empty_statement_p(st)...)
594  else {
595  // By default, it should be useful:
596  useful_sts = gen_nconc(useful_sts, CONS(STATEMENT, st, NIL));
597  pips_debug(4, "Statement useful... %zd\n",
598  gen_length(useful_sts));
599  }
600  if (the_comments != NULL) p_ctxt->changed = true;
601  deal_with_pending_comment(st, &the_comments);
602  // free the spine of the list of internal declarations
603  gen_free_list(l_internal_proper_decls);
604  }
605  } // FOREACH(STATEMENT, st, sequence_statements(instruction_sequence(i)))
606 
607  /* Remove the list of unused statements with the
608  statements themselves: */
609  gen_full_free_list(delete_sts);
610 
611  if (the_comments != NULL /* || !ENDP(statement_declarations(s))*/) {
612  /* We have a pending comment we were not able to
613  attach. Create a continue statement to attach it: */
615  deal_with_pending_comment(st, &the_comments);
616  useful_sts = gen_nconc(useful_sts,
617  CONS(STATEMENT, st, NIL));
618  pips_debug(3, "CONTINUE created to add a pending comment...\n");
619  }
620 
621  /* Keep track of declarations within an empty sequence:
622  see C_syntax/block01.c */
623  /*
624  if(ENDP(useful_sts) && !ENDP(statement_declarations(s))) {
625  useful_sts = CONS(STATEMENT, s, NIL); // FI: maybe I should copy s?
626  }
627  */
628 
629  // Remove the old list of statements without the statements:
631  sequence_statements(instruction_sequence(i)) = useful_sts;
632 
633  // for consistency: add new entities to module and current_statement declarations
635  {
636  FOREACH(entity, decl, l_new_decls)
637  {
638  pips_debug(3, "adding new declaration for %s\n", entity_name(decl));
640  p_ctxt->changed = true;
641  }
642  }
643 
644  if (gen_length(useful_sts) == 1
647  /* A sequence of only 1 instruction can be replaced by
648  this instruction, if it has not declarations */
649  statement st = STATEMENT(CAR(useful_sts));
650  // Transfer the deeper statement in the current one:
662  /* Do not forget to adjust the GOTOs pointing on st: */
663  adjust_goto_from_to(st, s);
664  /* Discard the old statement: */
665  free_instruction(i);
666  pips_debug(3, "Sequence with 1 statement replaced by 1 statement...\n");
668  p_ctxt->changed = true;
669  }
670 }
671 
672 
673 /* An entry point for internal usage, such as from
674  take_out_the_exit_node_if_not_a_continue(): */
675 bool
677 {
678  debug_on("CLEAN_UP_SEQUENCES_DEBUG_LEVEL");
679 
681 
682  cusq_context ctxt;
683  cusq_ctxt_init(s, &ctxt);
684 
685  gen_context_recurse(s, &ctxt,
687 
688  cusq_ctxt_reset(&ctxt);
690 
691  ifdebug(1) {
693  }
694  debug_off();
695 
696  return ctxt.changed;
697 }
698 
699 
700 /* Recursively clean up the statement sequences by fusing them if possible
701  and by removing useless one. Remove also empty blocs and useless
702  continues. */
703 bool
705 {
706 
707  debug_on("CLEAN_UP_SEQUENCES_DEBUG_LEVEL");
709 
710  bool changed = clean_up_sequences_internal(s);
711 
713  debug_off();
714 
715  return changed;
716 }
void user_log(const char *format,...)
Definition: message.c:234
value make_value_unknown(void)
Definition: ri.c:2847
bool statement_consistent_p(statement p)
Definition: ri.c:2195
void free_instruction(instruction p)
Definition: ri.c:1118
static reference ref
Current stmt (an integer)
Definition: adg_read_paf.c:163
static bool store_declarations_references(statement st, cusq_context *p_ctxt)
bool clean_up_sequences_internal(statement s)
An entry point for internal usage, such as from take_out_the_exit_node_if_not_a_continue():
static void clean_up_sequences_rewrite(statement s, cusq_context *p_ctxt)
hash_table statement_to_goto_table
clean_up_sequences.c
void initialize_clean_up_sequences_statistics(void)
void compute_statement_to_goto_table(statement s)
Since clean_up_sequences() is called before the controlizer, there may be some GOTO.
static void deal_with_pending_comment(statement s, string *the_comments)
void discard_statement_to_goto_table(void)
Discard the statement_to_goto_table map:
static void cusq_ctxt_reset(cusq_context *p_ctxt)
static bool store_reference(reference ref, cusq_context *p_ctxt)
static int clean_up_fused_sequences
static bool sequence_proper_declarations_rename_in_place(sequence seq, hash_table renamings)
change the declarations of declaration statements directly contained in input sequence according to t...
void adjust_goto_from_to(statement s1, statement s2)
Adjust all the GOTOs pointing s1 to s2:
bool clean_up_sequences(statement s)
Recursively clean up the statement sequences by fusing them if possible and by removing useless one.
static void replace_entities_in_cusq_context(cusq_context *p_ctxt, hash_table ht)
replace entities in the module references and loop indices and loop locals stored in the input cusq_c...
void display_clean_up_sequences_statistics(void)
bool statement_to_goto_table_flt(instruction i)
End: clean up sequences context.
static bool store_loops(loop l, cusq_context *p_ctxt)
static int clean_up_1_statement_sequence
static int clean_up_empty_block_removed
Clean up the sequences and their contents by fusing them or removing useless continues or empty instr...
static void cusq_ctxt_init(statement s, cusq_context *p_ctxt)
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
#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 gen_full_free_list(list l)
Definition: genClib.c:1023
void free(void *)
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
void gen_context_multi_recurse(void *o, void *context,...)
Multi-recursion with context function visitor.
Definition: genClib.c:3373
void gen_null2(__attribute__((unused)) void *u1, __attribute__((unused)) void *u2)
idem with 2 args, to please overpeaky compiler checks
Definition: genClib.c:2758
bool gen_true2(__attribute__((unused)) gen_chunk *u1, __attribute__((unused)) void *u2)
Definition: genClib.c:2785
void gen_null(__attribute__((unused)) void *unused)
Ignore the argument.
Definition: genClib.c:2752
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
void gen_remove(list *cpp, const void *o)
remove all occurences of item o from list *cpp, which is thus modified.
Definition: list.c:685
#define POP(l)
Modify a list pointer to point on the next element of the list.
Definition: newgen_list.h:59
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
size_t gen_length(const list l)
Definition: list.c:150
#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
sequence statement_sequence(statement)
Get the sequence of a statement sequence.
Definition: statement.c:1328
bool empty_statement_or_labelless_continue_p(statement)
Return true if the statement is an empty instruction block without label or a continue without label ...
Definition: statement.c:446
bool unlabelled_statement_p(statement)
Definition: statement.c:402
bool empty_statement_p(statement)
Test if a statement is empty.
Definition: statement.c:391
bool statement_sequence_p(statement)
Statement classes induced from instruction type.
Definition: statement.c:335
void insert_comments_to_statement(statement, const char *)
Insert a comment string (if non empty) at the beginning of the comments of a statement.
Definition: statement.c:1916
string statement_identification(statement)
Like external_statement_identification(), but with internal information, the hexadecimal address of t...
Definition: statement.c:1700
list statement_to_declarations(void *)
Get a list of all variables declared recursively within a statement.
Definition: statement.c:3253
list statement_to_direct_declarations(statement)
Returns the declarations contained directly in a statement s.
Definition: statement.c:3366
bool empty_comments_p(const char *)
Definition: statement.c:107
bool statement_with_empty_comment_p(statement)
Return true if the statement has an empty statement:
Definition: statement.c:126
statement make_plain_continue_statement(void)
Make a simple continue statement to be used as a NOP or ";" in C.
Definition: statement.c:964
bool declaration_statement_p(statement)
Had to be optimized according to Beatrice Creusillet.
Definition: statement.c:224
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_update(hash_table htp, const void *key, const void *val)
update key->val in htp, that MUST be pre-existent.
Definition: hash.c:491
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
void * hash_del(hash_table htp, const void *key)
this function removes from the hash table pointed to by htp the couple whose key is equal to key.
Definition: hash.c:439
#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_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#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 TOP_LEVEL_MODULE_NAME
Module containing the global variables in Fortran and C.
Definition: naming-local.h:101
#define MODULE_SEP_STRING
Definition: naming-local.h:30
string concatenate(const char *,...)
Return the concatenation of the given strings.
Definition: string.c:183
#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
#define HASH_DEFAULT_SIZE
Definition: newgen_hash.h:26
#define string_undefined
Definition: newgen_types.h:40
static char * module
Definition: pips.c:74
#define STATEMENT_NUMBER_UNDEFINED
default values
#define entity_declarations(e)
MISC: newgen shorthands.
const char * entity_user_name(entity e)
Since entity_local_name may contain PIPS special characters such as prefixes (label,...
Definition: entity.c:487
entity FindEntity(const char *package, const char *name)
Retrieve an entity from its package/module name and its local name.
Definition: entity.c:1503
entity make_entity_copy_with_new_name_and_suffix(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:2495
void print_entities(list l)
Definition: entity.c:167
const char * label_local_name(entity e)
END_EOLE.
Definition: entity.c:604
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
void AddLocalEntityToDeclarationsOnly(entity, entity, statement)
Add the variable entity e to the list of variables of the function module.
Definition: variable.c:253
#define extensions_undefined
Definition: ri.h:1308
#define value_undefined_p(x)
Definition: ri.h:3017
#define LOOP(x)
LOOP.
Definition: ri.h:1606
#define REFERENCE(x)
REFERENCE.
Definition: ri.h:2296
#define instruction_sequence_p(x)
Definition: ri.h:1512
#define reference_variable(x)
Definition: ri.h:2326
#define loop_domain
newgen_language_domain_defined
Definition: ri.h:218
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define INSTRUCTION(x)
INSTRUCTION.
Definition: ri.h:1448
#define instruction_goto(x)
Definition: ri.h:1526
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
#define instruction_domain
newgen_functional_domain_defined
Definition: ri.h:202
#define instruction_undefined
Definition: ri.h:1454
#define statement_label(x)
Definition: ri.h:2450
#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 statement_extensions(x)
Definition: ri.h:2464
#define instruction_sequence(x)
Definition: ri.h:1514
#define loop_locals(x)
Definition: ri.h:1650
#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 extensions_extension(x)
Definition: ri.h:1330
#define statement_number(x)
Definition: ri.h:2452
#define instruction_goto_p(x)
Definition: ri.h:1524
#define loop_index(x)
Definition: ri.h:1640
#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()
s1
Definition: set.c:247
#define ifdebug(n)
Definition: sg.c:47
char * strndup(char const *s, size_t n)
A replacement function, for systems that lack strndup.
Definition: strndup.c:26
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
Clean up sequences context.
bool merge_sequences_with_declarations
Definition: statement.c:54