PIPS
controlizer.c
Go to the documentation of this file.
1 /* There are some TODO !!! RK
2 
3  */
4 
5 
6 
7 
8 
9 
10 
11 
12 /*
13 
14  $Id: controlizer.c 23065 2016-03-02 09:05:50Z coelho $
15 
16  Copyright 1989-2016 MINES ParisTech
17 
18  This file is part of PIPS.
19 
20  PIPS is free software: you can redistribute it and/or modify it
21  under the terms of the GNU General Public License as published by
22  the Free Software Foundation, either version 3 of the License, or
23  any later version.
24 
25  PIPS is distributed in the hope that it will be useful, but WITHOUT ANY
26  WARRANTY; without even the implied warranty of MERCHANTABILITY or
27  FITNESS FOR A PARTICULAR PURPOSE.
28 
29  See the GNU General Public License for more details.
30 
31  You should have received a copy of the GNU General Public License
32  along with PIPS. If not, see <http://www.gnu.org/licenses/>.
33 
34 */
35 #ifdef HAVE_CONFIG_H
36  #include "pips_config.h"
37 #endif
38 
39 #ifndef lint
40 char vcid_control_controlizer[] = "$Id: controlizer.c 23065 2016-03-02 09:05:50Z coelho $";
41 #endif /* lint */
42 
43 /* \defgroup controlizer Controlizer phase to build the Hierarchical Control Flow Graph
44 
45  It computes the Hierarchical Control Flow Graph of a given statement
46  according the control hierarchy.
47 
48  It is used in PIPS to transform the output of the parsers (the
49  PARSED_CODE resource) into HCFG code (the CODE resource).
50 
51  For example if there are some "goto" in a program, it will encapsulate
52  the unstructured graph into an "unstructured" object covering all the
53  gotos and their label targets to localize the messy part. Then this object
54  is put into a normal statement so that, seen from above, the code keep a
55  good hierarchy.
56 
57  In PIPS the RI (Internal Representation or AST) is quite simple so that
58  it is easy to deal with. But the counterpart is that some complex
59  control structures need to be "unsugared". For example
60  switch/case/break/default are transformed into tests, goto and label,
61  for(;;) with break or continue are transformed into while() loops with
62  goto/label, and so on. It is up to the prettyprinter to recover the
63  high level construction if needed (...and possible).
64 
65  In the case of C, it is far more complicated than with Fortran77 that
66  was targeted by PIPS at the beginning because we need to deal with
67  variable scoping according to their block definitions that may not be
68  the same hierarchy that the HCFG, for example when you have a goto
69  inside a block from outside and when you have local variables in the
70  block. In C99 it is even worse since you can have executable
71  declarations.
72 
73  There are other phases in PIPS that can be used later to operate on the
74  CODE to optimize it further.
75 
76  Even if there is no fundamental reason that we cannot controlize an
77  already controlized code, it is not implemented yet. For example, it
78  could be useful to modify some CODE by adding some goto or complex
79  control code and call again the controlizer on the CODE to have nice
80  unstructured back instead of building correct unstructured statements
81  from scratch or using some CODE dump-and-reparse as it is done in some
82  PIPS phases (outliner...).
83 
84  TODO: a zen-er version of the recursion that avoid passing along the
85  successor everywhere since we know at entry that it is the only
86  successor of the main control node.
87 
88  This is the new version of the controlizer version rewritten by
89  Ronan.Keryell@hpc-project.com
90 
91  @{
92 */
93 
94 /*
95  * $Id: controlizer.c 23065 2016-03-02 09:05:50Z coelho $
96  */
97 
98 #include <stdio.h>
99 #include <strings.h>
100 
101 #include "linear.h"
102 
103 #include "genC.h"
104 #include "ri.h"
105 #include "ri-util.h"
106 //#include "prettyprint.h" // for print_stateement
107 #include "control.h"
108 #include "properties.h"
109 
110 #include "misc.h"
111 
112 #include "constants.h"
113 
114 
115 #define LABEL_TABLES_SIZE 10
116 
117 ␌
118 /* This maps label names to the list of statements where
119  they appear (either as definition or reference).
120 
121  This is a global table to all the module.
122 
123  There are some other local tables used elsewhere in the code to have a
124  more hierarchical owning information
125 */
127 
128 
129 /* This maps label names to their (possible forward) control
130  nodes.
131 
132  That is each statement with a label target is in a control that
133  owns this statement.
134 
135  Since the code is analyzed from the beginning, we may have some labels
136  that map to control node with no statement if their target statement
137  has not been encountered yet, in the case of forward gotos for example.
138 */
140 
141 
142 /* In C, we can have some "goto" inside a block from outside, that
143  translates as any complex control graph into an "unstructured" in the
144  PIPS jargon.
145 
146  Unfortunately, that means it break the structured block nesting that
147  may carry declarations with the scoping information.
148 
149  So we need to track this scope information independently of the control
150  graph. This is the aim of this declaration scope stack that is used to
151  track scoping during visiting the RI.
152 */
153 DEFINE_LOCAL_STACK(scoping_statement, statement)
154 
155 
156 /* Make a control node around a statement if not already done
157 
158  It is like the make_control() constructor except when the statement @p
159  st has a label and is already referenced in Label_control. Thus return
160  the control node that already owns this statement.
161 
162  @param[in] st is the statement we want a control node around
163 
164  @return the new (in the case of a statement without a label) or already
165  associated (in the case of a statement with a label) control node with
166  the statement inside.
167 
168  It returns NULL if the statement has a label but it is not associated to
169  any control node yet
170 
171  FI: the call sites do not seem to check if c==NULL...
172  */
174  string label = entity_name(statement_label(st));
176 
177  if (empty_global_label_p(label))
178  /* No label, so there cannot be a control already associated to a
179  label */
180  c = make_control(st, NIL, NIL);
181  else
182  /* Get back the control node associated with this statement
183  label. Since we store control object in this hash table, use
184  cast. We rely on the fact that NIL for a list is indeed
185  NULL... */
187 
188  pips_assert("c==0 || control_consistent_p(c)",
189  c==0 || control_consistent_p(c));
190 
191  return c;
192 }
193 
194 
195 /* Get the control node associated to a label name
196 
197  It looks for the label name into the Label_control table.
198 
199  The @p name must be the complete entity name, not a local or a user name.
200 
201  @param[in] name is the string name of the label entity
202 
203  The label must exist in the table.
204 
205  @return the associated control node.
206 */
207 static control get_label_control(string name) {
208  control c;
209 
210  pips_assert("label is not the empty label", !empty_global_label_p(name)) ;
211  c = (control) hash_get(Label_control, name);
212  pips_assert("c is defined", c != (control) HASH_UNDEFINED_VALUE);
213  pips_assert("c is a control", check_control(c));
214  ifdebug(2) {
216  }
217  return(c);
218 }
219 
220 
221 /* Mark a statement as related to a label.
222 
223  A @p used_label is a hash_table that maps the label name to the list of
224  statements that reference it.
225 
226  A statement can appear many times for a given label
227 
228  @param used_labels[in,out] is the hash table used to record the statements
229  related to a label. It is not updated for empty labels.
230 
231  @param name[in] is the label entity name. It may be the empty label.
232 
233  @param st[in] is the statement to be recorded as related to the label
234 */
235 static void update_used_labels(hash_table used_labels,
236  string name,
237  statement st) {
238  list sts ;
239 
240  /* Do something only if there is a label: */
241  if (!empty_global_label_p(name)) {
242  list new_sts;
243  /* Get a previous list of statements related to this label: */
244  sts = hash_get_default_empty_list(used_labels, name) ;
245  /* Add the given statement to the list */
246  new_sts = CONS(STATEMENT, st, sts);
247  if (hash_defined_p(used_labels, name))
248  /* If there was already something associated to the label, register
249  the new list: */
250  hash_update(used_labels, name, new_sts);
251  else
252  /* Or create a new entry: */
253  hash_put(used_labels, name, new_sts);
254  /* FI: This debug message happens a lot after inlining? In spite
255  of the source parsing, line numbers are not assigned? */
256  pips_debug(5, "Reference to statement %d seen\n",
257  (int) statement_number( st )) ;
258  }
259 }
260 
261 
262 /* Unions 2 hash maps that list statements referencing labels into one.
263 
264  @param[in,out] l1 is the hash map used as source and target
265 
266  @param[in] l2 is the other hash map
267 
268  @returns @p l1 that is the union of @p l1 and @p l2 interpreted as in
269  the context of update_used_labels() */
271  hash_table l2) {
272  HASH_MAP(name, sts, {
273  FOREACH(STATEMENT, s, sts) {
274  update_used_labels(l1, name, s);
275  };
276  }, l2);
277  return l1;
278 }
279 
280 ␌
281 /* Compute whether all the label references in a statement are in a given
282  label name to statement list local mapping.
283 
284  @param st[in] is the statement we want to check if it owns all allusions to
285  the given label name in the @p used_labels mapping
286 
287  @param[in] used_labels is a hash table mapping a label name to a list
288  of statements that use it (à la Label_statements), as their own label
289  or because it is a goto to it
290 
291  @return true if all the label allusions in @p st are covered by the @p
292  used_labels mapping.
293 */
294 static bool covers_labels_p(statement st,
295  hash_table used_labels) {
296  ifdebug(5) {
297  pips_debug(5, "Statement %td (%p): \n ", statement_number(st), st);
298  /* print_statement(st); */
299  }
300  /* For all the labels in used_labels: */
301  void * cl = NULL;
302  list stats = NIL;
303  string name = string_undefined;
304  while((cl=hash_table_scan(used_labels, cl, (void **) &name, (void **) &stats))) {
305  // HASH_MAP(name, sts, {
306  /* The statements using a label name in used_labels: */
307  //list stats = (list) sts;
308 
309  /* For all the statements associated to this label name: */
310  list sl = (list) hash_get_default_empty_list(Label_statements, (void *) name);
311  FOREACH(STATEMENT, def, sl) {
312  /* In one special case, def may have lost its use of a label:
313  if it is a goto to the next statement (see
314  controlize_goto()). Then it is a simple
315  continue. This special configuration never happens, except
316  in code generated by the inlining pass... or written by a
317  weird programmer. It seems easier to keep Label_statements
318  consistent rather than fix the problem here. */
319  bool found = false;
320  /* Verify that def is in all the statements associated globally to
321  the label name according to module-level Label_statements. */
322  FOREACH(STATEMENT, st, stats) {
323  found |= st == def;
324  }
325 
326  if (!found) {
327  pips_debug(5, "does not cover label %s\n", (char *) name);
328  /* Not useful to go on: */
329  return(false);
330  }
331  }
332  }
333  //}, used_labels);
334 
335  ifdebug(5)
336  fprintf(stderr, "covers its label usage\n");
337 
338  return(true);
339 }
340 
341 
342 #if 0
343 /* Register globally a relation between a label and a statement.
344 
345  It marks the statement as related to a label at the global module level
346  into global Label_statements table and create the control node to hold
347  the statement.
348 
349  @param[in] name is the label of the statement
350 
351  @param[in] st
352 
353  byPut the reference in the statement ST to the label NAME
354  int the Label_statements table and allocate a slot in the Label_control
355  table. */
356 static void init_label(string name, statement st) {
357  /* Do something only if there is a label: */
358  if(!empty_global_label_p(name)) {
359  /* Get the list of statements related to this label: */
361  /* Append the given statement to the list of statements pointing to
362  this label: */
363  list sts = CONS(STATEMENT, st, used);
364  /* Update or create the entry for this label according a previous
365  existence or not: */
366  if (hash_defined_p(Label_statements, name))
367  hash_update(Label_statements, name, (char *) sts);
368  else
369  hash_put(Label_statements, name, (char *) sts);
370 
371  /* */
372  if (! hash_defined_p(Label_control, name)) {
374  control c = make_control( new_st, NIL, NIL);
375  pips_debug(8, "control %p allocated for label \"%s\"", c, name);
376  hash_put(Label_control, name, (char *)c);
377  }
378  }
379 }
380 #endif
381 
382 
383 /* Update the global module-level Label_statements table according to the
384  labels a statement references.
385 
386  It also creates a control node for this statement if it has a label and
387  register it to the module-global Label_control table.
388 
389  A statement can reference a label if it is its own label or if the
390  statement is indeed a goto to this label.
391 
392  Label found in Fortran do-loop to set loop boundary or in Fortran IO
393  using some FORMAT through its label are not considered here since it is
394  not related to control flow.
395 
396  @param[in] st is the statement to look at for labels
397 */
399  instruction i;
400 
401  /* Add the statement to its own label reference, if needed: */
402  string name = entity_name(statement_label(st));
403  if (!empty_global_label_p(name)) {
404  /* Associate globally the statement to its own label: */
406  /* Create the control node with the statement inside: */
407  control c = make_control(st, NIL, NIL);
408  pips_debug(8, "control %p allocated for label \"%s\"", c, name);
409  hash_put(Label_control, name, (char *)c);
410  }
411 
412  switch(instruction_tag(i = statement_instruction(st))) {
413  /* If the statement is a goto, add to the target label a reference to
414  this statement: */
415  case is_instruction_goto: {
416  string where = entity_name(statement_label(instruction_goto(i)));
417  /* Associate the statement to the target label: */
419  break;
420  }
421 
423  pips_internal_error("Found unstructured", "");
424 
425  default:
426  /* Do nothing special for other kind of instructions */
427  ;
428  }
429 }
430 
431 
432 /* Initialize the global Label_statements mapping for the module that
433  associates for any label in the module the statements that refer to it.
434 
435  @param[in] st is the module (top) statement
436 */
438  /* Apply create_statements_of_label() on all the module statements */
439  gen_recurse(st,
441  gen_true,
443 }
444 
445 ␌
446 /* @defgroup do_loop_desugaring Desugaring functions used to transform
447  non well structured à la Fortran do-loop into an equivalent code with
448  tests and gotos.
449 
450  @{
451 */
452 /* LOOP_HEADER, LOOP_TEST and LOOP_INC build the desugaring phases of a
453  do-loop L for the loop header (i=1), the test (i<10) and the increment
454  (i=i+1). */
455 
456 /* Make an index initialization header for an unsugared à la Fortran
457  do-loop "do i = l,u,s"
458 
459  @param[in] sl is the do-loop statement
460 
461  @return an assignment statement "i = l"
462  */
464 {
465  loop l = statement_loop(sl);
466  /* Build a reference expression to the loop index: */
468  /* Assign the lower range to it: */
470 
471  return hs;
472 }
473 
475 {
476  forloop l = statement_forloop(sl);
480 
481  return is;
482 }
483 
485 {
487 
488  return hs;
489 }
490 
491 
492 /* Do a crude test of end of do-loop for do-loop unsugaring.
493 
494  TODO : indeed the code is wrong since it only works for loops without
495  side effects on the index inside the loop and if the stride is
496  positive, and the upper bound greated than the lower bound
497 
498  @param[in] sl is a statement loop of the form "do i = l, u, s"
499 
500  @return a test statement "if (i < u)" with empty then and else branches.
501 */
503 {
504  loop l = statement_loop(sl);
505  /* Build i < u */
509  /* Build if (i < u) with empty branches: */
510  test t = make_test(c,
513 
515  return ts;
516 }
517 
519 {
520  forloop l = statement_forloop(sl);
522  /* Build if (c) with empty branches: */
523  test t = make_test(c,
526 
528  return ts;
529 }
530 
532 {
535  test t = make_test(c,
538 
540  return ts;
541 }
542 
543 
544 /* Do an index increment instruction for do-loop unsugaring.
545 
546  TODO : indeed the code is wrong since it only works for loops without
547  side effects on the index inside the loop
548 
549  @param[in] sl is a statement loop of the form "do i = l, u, s"
550 
551  @return a "i = i + s" statement test "if (i < u)" with empty then and
552  else branches.
553 */
555 {
556  loop l = statement_loop(sl);
557  /* Build "i + s" */
559  // Even for C code? To verify for pointers...
562  /* Build "i = i +s" */
564  c);
565 
566  return s;
567 }
568 
570 {
571  forloop l = statement_forloop(sl);
575 
576  return s;
577 }
578 
579 /* @} */
580 ␌
581 /* Computes the control graph of a Fortran do-loop statement
582 
583  @param[in,out] c_res is the entry control node with the do-loop
584  statement to controlize. If the do-loop has complex control code such
585  as some goto to outside, it is transformed into an equivalent control
586  graph.
587 
588  @param[in,out] succ must be the control node successor of @p c_res that
589  will be the current end of the control node sequence and an exit node
590 
591  @param[in,out] used_labels is a hash table mapping a label name to a
592  list of statements that use it, as their label or because it is a goto
593  to it
594 
595  @return true if the code is not a structured control.
596 */
597 static bool controlize_loop(control c_res,
598  control succ,
599  hash_table used_labels)
600 {
601  /* To track the statement related to labels inside the loop body: */
602  hash_table loop_used_labels = hash_table_make(hash_string, 0);
603  statement sl = control_statement(c_res);
604 
605  pips_debug(5, "(st = %p, c_res = %p, succ = %p)\n", sl, c_res, succ);
606 
607  loop l = statement_loop(sl);
608  statement body_s = loop_body(l);
609 
610  /* Remove the loop body from the loop just in case we want to
611  prettyprint our work in progress: */
612  //loop_body(l) = statement_undefined;
614  /* Create a control node to host the loop body and insert it in the
615  control graph: */
616  control c_body = make_conditional_control(body_s);
617  insert_control_in_arc(c_body, c_res, succ);
618  /* We also insert a dummy node between the body and the exit that will
619  be used for the incrementation because if the control body has goto
620  to succ node, we will have trouble to insert it later: */
622  insert_control_in_arc(c_inc, c_body, succ);
623  /* TODO
624  switch(get_prettyprint_language_tag()) {
625  case is_language_fortran:
626  case is_language_fortran95:
627  cs = strdup(concatenate(prev_comm,
628  get_comment_sentinel(),
629  " DO loop ",
630  lab,
631  " with exit had to be desugared\n",
632  NULL));
633  break;
634  case is_language_c:
635  cs = prev_comm;
636  break;
637  default:
638  pips_internal_error("This language is not handled !");
639  break;
640  }
641  */
642  /* Recurse by controlizing inside the loop: */
643  // FI: this seems redundant with the above call to insert_control_in_arc()
644  //link_2_control_nodes(c_body, c_inc);
645  bool controlized = controlize_statement(c_body, c_inc, loop_used_labels);
646 
647  if (!controlized) {
648  /* First the easy way. We have a kindly control-localized loop body,
649  revert to the original code */
650  pips_debug(6, "Since we can keep the do-loop, remove the useless control node %p that was allocated for the loop_body.\n", c_body);
652  /* Remove the control node from the control graph by carefully
653  relinking around: */
655  /* Remove also the dummy increment node that has not been used
656  either: */
658  /* Move the loop body into its own loop: */
659  loop_body(l) = body_s;
660  }
661  else {
662  /* We are in trouble since the loop body is not locally structured,
663  there are goto from inside or outside the loop body. So we
664  replace the do-loop with a desugared version with an equivalent
665  control graph. */
666  /* Update the increment control node with the real computation: */
667  /* First remove the dummy statement added above: */
669  /* And put "i = i + s" instead: */
671  /* Now build the desugared loop: */
672  /* We can replace the former loop statement by the new header. That
673  means that all pragma, comment, extensions, label on the previous
674  loop stay on this. */
676  /* Add the continuation test between the header and the body that are
677  already connected: */
679  insert_control_in_arc(c_test, c_res, c_body);
680  /* Detach the increment node from the loop exit */
681  unlink_2_control_nodes(c_inc, succ);
682  /* And reconnect it to the test node to make the loop: */
684  /* Add the else branch of the test toward the loop exit: */
685  // FI: try to get the true and false successors at the right location...
686  // link_2_control_nodes(c_test, succ);
687  //control_successors(c_test) = gen_nconc(control_successors(c_test),
688  // CONS(CONTROL, succ, NIL));
689  //control_successors(c_test) = gen_nreverse(control_successors(c_test));
692  CONS(CONTROL, c_test, NIL));
693  /* Detach the succ node from the body node */
694  //unlink_2_control_nodes(c_body, succ);
695  /* We can remove */
696  }
697 
698  /* Keep track of labels that were used by the statements of the loop: */
699  union_used_labels( used_labels, loop_used_labels);
700  hash_table_free(loop_used_labels);
701 
702  pips_debug(5, "Exiting\n");
703 
704  return controlized;
705 }
706 ␌
707 /* Computes the control graph of a C for loop statement
708 
709  @param[in,out] c_res is the entry control node with the for loop
710  statement to controlize. If the for loop has complex control code such
711  as some goto to outside, it is transformed into an equivalent control
712  graph.
713 
714  @param[in,out] succ must be the control node successor of @p c_res that
715  will be the current end of the control node sequence and an exit node
716 
717  @param[in,out] used_labels is a hash table mapping a label name to a
718  list of statements that use it, as their label or because it is a goto
719  to it
720 
721  @return true if the code is not a structured control.
722 */
723 static bool controlize_forloop(control c_res,
724  control succ,
725  hash_table used_labels)
726 {
727  /* To track the statement related to labels inside the loop body: */
728  hash_table loop_used_labels = hash_table_make(hash_string, 0);
729  statement sl = control_statement(c_res);
730 
731  pips_debug(5, "(st = %p, c_res = %p, succ = %p)\n", sl, c_res, succ);
732 
733  forloop l = statement_forloop(sl);
734  statement body_s = forloop_body(l);
735 
736  /* Remove the loop body from the loop just in case we want to
737  prettyprint our work in progress: */
738  //loop_body(l) = statement_undefined;
740  /* Create a control node to host the loop body and insert it in the
741  control graph: */
742  control c_body = make_conditional_control(body_s);
743  insert_control_in_arc(c_body, c_res, succ);
744  /* We also insert a dummy node between the body and the exit that will
745  be used for the incrementation because if the control body has goto
746  to succ node, we will have trouble to insert it later: */
748  insert_control_in_arc(c_inc, c_body, succ);
749  /* TODO
750  switch(get_prettyprint_language_tag()) {
751  case is_language_fortran:
752  case is_language_fortran95:
753  cs = strdup(concatenate(prev_comm,
754  get_comment_sentinel(),
755  " DO loop ",
756  lab,
757  " with exit had to be desugared\n",
758  NULL));
759  break;
760  case is_language_c:
761  cs = prev_comm;
762  break;
763  default:
764  pips_internal_error("This language is not handled !");
765  break;
766  }
767  */
768  /* Recurse by controlizing inside the loop: */
769  // link_2_control_nodes(c_body, c_inc); already done by insert_control_in_arc
770  bool controlized = controlize_statement(c_body, c_inc, loop_used_labels);
771 
772  if (!controlized) {
773  /* First the easy way. We have a kindly control-localized loop body,
774  revert to the original code */
775  pips_debug(6, "Since we can keep the do-loop, remove the useless control node %p that was allocated for the loop_body.\n", c_body);
777  /* Remove the control node from the control graph by carefully
778  relinking around: */
780  /* Remove also the dummy increment node that has not been used
781  either: */
783  /* Move the loop body into its own loop: */
784  forloop_body(l) = body_s;
785  }
786  else {
787  /* We are in trouble since the loop body is not locally structured,
788  there are goto from inside or outside the loop body. So we
789  replace the do-loop with a desugared version with an equivalent
790  control graph. */
791  /* Update the increment control node with the real computation: */
792  /* First remove the dummy statement added above: */
794  /* And put "i = i + s" instead: */
796  /* Now build the desugared loop: */
797  /* We can replace the former loop statement by the new header. That
798  means that all pragma, comment, extensions, label on the previous
799  loop stay on this. */
801  /* Add the continuation test between the header and the body that are
802  already connected: */
804  insert_control_in_arc(c_test, c_res, c_body);
805  /* Detach the increment node from the loop exit */
806  unlink_2_control_nodes(c_inc, succ);
807  /* And reconnect it to the test node to make the loop: */
809  /* Add the else branch of the test toward the loop exit: */
810  // link_2_control_nodes(c_test, succ) does not support distinction
811  // between true and false branch as first and second successors
812  // FI: I hesitated to define a new loe level procedure in ri-util/control.c
814  CONS(CONTROL, succ, NIL));
816  CONS(CONTROL, c_test, NIL));
817  /* Detach the succ node from the body node */
818  //unlink_2_control_nodes(c_body, succ);
819  /* We can remove */
820  }
821 
822  /* Keep track of labels that were used by the statements of the loop: */
823  union_used_labels( used_labels, loop_used_labels);
824  hash_table_free(loop_used_labels);
825 
826  pips_debug(5, "Exiting\n");
827 
828  return controlized;
829 }
830 ␌
831 /* Computes the control graph of a Fortran or C while loop statement
832 
833  @param[in,out] c_res is the entry control node with the do-loop
834  statement to controlize. If the do-loop has complex control code such
835  as some goto to outside, it is transformed into an equivalent control
836  graph.
837 
838  @param[in,out] succ must be the control node successor of @p c_res that
839  will be the current end of the control node sequence and an exit node
840 
841  @param[in,out] used_labels is a hash table mapping a label name to a
842  list of statements that use it, as their label or because it is a goto
843  to it
844 
845  @return true if the code is not a structured control.
846 */
847 static bool controlize_whileloop(control c_res,
848  control succ,
849  hash_table used_labels)
850 {
851  /* To track the statement related to labels inside the loop body: */
852  hash_table loop_used_labels = hash_table_make(hash_string, 0);
853  statement sl = control_statement(c_res);
854 
855  pips_debug(5, "(st = %p, c_res = %p, succ = %p)\n", sl, c_res, succ);
856 
858  statement body_s = whileloop_body(wl);
859 
860  /* Remove the loop body from the loop just in case we want to
861  prettyprint our work in progress: */
862  // incompatible with debugging code
863  //whileloop_body(wl) = statement_undefined;
865 
866  /* Create a control node to host the loop body and insert it in the
867  control graph: */
868  control c_body = make_conditional_control(body_s);
869  // FI: if c_test were already available, it should be used instead
870  // of succ
871  // insert_control_in_arc(c_body, c_res, succ);
872 
873  // FI: this should be language neutral. The prettyprinter is
874  // supposed to fix comments according to language rules...
875  /* TODO
876  switch(get_prettyprint_language_tag()) {
877  case is_language_fortran:
878  case is_language_fortran95:
879  cs = strdup(concatenate(prev_comm,
880  get_comment_sentinel(),
881  " DO loop ",
882  lab,
883  " with exit had to be desugared\n",
884  NULL));
885  break;
886  case is_language_c:
887  cs = prev_comm;
888  break;
889  default:
890  pips_internal_error("This language is not handled !");
891  break;
892  }
893  */
894 
896  /* Recurse by controlizing inside the loop: */
897  link_2_control_nodes(c_body, c_test);
898  bool controlized = controlize_statement(c_body, c_test, loop_used_labels);
899 
900  if (!controlized) {
901  /* First the easy way. We have a kindly control-localized loop body,
902  revert to the original code */
903  pips_debug(6, "Since we can keep the whileloop, remove the useless control node %p that was allocated for the loop_body.\n", c_body);
905  /* Remove the control node from the control graph by carefully
906  relinking around: */
908  /* Remove also the dummy increment node that has not been used
909  either: */
910  //remove_a_control_from_an_unstructured(c_inc);
911  /* Move the loop body into its own loop: */
912  whileloop_body(wl) = body_s;
913  }
914  else {
915  /* We are in trouble since the loop body is not locally structured,
916  there are goto from inside or outside the loop body. So we
917  replace the while loop with a desugared version with an equivalent
918  control graph. */
919  /* Update the increment control node with the real computation: */
920  /* First remove the dummy statement added above: */
921  //free_statement(control_statement(c_inc));
922  /* And put "i = i + s" instead: */
923  //control_statement(c_inc) = unsugared_loop_inc(sl);
924  /* Now build the desugared loop: */
925  /* We can replace the former loop statement by the new header. That
926  means that all pragma, comment, extensions, label on the previous
927  loop stay on this. */
928  //control_statement(c_res) = unsugared_loop_header(sl);
929  // FI: c_res is useless and should be identified with c_test
931  /* Add the continuation test between the header and the body that are
932  already connected: */
933  //control c_test = make_control(unsugared_loop_test(sl), NIL, NIL);
934  unlink_2_control_nodes(c_res, succ);
936  //insert_control_in_arc(c_test, c_res, c_body);
937  /* Detach succ from the loop body exit */
938  //unlink_2_control_nodes(c_body, succ);
939  /* And reconnect it to the test node to make the loop: */
940  //link_2_control_nodes(c_body, c_test);
941  /* Add the else branch of the test toward the loop exit: arc
942  ordering matters */
944  //link_2_control_nodes(c_test, succ);
945  //link_2_control_nodes(c_test, c_body);
946  link_3_control_nodes(c_test, c_body, succ);
947  // link_2_control_nodes(c_test, c_res);
948  //unlink_2_control_nodes(c_res, succ);
949 
950  pips_assert("c_test is a test with two successors",
953  pips_assert("c_body may have two successors if it is a test",
954  ( gen_length(control_successors(c_body))==2
955  && statement_test_p(control_statement(c_body)) )
956  ||
957  ( gen_length(control_successors(c_body))==1
958  && !statement_test_p(control_statement(c_body)) )
959  );
960  pips_assert("c_res should not be a test",
961  gen_length(control_successors(c_res))==1
962  && !statement_test_p(control_statement(c_res)) );
963  }
964 
965  /* Keep track of labels that were used by the statements of the loop: */
966  union_used_labels( used_labels, loop_used_labels);
967  hash_table_free(loop_used_labels);
968 
969  pips_debug(5, "Exiting\n");
970 
971  return controlized;
972 }
973 ␌
974 /* Computes the control graph of a C repeat until loop statement
975 
976  @param[in,out] c_res is the entry control node with the do-loop
977  statement to controlize. If the do-loop has complex control code such
978  as some goto to outside, it is transformed into an equivalent control
979  graph.
980 
981  @param[in,out] succ must be the control node successor of @p c_res that
982  will be the current end of the control node sequence and an exit node
983 
984  @param[in,out] used_labels is a hash table mapping a label name to a
985  list of statements that use it, as their label or because it is a goto
986  to it
987 
988  @return true if the code is not a structured control.
989 */
990 static bool controlize_repeatloop(control c_res,
991  control succ,
992  hash_table used_labels)
993 {
994  /* To track the statement related to labels inside the loop body: */
995  hash_table loop_used_labels = hash_table_make(hash_string, 0);
996  statement sl = control_statement(c_res);
997 
998  pips_debug(5, "(st = %p, c_res = %p, succ = %p)\n", sl, c_res, succ);
999 
1000  whileloop wl = statement_whileloop(sl);
1001  statement body_s = whileloop_body(wl);
1002 
1003  /* Remove the loop body from the loop just in case we want to
1004  prettyprint our work in progress: */
1006  /* Create a control node to host the loop body and insert it in the
1007  control graph: */
1008  control c_body = make_conditional_control(body_s);
1009  //insert_control_in_arc(c_body, c_res, succ);
1010  /* We also insert a dummy node between the body and the exit that will
1011  be used for the incrementation because if the control body has goto
1012  to succ node, we will have trouble to insert it later: */
1013  //control c_inc = make_control(make_plain_continue_statement(), NIL, NIL);
1014  //insert_control_in_arc(c_inc, c_body, succ);
1015  /* TODO
1016  switch(get_prettyprint_language_tag()) {
1017  case is_language_fortran:
1018  case is_language_fortran95:
1019  cs = strdup(concatenate(prev_comm,
1020  get_comment_sentinel(),
1021  " DO loop ",
1022  lab,
1023  " with exit had to be desugared\n",
1024  NULL));
1025  break;
1026  case is_language_c:
1027  cs = prev_comm;
1028  break;
1029  default:
1030  pips_internal_error("This language is not handled !");
1031  break;
1032  }
1033  */
1035  /* Recurse by controlizing inside the loop: */
1036  link_2_control_nodes(c_body, c_test);
1037  bool controlized = controlize_statement(c_body, c_test, loop_used_labels);
1038 
1039  if (!controlized) {
1040  /* First the easy way. We have a kindly control-localized loop body,
1041  revert to the original code */
1042  pips_debug(6, "Since we can keep the do-loop, remove the useless control node %p that was allocated for the loop_body.\n", c_body);
1044  /* Remove the control node from the control graph by carefully
1045  relinking around: */
1047  /* Remove also the dummy increment node that has not been used
1048  either: */
1049  //remove_a_control_from_an_unstructured(c_inc);
1050  /* Move the loop body into its own loop: */
1051  whileloop_body(wl) = body_s;
1052  }
1053  else {
1054  /* We are in trouble since the loop body is not locally structured,
1055  there are goto from inside or outside the loop body. So we
1056  replace the do-loop with a desugared version with an equivalent
1057  control graph. */
1058  /* Update the increment control node with the real computation: */
1059  /* First remove the dummy statement added above: */
1060  //free_statement(control_statement(c_inc));
1061  /* And put "i = i + s" instead: */
1062  //control_statement(c_inc) = unsugared_loop_inc(sl);
1063  /* Now build the desugared loop: */
1064  /* We can replace the former loop statement by the new header. That
1065  means that all pragma, comment, extensions, label on the previous
1066  loop stay on this. */
1068  /* Add the continuation test between the header and the body that are
1069  already connected: */
1070  //control c_test = make_control(unsugared_loop_test(sl), NIL, NIL);
1071  // insert_control_in_arc(c_test, c_res, c_body);
1072  /* Detach the increment node from the loop exit */
1073  //unlink_2_control_nodes(c_inc, succ);
1074  /* And reconnect it to the test node to make the loop: */
1075  //link_2_control_nodes(c_inc, c_test);
1076  //link_2_control_nodes(c_body, c_test);
1077  //link_2_control_nodes(c_test, c_res);
1078  /* Add the else branch of the test toward the loop exit: */
1079  //link_2_control_nodes(c_test, succ);
1080  /* We can remove */
1081  unlink_2_control_nodes(c_res, succ);
1082  link_2_control_nodes(c_res, c_body);
1083  /* Add the else branch of the test toward the loop exit: arc
1084  ordering matters */
1085  unlink_2_control_nodes(c_test, c_body);
1086  //link_2_control_nodes(c_test, succ);
1087  //link_2_control_nodes(c_test, c_body);
1088  link_3_control_nodes(c_test, c_body, succ);
1089 
1090  pips_assert("c_test is a test with two successors",
1093  pips_assert("c_body may have two successors if it is a test",
1094  ( gen_length(control_successors(c_body))==2
1095  && statement_test_p(control_statement(c_body)) )
1096  ||
1097  ( gen_length(control_successors(c_body))==1
1098  && !statement_test_p(control_statement(c_body)) )
1099  );
1100  pips_assert("c_res should not be a test",
1101  gen_length(control_successors(c_res))==1
1102  && !statement_test_p(control_statement(c_res)) );
1103  }
1104 
1105  /* Keep track of labels that were used by the statements of the loop: */
1106  union_used_labels( used_labels, loop_used_labels);
1107  hash_table_free(loop_used_labels);
1108 
1109  pips_debug(5, "Exiting\n");
1110 
1111  return controlized;
1112 }
1113 
1114 
1115 #if 0
1116 /* Generate a test statement ts for exiting loop sl.
1117  * There should be no sharing between sl and ts.
1118  */
1120 {
1123  string cs = string_undefined;
1124  call c = call_undefined;
1125 
1126  switch (get_prettyprint_language_tag()) {
1127  case is_language_fortran:
1129  CONS(EXPRESSION,
1131  NIL));
1132  break;
1133  case is_language_c:
1135  CONS(EXPRESSION,
1137  NIL));
1138  break;
1139  case is_language_fortran95:
1140  pips_internal_error("Need to update F95 case");
1141  break;
1142  default:
1143  pips_internal_error("Language unknown !");
1144  break;
1145  }
1146 
1151  string csl = statement_comments(sl);
1152  /* string prev_comm = empty_comments_p(csl)? "" : strdup(csl); */
1153  string prev_comm = empty_comments_p(csl)? empty_comments /* strdup("") */ : strdup(csl);
1154  string lab = string_undefined;
1155 
1156  switch (get_prettyprint_language_tag()) {
1157  case is_language_fortran:
1158  case is_language_fortran95:
1160  cs = strdup(concatenate(prev_comm,
1162  " DO WHILE loop ",
1163  "with GO TO exit had to be desugared\n",
1164  NULL));
1165  } else {
1167  cs = strdup(concatenate(prev_comm,
1169  " DO WHILE loop ",
1170  lab,
1171  " with GO TO exit had to be desugared\n",
1172  NULL));
1173  }
1174  break;
1175  case is_language_c:
1176  cs = prev_comm;
1177  break;
1178  default:
1179  pips_internal_error("Language unknown !");
1180  break;
1181  }
1182 
1183  abort();
1184  if (get_bool_property("PRETTYPRINT_C_CODE"))
1185  cs = prev_comm;
1186  else
1187  {
1189  cs = strdup(concatenate(prev_comm,
1190  "C DO WHILE loop ",
1191  "with GO TO exit had to be desugared\n",
1192  NULL));
1193  }
1194  else {
1195  string lab = label_local_name(whileloop_label(l));
1196  cs = strdup(concatenate(prev_comm,
1197  "C DO WHILE loop ",
1198  lab,
1199  " with GO TO exit had to be desugared\n",
1200  NULL));
1201  }
1202  }
1203 
1205  statement_number(sl),
1207  cs,
1210 
1211  return ts;
1212 }
1213 
1214 ␌
1215 /* CONTROLIZE_WHILELOOP computes in C_RES the control graph of the loop L (of
1216  * statement ST) with PREDecessor and SUCCessor
1217  *
1218  * Derived by FI from controlize_loop()
1219  */
1220 
1221 /* NN : What about other kind of whileloop, evaluation = after ? TO BE IMPLEMENTED */
1222 
1223 bool old_controlize_whileloop(st, l, pred, succ, c_res, used_labels)
1224 statement st;
1225 whileloop l;
1226 control pred, succ;
1227 control c_res;
1228 hash_table used_labels;
1229 {
1230  hash_table loop_used_labels = hash_table_make(hash_string, 0);
1232  bool controlized;
1233 
1234  pips_debug(5, "(st = %p, pred = %p, succ = %p, c_res = %p)\n",
1235  st, pred, succ, c_res);
1236 
1237  abort();
1238  controlize_statement(whileloop_body(l), c_res, c_res, c_body, loop_used_labels);
1239 
1240  if(covers_labels_p(whileloop_body(l),loop_used_labels)) {
1242  control_statement(c_body),
1243  whileloop_label(l),
1245 
1246  /* The edges between c_res and c_body, created by the above call to
1247  * controlize are useless. The edge succ
1248  * from c_res to c_body is erased by the UPDATE_CONTROL macro.
1249  */
1250  gen_remove(&control_successors(c_body), c_res);
1251  gen_remove(&control_predecessors(c_body), c_res);
1252  gen_remove(&control_predecessors(c_res), c_body);
1253 
1254  st = normalize_statement(st);
1255  UPDATE_CONTROL(c_res,
1257  statement_number(st),
1261  new_l),
1266  CONS(CONTROL, succ, NIL));
1267  controlized = false;
1268  }
1269  else {
1270  control_statement(c_res) = whileloop_test(st);
1271  /* control_predecessors(c_res) =
1272  CONS(CONTROL, pred, control_predecessors(c_res)); */
1273  /* ADD_PRED(pred, c_res); */
1274  control_predecessors(c_res) =
1275  gen_once(pred, control_predecessors(c_res));
1276  control_successors(c_res) =
1277  CONS(CONTROL, succ, control_successors(c_res));
1278  controlized = true ;
1279  /* Cannot be consistent yet! */
1280  /* ifdebug(5) check_control_coherency(c_res); */
1281  }
1284  /* control_successors(pred) = ADD_SUCC(c_res, pred); */
1285 
1286  ifdebug(5) check_control_coherency(c_res);
1287 
1288  union_used_labels( used_labels, loop_used_labels);
1289  hash_table_free(loop_used_labels);
1290 
1291  pips_debug(5, "Exiting\n");
1292 
1293  return(controlized);
1294 }
1295 
1296 ␌
1298 {
1302 
1303  return hs;
1304 }
1305 
1306 
1308 {
1310  expression cond = forloop_condition(l);
1312  CONS(EXPRESSION,
1313  copy_expression(cond),
1314  NIL));
1319  string csl = statement_comments(sl);
1320  string cs = empty_comments_p(csl)? empty_comments /* strdup("") */ : strdup(csl);
1321 
1323  statement_number(sl),
1325  cs,
1328 
1329  ifdebug(8) {
1330  pips_debug(8, "Condition expression: ");
1331  print_expression(cond);
1332  }
1333 
1334  return ts;
1335 }
1336 
1337 
1339 {
1341  expression inc = forloop_increment(l);
1344 
1345  ifdebug(8) {
1346  pips_debug(8, "Increment expression: ");
1347  print_expression(inc);
1348  }
1349 
1350  return is;
1351 }
1352 
1353 
1354 bool controlize_forloop(st, l, pred, succ, c_res, used_labels)
1355 statement st;
1356 forloop l;
1357 control pred, succ;
1358 control c_res;
1359 hash_table used_labels;
1360 {
1361  hash_table loop_used_labels = hash_table_make(hash_string, 0);
1365  bool controlized = false; /* To avoid gcc warning about possible
1366  non-initialization */
1367 
1368  pips_debug(5, "(st = %p, pred = %p, succ = %p, c_res = %p)\n",
1369  st, pred, succ, c_res);
1370  abort();
1371  ifdebug(1)
1373 
1374  controlize_statement(forloop_body(l), c_test, c_inc, c_body, loop_used_labels);
1375 
1376  ifdebug(1)
1378 
1379  if (covers_labels_p(forloop_body(l),loop_used_labels)) {
1381 
1382  /* Try an unsafe conversion to a Fortran style DO loop: it assumes
1383  that the loop body does not define the loop index, but effects are
1384  not yet available when the controlizer is run. */
1385  if(get_bool_property("FOR_TO_DO_LOOP_IN_CONTROLIZER")) {
1386  forloop_body(l)= control_statement(c_body);
1387  sequence new_l = for_to_do_loop_conversion(l,st);
1388 
1389  if(!sequence_undefined_p(new_l)) {
1390  ni = make_instruction_sequence( new_l);
1391  }
1392  }
1393 
1394  /* If the DO conversion has failed, the WHILE conversion may be requested */
1395  if(instruction_undefined_p(ni)) {
1396  if(get_bool_property("FOR_TO_WHILE_LOOP_IN_CONTROLIZER")) {
1397  /* As a sequence cannot carry comments, the for loop comments
1398  are moved to the while loop */
1400  forloop_condition(l),
1401  forloop_increment(l),
1402  control_statement(c_body),
1403  statement_extensions(st));
1404 
1405  /* These three fields have been re-used or freed by the previous call */
1409 
1410  ni = make_instruction_sequence(wls);
1411  }
1412  else {
1414  forloop_condition(l),
1415  forloop_increment(l),
1416  control_statement(c_body));
1417 
1418  ni = make_instruction_forloop(new_l);
1419  }
1420  }
1421 
1422  gen_remove(&control_successors(c_body), c_res);
1423  gen_remove(&control_predecessors(c_body), c_res);
1424  gen_remove(&control_predecessors(c_res), c_body);
1425 
1426  /* Quite a lot of sharing between st and d_st*/
1427  st = normalize_statement(st);
1429  statement_number(st),
1432  ni,
1436  ifdebug(1) {
1438  statement_consistent_p(d_st);
1439  }
1440  /* Since we may have replaced a statement that may have comments and
1441  labels by a sequence, do not forget to forward them where they can
1442  be: */
1444  ifdebug(1) {
1445  statement_consistent_p(d_st);
1446  }
1447 
1448  UPDATE_CONTROL(c_res,
1449  d_st,
1451  CONS(CONTROL, succ, NIL));
1452  controlized = false;
1454  }
1455  else /* The for loop cannot be preserved as a control structure*/
1456  {
1457  /* NN : I do not know how to deal with this, the following code does not always work
1458 
1459  pips_internal_error("Forloop with goto not implemented yet");*/
1460 
1464  CONS(CONTROL, c_res, CONS(CONTROL, c_inc, NIL)),
1466  CONS(CONTROL, succ, CONS(CONTROL, c_body, NIL));
1468  control_statement(c_inc) = forloop_inc(st);
1470  UPDATE_CONTROL(c_res,
1471  forloop_header(st),
1473  CONS(CONTROL, c_test, NIL));
1474  controlized = true ;
1476  }
1478  /* control_successors(pred) = ADD_SUCC(c_res, pred); */
1479 
1480  ifdebug(5) check_control_coherency(c_res);
1481 
1482  union_used_labels( used_labels, loop_used_labels);
1483  hash_table_free(loop_used_labels);
1484 
1485  pips_debug(5, "Exiting\n");
1486 
1487  return(controlized);
1488 }
1489 #endif
1490 
1491 /* Move all the declarations found in a list of control to a given
1492  statement. Maintain the initializations where they belong. See
1493  Control/block_scope5n.
1494 
1495  @ctls is a list of control nodes
1496 
1497  It is useful in the controlizer to keep scoping of declarations even
1498  with unstructured that may destroy the variable scoping rules.
1499 
1500  If there are conflict names on declarations, they are renamed.
1501 
1502  It relies on correct calls to push_declarations()/pop_declarations()
1503  before to track where to put the declarations.
1504 */
1505 static void
1507  statement s = scoping_statement_head();
1508  list declarations = statement_declarations(s);
1509  statement s_above = scoping_statement_nth(2);
1510  list nctls = NIL; // build a new list of controls to include the
1511  // initialization statements that are derived from
1512  // the declaration statements
1513 
1514  pips_debug(2, "Dealing with block statement %p included into block"
1515  " statement %p\n", s, s_above);
1516 
1517  if (s_above == NULL)
1518  /* No block statement above, so it is hard to move something there :-) */
1519  return;
1520 
1521  list declarations_above = statement_declarations(s_above);
1522  list new_declarations = NIL;
1523  /* The variables created in case of name conflict */
1524  list new_variables = NIL;
1525  hash_table old_to_new_variables = hash_table_make(hash_chunk, 0);
1526 
1527  /* Look for conflicting names: */
1528  FOREACH(ENTITY, e, declarations) {
1529  const char * name = entity_user_name(e);
1530  bool conflict = false;
1531  FOREACH(ENTITY, e_above, declarations_above) {
1532  const char * name_above = entity_user_name(e_above);
1533  pips_debug(2, "Comparing variables %s and %s\n",
1534  entity_name(e), entity_name(e_above));
1535 
1536  if (strcmp(name, name_above) == 0) {
1537  /* There is a conflict name between a declaration in the current
1538  statement block and one in the statement block above: */
1539  conflict = true;
1540  break;
1541  }
1542  }
1543  entity v;
1544  if (conflict) {
1545  pips_debug(2, "Conflict on variable %s\n", entity_name(e));
1546 
1547  /* Create a new variable with a non conflicting name without
1548  inserting a new statement declaration which is likely to be
1549  lost because s_above is currently represented as a list of
1550  control nodes not as a standard sequence. */
1552  s_above,
1553  "",
1554  "_",
1556  false);
1557  new_variables = gen_entity_cons(v , new_variables);
1558  hash_put_or_update(old_to_new_variables, e, v);
1559  // FI: I do not understand how v can already be in
1560  // new_declarations since v has just been cloned!
1561  // if(!gen_in_list_p(v, new_declarations))
1562  // new_declarations = gen_entity_cons(v , new_declarations);
1563  // The new variable v has already been added to the declarations
1564  // of s_above. The code would be easuer to understand if e were
1565  // added to these declarations in the else clause.
1566  }
1567  else {
1568  v = e;
1569  /* Add the inner declaration to the upper statement later */
1570  new_declarations = gen_entity_cons(v , new_declarations);
1571  }
1572  }
1573 
1574  /* Remove the inner declaration from the inner statement block:
1575  */
1578 
1579  /* Add all the declarations to the statement block above and
1580  preserve the order: */
1581  new_declarations = gen_nreverse(new_declarations);
1582  statement_declarations(s_above) = gen_nconc(declarations_above,
1583  new_declarations);
1584  FOREACH(ENTITY, dv, new_variables) {
1585  // This does not seem to work because the above statement is being
1586  // controlized. Hence, the new declaration statements are simply
1587  // ignored... It might be better to rely on the block declaration
1588  // list and to fix the declarations a posteriori, maybe at the end
1589  // of controlize_statement(). The other option is to generate C99
1590  // code with declarations anywhere in the execution flow
1591  //add_declaration_statement(s_above, dv);
1592  ;
1593  }
1594 
1595  // Even with C99 code, the initializations should not be moved,
1596  // even when the initial value is numerically known. See
1597  // Control/block_scope5n. Unless the variable is static. See
1598  // Control/block_scope13.c
1599  if(true || get_bool_property("C89_CODE_GENERATION")) {
1600  /* Replace initializations in declarations by assignment
1601  statements, when possible; see split_initializations(); do not
1602  worry about variable renaming yet */
1603  FOREACH(CONTROL, c, ctls) {
1605  nctls = gen_nconc(nctls, CONS(CONTROL, c, NIL));
1606  // FI: the entity must also be substituted in the
1607  // initializations contained by the declarations. Also old
1608  // declarations must be transformed into assignments.
1609  if(declaration_statement_p(s)) {
1610  int sn = statement_number(s);
1611  list icl = NIL;
1612  /* If old is declared in s, its declaration must be removed
1613  and replaced if necessary by an assignment with its
1614  initial value... It seems tricky at first if many
1615  variables are declared simultaneously but is does not
1616  matter if all have to be substituted. Oops for
1617  functional declarations... */
1618  list dvl = statement_declarations(s);
1619  //list il = NIL; // initialization list
1620  FOREACH(ENTITY, dv, dvl) {
1621  if(!entity_static_variable_p(dv)) {
1622  value iv = entity_initial(dv);
1623  if(!value_unknown_p(iv)) {
1626  statement is = make_assign_statement(lhs, ie);
1627  statement_number(is) = sn;
1628  control ic = make_control(is, NIL, NIL);
1629  /* FI: it would be better to use a comma expression in
1630  order to replace a statement by a unique statement */
1631  nctls = gen_nconc(nctls, CONS(CONTROL, ic, NIL));
1632  icl = gen_nconc(icl, CONS(CONTROL, ic, NIL));
1633  entity n = (entity) hash_get(old_to_new_variables, (void *) dv);
1634  n = HASH_UNDEFINED_VALUE==n? dv : n;
1637  }
1638  }
1639  }
1640  /* chain icl to c, assume ctls is a list over a control sequence... */
1641  if(!ENDP(icl)) {
1642  pips_assert("c has one successor (but may be zero with"
1643  " dead code behind declarations:-(",
1645  control succ = CONTROL(CAR(control_successors(c)));
1646  control fic = CONTROL(CAR(icl));
1647  control cic = fic;
1648  control lic = CONTROL(CAR(gen_last(icl)));
1649  FOREACH(CONTROL, nc, CDR(icl)) {
1650  /* The nodes in icl must be linked together */
1651  link_2_control_nodes(cic, nc);
1652  cic = nc;
1653  }
1654  unlink_2_control_nodes(c, succ);
1655  link_2_control_nodes(c, fic);
1656  link_2_control_nodes(lic, succ);
1657  /* They should be added into ctls too... because the
1658  initialization expressions may require some
1659  renaming... but nctls probably takes care of that. */
1660  gen_free_list(icl);
1661  }
1663  }
1664  }
1665  }
1666  else
1667  nctls = gen_copy_seq(ctls);
1668 
1669  /* Replace all references to old variables to references to the new
1670  ones in all the corresponding control nodes by in the code */
1671  void * ccp = NULL; // current couple pointer
1672  entity old, new;
1673  while((ccp = hash_table_scan(old_to_new_variables, ccp, (void *) &old, (void *) &new))) {
1674  //HASH_MAP(old, new, {
1675  FOREACH(CONTROL, c, nctls) {
1677  if(true || !get_bool_property("C89_CODE_GENERATION")) { // C99 assumed
1678  if(declaration_statement_p(s)) {
1679  list dl = statement_declarations(s);
1680  list cl;
1681  for(cl=dl; !ENDP(cl); POP(cl)) {
1682  entity dv = ENTITY(CAR(cl));
1683  if(dv==old)
1684  ENTITY_(CAR(cl)) = new;
1685  }
1686  }
1687  }
1688  replace_entity(s, old, new);
1689  }
1690  /* We should free in some way the old variable... */
1691  //}, old_to_new_variables);
1692  }
1693  hash_table_free(old_to_new_variables);
1694 
1695  return;
1696 }
1697 
1698 ␌
1699 /* Find the exit node of a sub-CFG defined by the list of nodes ctls
1700  * and by the first node to execute when finished. The entry node of
1701  * the sub-CFG is the last node of the ctls list, because it is built
1702  * backwards.
1703  *
1704  * RK: ctls is built backwards: hence its exit node is the first node in
1705  * the list.
1706  *
1707  * FI: in fact, it's a bit more complicated...
1708  *
1709  * The underlying purpose of this function only called from
1710  * controlize_sequence(() is to help separate a sub CFG with only one
1711  * entry and one exit point from the global graph. The entry node is
1712  * easy to find as CONTROL(CAR(gen_last(ctls))). The exit node may be
1713  * anywhere because of the goto statements. The succ node is the first
1714  * node executed after the CFG defined by ctls. But it may have no
1715  * predecessor or only some of its predecessors belong to the global
1716  * graph but not to the local graph. So we are interested in
1717  * predecessors of succ that are reachable from the entry node. Unless
1718  * we are lucky because succ has only one predecessor and this
1719  * predecessor has only one successor, succ. In that case, the
1720  * predecessor of succ is the exit node.
1721  *
1722  * The control graph may be altered with a newly allocated node or
1723  * not.
1724  *
1725  * @param ctls: list of the control nodes belonging to the subgraph to
1726  * isolate
1727  *
1728  * @param: succ is the first control node not in ctls to be executed
1729  * after the nodes in ctls.
1730  *
1731  * @return exit, the existing or newly allocated exit node. The
1732  * subgraph defined by ctls is updated when a new node is allocated.
1733  *
1734  * Two algorithms at least are possible: we can either start from the
1735  * predecessors of succ and check that a backward control path to the
1736  * entry of ctls exists, or we can start from entry and look for
1737  * control paths reaching succ. The second approach is implemented here.
1738  */
1740 {
1741  control exit = CONTROL(CAR(ctls));
1742  control entry = CONTROL(CAR(gen_last(ctls)));
1743 
1744  ifdebug(8) {
1745  FOREACH(CONTROL, c, ctls) {
1747  }
1749  }
1750 
1753  && CONTROL(CAR(control_successors(exit)))==succ))) {
1754  /* look for a successor of entry that is a predecessor of succ */
1755  list visited = NIL;
1756  list to_be_visited = gen_copy_seq(control_successors(entry));
1757  bool found_p = false;
1759 
1760  while(!ENDP(to_be_visited)) {
1761  FOREACH(CONTROL, c, to_be_visited) {
1762  if(gen_in_list_p(succ, control_successors(c))) {
1765 
1766  insert_control_in_arc(exit, c, succ);
1767  found_p = true;
1768  }
1769  if(c!=succ) { // Should always be true...
1770  visited = CONS(CONTROL, c, visited);
1771  gen_remove(&to_be_visited, c);
1773  if(!gen_in_list_p(s, visited)
1774  && !gen_in_list_p(s, to_be_visited)
1775  && s!=succ && s!=exit)
1776  // update the loop variable... within the two nested loops
1777  to_be_visited = CONS(CONTROL, s, to_be_visited);
1778  }
1779  }
1780  else {
1781  pips_internal_error("design error\n.");
1782  }
1783  }
1784  }
1785 
1786  gen_free_list(visited);
1787  gen_free_list(to_be_visited);
1788 
1789  if(!found_p) {
1790  /* succ may be unreachable because ctls loops on itself*/
1792  }
1793  }
1794 
1795  ifdebug(8) {
1796  FOREACH(CONTROL, c, ctls) {
1798  }
1800  }
1801 
1802 return exit;
1803 }
1804 
1805 /* FI: remake of function above, incomplete backward approach, now
1806  obsolete because the forward approach works. But who knows? The
1807  complexity of the backward approach might be lower than the
1808  complexity of the forward approach? */
1810 {
1812  //control entry = CONTROL(CAR(gen_last(ctls)));
1813 
1814  ifdebug(8) {
1815  FOREACH(CONTROL, c, ctls) {
1817  }
1819  }
1820 
1821  /* Because of the recursive descent in the AST... */
1822  pips_assert("succ has only one successor or none",
1823  gen_length(control_successors(succ))<=1);
1824 
1825  /* Let's try to use an existing node as exit node */
1826  if(gen_length(control_predecessors(succ))==1) {
1828  if(gen_length(control_successors(c))==1) {
1829  pips_debug(8, "succ has a fitting predecessor as exit.\n");
1830  exit = c;
1831  }
1832  }
1833 
1834  if(control_undefined_p(exit)) {
1835  /* A new node is needed as exit node */
1837  if(gen_length(control_predecessors(succ))==0) {
1838  /* The CFG contains an infinite loop and succ is never reached? */
1839  /* FI: we might need to check that the predecessor is not still
1840  c_res? */
1841  /* Why would we link it to succ to have it unlinked by the
1842  caller? */
1843  pips_debug(8, "succ is unreachable and a new exit node %p is created.\n",
1844  exit);
1845  }
1846  else {
1847  /* succ must be removed from the current CFG. Its predecessors within
1848  the current CFG must be moved onto the new exit node */
1849  FOREACH(CONTROL, c, control_predecessors(succ)) {
1850  /* Is c in the current CFG or in anoter one at a higher
1851  level? Typical case: the current sequence is a test branch
1852  and hence succ has two predecessors at the higher level */
1853  if(1 /*forward_control_path_p(entry, c)*/) {
1854  // FI: could we use link and unlink of control nodes?
1855  list pcl = list_undefined;
1856  for(pcl = control_successors(c); !ENDP(pcl); POP(pcl)) {
1857  control cc = CONTROL(CAR(pcl));
1858  if(cc==succ)
1859  CONTROL_(CAR(pcl))=exit;
1860  }
1862  CONS(CONTROL, c, NIL));
1863  }
1864  }
1865  //control_predecessors(exit) = control_predecessors(succ);
1866  //control_predecessors(succ) = CONS(CONTROL, exit, NIL);
1867  /* hpftest62b.f: the sequence below pulls an extra statement in
1868  the unstructured that is being built */
1869  /*
1870  statement fs = control_statement(succ);
1871  statement es = control_statement(exit);
1872  control_statement(exit) = fs;
1873  control_statement(succ) = es;
1874  */
1875  pips_debug(8, "succ is reachable thru %d control paths "
1876  "but a new exit node %p is created.\n",
1878  }
1879  }
1880 
1881  ifdebug(8) {
1882  FOREACH(CONTROL, c, ctls) {
1884  }
1886  }
1887 
1888 return exit;
1889 }
1890 
1891 /* Computes the control graph of a sequence statement
1892 
1893  We try to minimize the number of graphs by looking for graphs with one
1894  node only and picking the statement in that case.
1895 
1896  @param[in,out] c_res is the entry control node with the sequence statement to
1897  controlize. It may be at exit the entry control node of a potential
1898  unstructured
1899 
1900  @param[in,out] succ must be the control node successor of @p c_res that
1901  will be the current end of the control node sequence and an exit node
1902 
1903  @param[in,out] used_labels is a hash table mapping a label name to a
1904  list of statements that use it, as their label or because it is a goto
1905  to it
1906 
1907  @return true if the code is not a structured control, i.e. it has
1908  to be "controlized", i.e. transformed into an "unstructured".
1909 
1910  Also, side effect on hash table Label_statements if ever a goto is
1911  replaced by a continue because it points to the very next
1912  statement, via an indirect call to controlize_goto().
1913 */
1914 static bool controlize_sequence(control c_res,
1915  control succ,
1916  hash_table used_labels) {
1917  statement st = control_statement(c_res);
1918  /* To see if the control graph will stay local or not: */
1919  hash_table block_used_labels = hash_table_make(hash_string, 0);
1920  bool controlized = false;
1921 
1922  pips_assert("st it a statement sequence", statement_sequence_p(st));
1923 
1924  ifdebug(5) {
1925  pips_debug(5, "Entering with nodes linked with c_res %p:\n", c_res);
1927  }
1928  ifdebug(1) {
1929  check_control_coherency(c_res);
1931  }
1932 
1933  scoping_statement_push(st);
1934 
1935  /* A C block may have a label and even goto from outside on it. */
1936  /* To track variable scoping, track this statement */
1937  // TODO scoping_statement_push(st);
1938 
1939  /* Get the list of statements in the block statement: */
1940  list sts = statement_block(st);
1941  /* The list of all the control nodes associated to this statement
1942  list: */
1943  list ctls = NIL;
1944 
1945  /* To track where to insert the current control node of a sequence
1946  element: */
1947  control pred = c_res;
1948  /* We first transform a structured block of statement in a thread of
1949  control node with all the statements that we insert from c_res up to
1950  succ: */
1951  bool must_be_controlized_p = false;
1952  //bool previous_control_preexisting_p = false;
1953 
1954  FOREACH(STATEMENT, s, sts) {
1955  /* Create a new control node for this statement, or retrieve one
1956  if it as a label: */
1958  //bool control_preexisting_p = false;
1959 
1960  // FI: I'm not sure this is enough to detect that
1961  // make_conditional_control() has not made a new control but
1962  // retrieved a control by its label...
1963  //if(!ENDP(control_successors(c)) || !ENDP(control_predecessors(c)) ) {
1964  // FI: too bad if the label is unused... or used locally... or is
1965  // useless as happens after inlining for FREIA: "goto l1;l1: ;"
1966  if(!unlabelled_statement_p(s)) {
1967  pips_debug(8, "This control %p pre-existed. "
1968  "The sequence cannot be controlized.\n", c);
1969  must_be_controlized_p = true;
1970  //control_preexisting_p = true;
1971  }
1972 
1973  // "insert_control_in_arc(c, pred, succ);" with additional checks
1974  unlink_2_control_nodes(pred,succ); // whether they are linked or not
1975  if(ENDP(control_successors(pred)))
1976  link_2_control_nodes(pred, c);
1977  if(ENDP(control_successors(c)))
1978  link_2_control_nodes(c, succ);
1979 
1980 
1981  /* Keep track of the control node associated to this statement. Note
1982  that the list is built in reverse order: */
1983  ctls = CONS(CONTROL, c, ctls);
1984  /* The next control node will be inserted after the new created node: */
1985  pred = c;
1986  //previous_control_preexisting_p = control_preexisting_p;
1987  }
1988 
1989  // FI: check that this is a neat sequence if it does not must be controlized
1990  if(!must_be_controlized_p) {
1991  FOREACH(CONTROL, c, ctls) {
1992  pips_assert("c may have only one successor even if it is a test "
1993  "a this point",
1996  ||
1999  );
2000  }
2001  }
2002 
2003  /* Now do the real controlizer job on the previously inserted thread of
2004  control nodes. */
2005  /* Note that we iterate in the reverse order of the
2006  statements since the control list was built up in reverse
2007  order. Indeed doing this in reverse order is simpler to write with
2008  this "next" stuff because we already have the current element and the
2009  successor "succ". */
2010  control next = succ;
2011  pips_debug(5, "Controlize each statement sequence node in reverse order:\n");
2012  FOREACH(CONTROL, c, ctls) {
2013  /* Recurse on each statement: controlized has been initialized to
2014  false */
2015  controlized |= controlize_statement(c, next, block_used_labels);
2016  /* The currently processed element will be the successor of the one to
2017  be processed: */
2018  next = c;
2019  }
2020 
2021  if (!controlized && !must_be_controlized_p) {
2022 
2023  // FI: check that this is a neat sequence
2024  FOREACH(CONTROL, c, ctls) {
2025  if(controlized) // unstructured case: impossible
2026  pips_assert("c may have two successors only if it is a test",
2029  ||
2032  );
2033  else // the sequence is structured: always
2034  pips_assert("c may have two successors only if it is a test",
2037  ||
2039  // FI: the test may not be unstructured; a
2040  // structured test has only one successor
2041  /* && !statement_test_p(control_statement(c))*/ )
2042  );
2043  }
2044  /* Each control node of the sequence is indeed well structured, that
2045  each control node is without any goto from or to outside itself. So
2046  we can keep the original sequence back! */
2047  pips_debug(5, "Keep a statement sequence and thus remove"
2048  " previously allocated control nodes for the sequence.\n");
2049  /* Easy, just remove all the control nodes of the sequence and relink
2050  around the control graph: */
2051  FOREACH(CONTROL, c, ctls) {
2053  int nsucc = (int) gen_length(control_successors(c));
2054  /* Do not forget to detach the statement of its control node since
2055  we do not want the statement to be freed at the same time: */
2056  pips_debug(6, "Removing useless control node %p.\n", c);
2058 
2059  if(statement_test_p(s)) {
2060  // FI: this had not been planned by Ronan
2061  if(nsucc==1) {
2062  // FI: might this happen when a test is found out well-structured?
2064  }
2065  else {
2066  pips_assert("a test has two successors\n", nsucc==2);
2068  }
2069  }
2070  else {
2071  if(nsucc<=1) {
2072  pips_assert("a non test has one successor at most\n", nsucc<=1);
2073  /* Remove the control node from the control graph by carefully
2074  relinking around: */
2076  }
2077  else {
2078  pips_debug(1, "Abnormal control: not a test, two successors.\n");
2080  }
2081  }
2082  }
2083  // You may have to fix C89 declarations if some unstructured has
2084  // been created below in the recursion
2085  if(get_bool_property("C89_CODE_GENERATION")) {
2087  }
2088  }
2089  else {
2090  /* So, there is some unstructured stuff. We can consider 2 cases to
2091  simplify the generated code:
2092 
2093  - If the unstructured control code is local to the sequence
2094  statements, we can keep some locality by encapsulated this mess
2095  into an unstructured so that from outside this unstructured the
2096  code is view as structured (the H in HCFG!).
2097 
2098  - If not, there are some goto to or from control nodes outside of
2099  the sequence statement and then we cannot do anything and return
2100  the control graph marked as with control side effect.
2101  */
2102  bool covers_p = covers_labels_p(st, block_used_labels);
2103  /* Remove the sequence list but not the statements themselves since
2104  each one has been moved into a control node: */
2107 
2108  // FI: this fails because st has been gutted out... covers_p must
2109  // be computed earlier
2110  if (covers_p) {
2111  /* There are no goto from/to the statements of the statement list,
2112  so we can encapsulate all this local control graph in an
2113  "unstructured" statement: */
2114  /* Get the local exit node that is the head of the control list
2115  since it was built in reverse order. Note that ctls cannot be
2116  empty here because it an empty statement sequence should be
2117  structured by definition and caught by the previous test. */
2118  /* FI: when the last statement is controlized, there is no
2119  guarantee any longer that the control corrresponding to the
2120  last statement of the sequence is the exit node. Also, an
2121  exit node should have no successor by definition. To avoid
2122  the issue, we could systematically add a nop statement to the
2123  sequence. Or we could check that the last control node has no
2124  successors, else look for the node connected to succ (might
2125  be dangerous because succ may not really be part of the code)
2126  and, if no such node is found because the sequence loops
2127  forever, create a new unreachable control node with a NOP
2128  statement. */
2129  // control exit = CONTROL(CAR(ctls));
2130  control exit = find_exit_control_node(ctls, succ);
2131  //control exit = find_or_create_exit_control_node(ctls, succ);
2132  control entry = CONTROL(CAR(gen_last(ctls)));
2133  pips_debug(5, "Create a local unstructured with entry node %p and exit node %p\n", entry, exit);
2134 
2135  /* First detach the local graph: */
2136  unlink_2_control_nodes(c_res, entry);
2137  /* FI: Not such a good idea to return succ as exit control node... */
2139  /* Reconnect around the unstructured: */
2140  link_2_control_nodes(c_res, succ);
2141  /* And create the local "unstructured" statement to take this local
2142  graph: */
2143  unstructured u = make_unstructured(entry, exit);
2144  ifdebug(1) {
2145  check_control_coherency(entry);
2147 
2148  /* Make sure that the new unstructured u is not linked to code
2149  sitting above */
2150  list linked_nodes = NIL;
2151  control_map_get_blocs(entry, &linked_nodes);
2152  if(gen_in_list_p(c_res, linked_nodes)) {
2153  list cp = NIL;
2154  list vp = NIL;
2155  find_a_control_path(entry, c_res, &cp, &vp, 0);
2157  pips_internal_error("Some issue due to \"c_res\" with covers_p\n");
2158  }
2159  else if(gen_in_list_p(succ, linked_nodes)) {
2160  list cp = NIL;
2161  list vp = NIL;
2162  find_a_control_path(entry, c_res, &cp, &vp, 0);
2164  pips_internal_error("Some issue due to \"succ\" with covers_p\n");
2165  }
2166  }
2167 
2168  statement u_s =
2170  /* We keep the old block statement since it may old extensions,
2171  declarations... If useless, it should be removed later by another
2172  phase. So, move the unstructured statement as the only statement
2173  of the block: */
2175  CONS(STATEMENT, u_s, NIL);
2176  // You may have to fix C89 declarations if some unstructured has
2177  // been created below in the recursion
2178  //if(get_bool_property("C89_CODE_GENERATION")) {
2180  //}
2181  /* From outside of this block statement, everything is hierarchized,
2182  so we claim it: */
2183  controlized = false;
2184  }
2185  else {
2186  /* There are some goto from or to external control nodes, so we
2187  cannot localize stuff. */
2188  pips_debug(5, "There are goto to/from outside this statement list"
2189  " so keep control nodes without any hierarchy here.\n");
2190  /* Keep the empty block statement for extensions and declarations: */
2191  // FI; maybe for extensions, but certainly not for declarations;
2192  // similar code to flatten_code must be used to rename the local
2193  // variables and to move them up the AST; see sequence04.c for instance
2195  NIL;
2196  // TODO move declarations up, keep extensions & here
2198  controlized = true;
2199  }
2200  }
2201  /* Integrate the statements related to the labels inside its statement
2202  to the current statement itself: */
2203  union_used_labels(used_labels, block_used_labels);
2204  /* Remove local label association hash map: */
2205  hash_table_free(block_used_labels);
2206 
2207 #if 0
2208 // TODO
2209  if (!hierarchized_labels) {
2210  /* We are in trouble since we will have an unstructured with goto
2211  from or to outside this statement sequence, but the statement
2212  sequence that define the scoping rules is going to disappear...
2213  So we gather all the declaration and push them up: */
2215  }
2216 #endif
2217  ///* Revert to the variable scope of the outer block statement: */
2218  // TODO scoping_statement_pop();
2219  scoping_statement_pop();
2221 
2222  return controlized;
2223 }
2224 
2225 ␌
2226 /* Builds the control node of a test statement
2227 
2228  @param[in,out] c_res is the control node with the test statement
2229  (if/then/else)
2230 
2231  @param[in,out] succ is the control node successor of @p c_res
2232 
2233  @param[in,out] used_labels is a hash table mapping a label name to a list of
2234  statements that use it, as their label or because it is a goto to it
2235 
2236  @return true if the control node generated is not structured.
2237 */
2238 static bool controlize_test(control c_res,
2239  control succ,
2240  hash_table used_labels)
2241 {
2242  bool controlized;
2243  statement st = control_statement(c_res);
2244  test t = statement_test(st);
2245  /* The statements of each branch: */
2246  statement s_t = test_true(t);
2247  statement s_f = test_false(t);
2248  /* Create a control node for each branch of the test: */
2249  control c_then = make_conditional_control(s_t);
2250  control c_else = make_conditional_control(s_f);
2251 
2252  pips_debug(5, "Entering (st = %p, c_res = %p, succ = %p)\n",
2253  st, c_res, succ);
2254 
2255  ifdebug(5) {
2256  /* pips_debug(1, "THEN at entry:\n"); */
2257  /* print_statement(s_t); */
2258  /* pips_debug(1, "c_then at entry:\n"); */
2259  /* print_statement(control_statement(c_then)); */
2260  /* pips_debug(1, "ELSE at entry:\n"); */
2261  /* print_statement(s_f); */
2262  /* pips_debug(1, "c_else at entry:\n"); */
2263  /* print_statement(control_statement(c_else)); */
2265  check_control_coherency(c_res);
2266  }
2267 
2268  /* Use 2 hash table to figure out the label references in each branch to
2269  know if we will able to restructure them later: */
2270  hash_table t_used_labels = hash_table_make(hash_string, 0);
2271  hash_table f_used_labels = hash_table_make(hash_string, 0);
2272 
2273  /* Insert the control nodes for the branch into the current control
2274  sequence: */
2275  /* First disconnect the sequence: */
2276  unlink_2_control_nodes(c_res, succ);
2277 
2278  /* Then insert the 2 nodes for each branch, in the correct order since
2279  the "then" branch is the first successor of the test and the "else"
2280  branch is the second one: */
2281  // Correct order: link_2_control_nodes add the new arc in the
2282  // first slot; so reverse linking of c_else and c_then
2283  link_3_control_nodes(c_res, c_then, c_else);
2284  link_2_control_nodes(c_else, succ);
2285  //link_2_control_nodes(c_res, c_then);
2286  link_2_control_nodes(c_then, succ);
2287 
2288  /* Now we can controlize each branch statement to deal with some control
2289  flow fun: */
2290  controlize_statement(c_then, succ, t_used_labels);
2291  controlize_statement(c_else, succ, f_used_labels);
2292 
2293  /* If all the label jumped to from the THEN/ELSE statements are in their
2294  respective statement, we can replace the unstructured test by a
2295  structured one back: */
2296  /* FI: this test returns a wrong result for if02.c. The reason
2297  might be again controlize_goto() or a consequence of the two
2298  calls to controlize_statement() above. */
2299  if(covers_labels_p(s_t, t_used_labels)
2300  && covers_labels_p(s_f, f_used_labels)) {
2301  pips_debug(5, "Restructure the IF at control %p\n", c_res);
2302  test_true(t) = control_statement(c_then);
2303  test_false(t) = control_statement(c_else);
2304  /* Remove the old unstructured control graph: */
2307  /* c_then & c_else are no longer useful: */
2310  // You do not want to relink too much, but you should relink a minimum
2311  link_2_control_nodes(c_res, succ);
2312 
2313  /* The test statement is a structured test: */
2314  controlized = false;
2315  }
2316  else {
2317  pips_debug(5, "Destructure the IF at control %p\n", c_res);
2318  /* Keep the unstructured test. Normalize the unstructured test where
2319  in the control node of the test, the branch statements must be
2320  empty since the real code is in the 2 control node successors: */
2323  /* Warn we have an unstructured test: */
2324  controlized = true;
2325  }
2326 
2327  /* Update the used labels hash map from the 2 test branches */
2328  union_used_labels(used_labels,
2329  union_used_labels(t_used_labels, f_used_labels));
2330 
2331  /* The local hash tables are no longer useful: */
2332  hash_table_free(t_used_labels);
2333  hash_table_free(f_used_labels);
2334 
2335  ifdebug(5) {
2336  /* pips_debug(1, "IF at exit:\n"); */
2337  /* print_statement(st); */
2340  check_control_coherency(c_res);
2341  }
2342  pips_debug(5, "Exiting\n");
2343 
2344  return controlized;
2345 }
2346 
2347 ␌
2348 /* Deal with "goto" when building the HCFG
2349 
2350  @param[in,out] c_res is the control node with the "goto" statement
2351  (that is an empty one in the unstructured since the "goto" in the HCFG
2352  is an arc, no longer a statement) that will point to a new control node
2353  with the given label
2354 
2355  @param[in,out] succ is the control node successor of @p c_res. Except
2356  if it is also the target of the "goto" by chance, it will become
2357  unreachable.
2358 
2359  @param[in,out] used_labels is a hash table mapping a label name to a
2360  list of statements that use it, as their label or because they are a
2361  goto to it */
2362 static bool controlize_goto(control c_res,
2363  control succ,
2364  hash_table used_labels)
2365 {
2366  bool controlized;
2367  statement st = control_statement(c_res);
2368  statement go_to = statement_goto(st);
2369  /* Get the label name of the statement the goto points to: */
2370  string name = entity_name(statement_label(go_to));
2371  /* Since the goto by itself is transformed into an arc in the control
2372  graph, the "goto" statement is no longer used. But some informations
2373  associated to the "goto" statement such as a comment or an extension
2374  must survive, so we keep them in a nop statement that will receive
2375  its attribute and will be the source arc representing the goto: */
2377  /* Disconnect the target statement: */
2379  free_instruction(i);
2381 
2382  /* Get the control node associated with the label we want to go to: */
2383  control n_succ = get_label_control(name);
2384 
2385  ifdebug(5) {
2386  pips_debug(5, "After freeing the goto, from c_res = %p:\n", c_res);
2388  check_control_coherency(c_res);
2389  pips_debug(5, "From n_succ = %p:\n", n_succ);
2391  check_control_coherency(n_succ);
2392  }
2393  if (succ == n_succ) {
2394  /* Since it is a goto just on the next statement, nothing to do and it
2395  is not unstructured. But st must no longer be associated to name
2396  in hash table Label_statements. */
2397  list sl = (list) hash_get_default_empty_list(Label_statements, (void *) name);
2398  if(gen_in_list_p((void *) st, sl)) {
2399  gen_remove(&sl, (void *) st);
2400  hash_update(Label_statements, (void *) name, (void *) sl);
2401  }
2402  else {
2403  pips_internal_error("Label %s associated to statement %p is not associated"
2404  " to statement %p in hash table Label_statements\n");
2405  }
2406  controlized = false;
2407  }
2408  else {
2409  /* The goto target is somewhere else, so it is clearly
2410  unstructured: */
2411  controlized = true;
2412  pips_debug(5, "Unstructured goto to label %s: control n_succ %p\n"
2413  "\tSo statement in control %p is now unreachable from this way\n",
2414  name, n_succ, succ);
2415  /* Disconnect the nop from the successor:*/
2416  unlink_2_control_nodes(c_res, succ);
2417  /* And add the edge in place of the goto from c_res to n_succ: */
2418  link_2_control_nodes(c_res, n_succ);
2419 
2420  /* Add st as locally related to this label name but do not add the
2421  target since it may be non local: */
2422  update_used_labels(used_labels, name, st);
2423 
2424  ifdebug(5) {
2425  pips_debug(5, "After freeing the goto, from c_res = %p:\n", c_res);
2427  check_control_coherency(c_res);
2428  pips_debug(5, "From n_succ = %p:\n", succ);
2431  }
2432  ifdebug(1)
2433  check_control_coherency(n_succ);
2434  }
2435  return controlized;
2436 }
2437 
2438 ␌
2439 /* Controlize a call statement
2440 
2441  The deal is to correctly manage STOP; since we don't know how to do it
2442  yet, we assume this is a usual call with a continuation !
2443 
2444  To avoid non-standard successors, IO statement with multiple
2445  continuations are not dealt with here. The END= and ERR= clauses are
2446  simulated by hidden tests.
2447 
2448  @param[in] c_res is the control node with a call statement to controlize
2449 
2450  @param[in] succ is the control node successor of @p c_res
2451 
2452  @return false since we do nothing, so no non-structured graph
2453  generation yet...
2454 */
2455 static bool controlize_call(control c_res,
2456  control succ)
2457 {
2458  statement st = control_statement(c_res);
2459  pips_debug(5, "(st = %p, c_res = %p, succ = %p)\n",
2460  st, c_res, succ);
2461 
2462  return false;
2463 }
2464 
2465 ␌
2466 /* Controlize a statement that is in a control node, that is restructure
2467  it to have a HCFG recursively (a hierarchical control flow graph).
2468 
2469  @param[in,out] c_res is the control node with the main statement to
2470  controlize. @p c_res should already own the statement at entry that
2471  will be recursively controlized. @p c_res can be seen as a potential
2472  unstructured entry node.
2473 
2474  @param[in,out] succ is the successor control node of @p c_res at
2475  entry. It may be no longer the case at exit if for example the code is
2476  unreachable or there is a goto to elsewhere in @p_res. @p succ can be
2477  seen as a potential unstructured exit node.
2478 
2479  @param[in,out] used_labels is a way to define a community of label we
2480  encounter in a top-down approac during the recursion with their related
2481  statements. With it, during the bottom-up approach, we can use it to
2482  know if a statement can be control-hierarchized or not. More
2483  concretely, it is a hash table mapping a label name to a list of
2484  statements that reference it, as their label or because it is a goto to
2485  it. This hash map is modified to represent local labels with their
2486  local related statements. This table is used later to know if all the
2487  statements associated to local labels are local or not. If they are
2488  local, the statement can be hierarchized since there is no goto from or
2489  to outside location.
2490 
2491  @return true if the current statement isn't a structured control.
2492 */
2494  control succ,
2495  hash_table used_labels)
2496 {
2497  /* Get the statement to controlized from its control node owner. The
2498  invariant is that this statement remains in its control node through
2499  the controlizer process. Only the content of the statement may
2500  change. */
2501  statement st = control_statement(c_res);
2503  bool controlized = false;
2504 
2505  ifdebug(5) {
2506  pips_debug(1,
2507  "Begin with (st = %p, c_res = %p, succ = %p)\n"
2508  "st at entry:\n",
2509  st, c_res, succ);
2511  /* print_statement(st); */
2512  pips_debug(1, "Control list from c_res %p:\n", c_res);
2515  check_control_coherency(c_res);
2516  }
2517 
2518  switch(instruction_tag(i)) {
2519 
2520  case is_instruction_block:
2521  /* Apply the controlizer on a statement sequence, basically by
2522  considering it as a control node sequence */
2523  controlized = controlize_sequence(c_res, succ, used_labels);
2524  break;
2525 
2526  case is_instruction_test:
2527  /* Go on with a test: */
2528  controlized = controlize_test(c_res, succ, used_labels);
2529  break;
2530 
2531  case is_instruction_loop:
2532  /* Controlize a DO-loop à la Fortran: */
2533  controlized = controlize_loop(c_res, succ, used_labels);
2534  break;
2535 
2536  case is_instruction_whileloop: {
2537  /* Controlize a while() or do { } while() loop: */
2540  controlized = controlize_whileloop(c_res, succ, used_labels);
2541  else
2542  controlized = controlize_repeatloop(c_res, succ, used_labels);
2544  break;
2545  }
2546 
2547  case is_instruction_goto: {
2548  /* The hard case, the goto, that will add some trouble in this well
2549  structured world... */
2550  controlized = controlize_goto(c_res, succ, used_labels);
2551 
2552  break;
2553  }
2554 
2555  case is_instruction_call:
2556  /* Controlize some function call (that hides many things in PIPS) */
2557  /* FI: IO calls may have control effects; they should be handled here! */
2558  // FI: no specific handling of return? controlized = return_instruction_p(i)
2559  controlized = controlize_call(c_res, succ);
2561  break;
2562 
2564  pips_assert("We are really dealing with a for loop",
2566  controlized = controlize_forloop(c_res, succ, used_labels);
2568  break;
2569 
2572  if(expression_reference_p(e)) {
2573  controlized = false;
2574  }
2575  else if(expression_call_p(e))
2576  /* PJ: controlize_call() controlize any "nice" statement, so even a C
2577  expression used as an instruction: */
2578  controlized = controlize_call(c_res, succ);
2580  break;
2581  }
2582 
2583  default:
2584  pips_internal_error("Unknown instruction tag %d", instruction_tag(i));
2585  }
2586 
2588  ifdebug(5) {
2589  pips_debug(1, "st %p at exit:\n", st);
2590  /* print_statement(st); */
2591  pips_debug(1, "Resulting Control c_res %p at exit:\n", c_res);
2593  fprintf(stderr, "---\n");
2594  /* The declarations may be preserved at a lower level
2595  if(!ENDP(statement_declarations(st))
2596  && ENDP(statement_declarations(control_statement(c_res)))) {
2597  pips_internal_error("Lost local declarations");
2598  }
2599  */
2600 
2602  check_control_coherency(c_res);
2603  }
2604 
2605  /* Update the association between the current statement and its
2606  label (the empty label is ignored by update_used_labels()):
2607  */
2608  string label = entity_name(statement_label(st));
2609  update_used_labels(used_labels, label, st);
2610 
2611  return controlized;
2612 }
2613 
2614 ␌
2615 /* Compute the hierarchical control flow graph (HCFG) of a statement
2616 
2617  @param st is the statement we want to "controlize"
2618 
2619  @return the unstructured with the control graph
2620 */
2622 {
2623  statement result;
2624 
2625  pips_assert("Statement should be OK.", statement_consistent_p(st));
2626  ifdebug(1) {
2627  /* To help debugging, force some properties: */
2628  set_bool_property("PRETTYPRINT_BLOCKS", true);
2629  set_bool_property("PRETTYPRINT_EMPTY_BLOCKS", true);
2630  }
2631 
2632  /* Initialize an empty association from label to the statements using
2633  them: */
2634  hash_table used_labels = hash_table_make(hash_string, 0);
2635 
2636  /* Initialize global tables: */
2639  /* Build the global table associating for any label all the statements
2640  that refer to it: */
2642 
2643  /* Construct the entry and exit control node of the unstructured to
2644  generate. First get the control node for all the code: */
2645  control entry = make_conditional_control(st);
2646  /* And make a successor node that is an empty instruction at first: */
2648  /* By default the entry is just connected to the exit that is the
2649  successor: */
2650  link_2_control_nodes(entry, exit);
2651 
2652  /* To track declaration scoping independently of control structure: */
2653  make_scoping_statement_stack();
2654 
2655  /* Build the HCFG from the module statement: */
2656  (void) controlize_statement(entry, exit, used_labels);
2657 
2658  /* Since this HCFG computation is quite general, we may have really an
2659  unstructured at the top level, which is not possible when dealing
2660  from the parser output. */
2661  if (gen_length(control_successors(entry)) == 1
2662  && CONTROL(CAR(control_successors(entry))) == exit) {
2663  /* The 2 control nodes are indeed still a simple sequence, so it is
2664  a structured statement at the top level and it is useless to
2665  build an unstructured to store it. */
2666  result = control_statement(entry);
2668  /* Really remove the useless by contruction statement too: */
2670  }
2671  else {
2672  /* For all the other case, it is not structured code at top level, so
2673  build an unstructured statement to represent it: */
2674  unstructured u = make_unstructured(entry, exit);
2676  }
2677 
2678  /* Clean up scoping stack: */
2679  free_scoping_statement_stack();
2680 
2681  /* Reset the tables used */
2684  hash_table_free(used_labels);
2685 
2686  /* Since the controlizer is a sensitive pass, avoid leaking basic
2687  errors... */
2688  pips_assert("Statement should be OK.", statement_consistent_p(result));
2689 
2690  return result;
2691 }
2692 
2693 /*
2694  @}
2695 */
float a2sf[2] __attribute__((aligned(16)))
USER generates a user error (i.e., non fatal) by printing the given MSG according to the FMT.
Definition: 3dnow.h:3
unstructured make_unstructured(control a1, control a2)
Definition: ri.c:2778
call make_call(entity a1, list a2)
Definition: ri.c:269
instruction make_instruction_forloop(forloop _field_)
Definition: ri.c:1193
value make_value_unknown(void)
Definition: ri.c:2847
expression make_expression(syntax a1, normalized a2)
Definition: ri.c:886
whileloop make_whileloop(expression a1, statement a2, entity a3, evaluation a4)
Definition: ri.c:2937
list gen_entity_cons(entity p, list l)
Definition: ri.c:2537
instruction make_instruction_expression(expression _field_)
Definition: ri.c:1196
control check_control(control p)
Definition: ri.c:493
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
bool statement_consistent_p(statement p)
Definition: ri.c:2195
test make_test(expression a1, statement a2, statement a3)
Definition: ri.c:2607
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_sequence(sequence _field_)
Definition: ri.c:1169
instruction make_instruction_test(test _field_)
Definition: ri.c:1172
void free_instruction(instruction p)
Definition: ri.c:1118
instruction make_instruction(enum instruction_utype tag, void *val)
Definition: ri.c:1166
bool control_consistent_p(control p)
Definition: ri.c:496
syntax make_syntax(enum syntax_utype tag, void *val)
Definition: ri.c:2491
synchronization make_synchronization_none(void)
Definition: ri.c:2424
instruction make_instruction_unstructured(unstructured _field_)
Definition: ri.c:1187
extensions copy_extensions(extensions p)
EXTENSIONS.
Definition: ri.c:947
control make_control(statement a1, list a2, list a3)
Definition: ri.c:523
void free_statement(statement p)
Definition: ri.c:2189
forloop make_forloop(expression a1, expression a2, expression a3, statement a4)
Definition: ri.c:1025
void free_value(value p)
Definition: ri.c:2787
struct _newgen_struct_entity_ * entity
Definition: abc_private.h:14
void const char const char const int
sequence for_to_do_loop_conversion(forloop, statement)
Try to convert a C-like for-loop into a Fortran-like do-loop.
sequence for_to_while_loop_conversion(expression, expression, expression, statement, extensions)
Build a sequence with a while-loop from for-loop parameters.
char vcid_control_controlizer[]
There are some TODO !!! RK.
Definition: controlizer.c:40
static string c_test(test t, bool breakable)
bool empty_global_label_p(const char *gln)
Definition: entity_names.c:264
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
if(!(yy_init))
Definition: genread_lex.c:1029
statement instruction_to_statement(instruction)
Build a statement from a give instruction.
Definition: statement.c:597
void insert_control_in_arc(control c, control before, control after)
Insert a control node between 2 connected control nodes.
Definition: control.c:1299
void unlink_2_control_nodes(control source, control target)
Remove all edged between 2 control nodes.
Definition: control.c:1276
void display_linked_control_nodes(control c)
Display all the control nodes reached or reachable from c for debugging purpose.
Definition: control.c:629
void link_3_control_nodes(control c_test, control c_then, control c_else)
Add an edge between 2 control nodes.
Definition: control.c:1249
void link_2_control_nodes(control source, control target)
Add an edge between 2 control nodes.
Definition: control.c:1193
void remove_a_control_from_an_unstructured_without_relinking(control c)
It removes a control node from its successor and predecessor.
Definition: control.c:1031
void free_a_control_without_its_statement(control c)
Remove a control node without touching its statement, its predecessors and successors,...
Definition: control.c:1087
void remove_a_control_from_an_unstructured(control c)
Remove a control node from a control graph.
Definition: control.c:992
void print_control_nodes(list l)
Display identification of a list of control nodes.
Definition: control.c:589
void check_control_coherency(control c)
Test the coherency of a control node network from a control node.
Definition: control.c:487
void control_map_get_blocs(control c, list *l)
Build recursively the list of all controls reachable from a control of an unstructured.
Definition: control.c:75
void find_a_control_path(control b, control e, list *pp, list *vp, int dir)
Build recursively a control path from b to e.
Definition: control.c:107
static bool controlize_whileloop(control c_res, control succ, hash_table used_labels)
Computes the control graph of a Fortran or C while loop statement.
Definition: controlizer.c:847
static control make_conditional_control(statement st)
In C, we can have some "goto" inside a block from outside, that translates as any complex control gra...
Definition: controlizer.c:173
static bool covers_labels_p(statement st, hash_table used_labels)
Compute whether all the label references in a statement are in a given label name to statement list l...
Definition: controlizer.c:294
static statement whileloop_test(statement sl)
Generate a test statement ts for exiting loop sl.
static bool controlize_forloop(control c_res, control succ, hash_table used_labels)
Computes the control graph of a C for loop statement.
Definition: controlizer.c:723
bool controlize_statement(control c_res, control succ, hash_table used_labels)
Controlize a statement that is in a control node, that is restructure it to have a HCFG recursively (...
Definition: controlizer.c:2493
static hash_table Label_control
This maps label names to their (possible forward) control nodes.
Definition: controlizer.c:139
statement forloop_header(statement)
control find_or_create_exit_control_node(list ctls, control succ)
FI: remake of function above, incomplete backward approach, now obsolete because the forward approach...
Definition: controlizer.c:1809
static bool controlize_sequence(control c_res, control succ, hash_table used_labels)
Computes the control graph of a sequence statement.
Definition: controlizer.c:1914
static void update_used_labels(hash_table used_labels, string name, statement st)
Mark a statement as related to a label.
Definition: controlizer.c:235
static void init_label(string name, statement st)
INIT_LABEL puts the reference in the statement ST to the label NAME int the Label_statements table an...
statement forloop_inc(statement)
static void create_statements_of_labels(statement st)
Initialize the global Label_statements mapping for the module that associates for any label in the mo...
Definition: controlizer.c:437
static hash_table Label_statements
This maps label names to the list of statements where they appear (either as definition or reference)...
Definition: controlizer.c:126
static bool controlize_loop(control c_res, control succ, hash_table used_labels)
Computes the control graph of a Fortran do-loop statement.
Definition: controlizer.c:597
control find_exit_control_node(list ctls, control succ)
Find the exit node of a sub-CFG defined by the list of nodes ctls and by the first node to execute wh...
Definition: controlizer.c:1739
static bool controlize_repeatloop(control c_res, control succ, hash_table used_labels)
Computes the control graph of a C repeat until loop statement.
Definition: controlizer.c:990
#define ADD_PRED_AND_COPY_IF_NOT_ALREADY_HERE(pred, c)
static bool controlize_test(control c_res, control succ, hash_table used_labels)
Builds the control node of a test statement.
Definition: controlizer.c:2238
static void create_statements_of_label(statement st)
Update the global module-level Label_statements table according to the labels a statement references.
Definition: controlizer.c:398
static void move_declaration_control_node_declarations_to_statement(list ctls)
Move all the declarations found in a list of control to a given statement.
Definition: controlizer.c:1506
static void add_proper_successor_to_predecessor(control pred, control c_res)
static control get_label_control(string name)
Get the control node associated to a label name.
Definition: controlizer.c:207
#define ADD_PRED_IF_NOT_ALREADY_HERE(pred, c)
In C, we can have some "goto" inside a block from outside, that translate as any complex control grap...
static bool controlize_call(control c_res, control succ)
Controlize a call statement.
Definition: controlizer.c:2455
#define LABEL_TABLES_SIZE
Definition: controlizer.c:115
static hash_table union_used_labels(hash_table l1, hash_table l2)
Unions 2 hash maps that list statements referencing labels into one.
Definition: controlizer.c:270
statement forloop_test(statement)
static bool controlize_goto(control c_res, control succ, hash_table used_labels)
Deal with "goto" when building the HCFG.
Definition: controlizer.c:2362
statement hcfg(statement st)
Compute the hierarchical control flow graph (HCFG) of a statement.
Definition: controlizer.c:2621
#define UPDATE_CONTROL(c, s, pd, sc)
Update control c by setting its statement to s, by unioning its predecessor set with pd,...
statement unsugared_forloop_inc(statement sl)
Definition: controlizer.c:569
statement unsugared_loop_inc(statement sl)
Do an index increment instruction for do-loop unsugaring.
Definition: controlizer.c:554
statement unsugared_loop_test(statement sl)
Do a crude test of end of do-loop for do-loop unsugaring.
Definition: controlizer.c:502
statement unsugared_whileloop_test(statement sl)
Definition: controlizer.c:531
statement unsugared_whileloop_header(statement sl __attribute__((__unused__)))
Definition: controlizer.c:484
statement unsugared_forloop_header(statement sl)
Definition: controlizer.c:474
statement unsugared_forloop_test(statement sl)
Definition: controlizer.c:518
statement unsugared_loop_header(statement sl)
LOOP_HEADER, LOOP_TEST and LOOP_INC build the desugaring phases of a do-loop L for the loop header (i...
Definition: controlizer.c:463
void replace_entity(void *s, entity old, entity new)
per variable version of replace_entities.
Definition: replace.c:113
bool gen_true(__attribute__((unused)) gen_chunk *unused)
Return true and ignore the argument.
Definition: genClib.c:2780
instruction make_continue_instruction()
Creates a CONTINUE instruction, that is the FORTRAN nop, the ";" in C or the "pass" in Python for exa...
Definition: instruction.c:79
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
list gen_nreverse(list cp)
reverse a list in place
Definition: list.c:304
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
list gen_once(const void *vo, list l)
Prepend an item to a list only if it is not already in the list.
Definition: list.c:722
list gen_copy_seq(list l)
Copy a list structure.
Definition: list.c:501
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
list gen_last(list l)
Return the last element of a list.
Definition: list.c:578
bool gen_in_list_p(const void *vo, const list lx)
tell whether vo belongs to lx
Definition: list.c:734
#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
#define list_undefined
Undefined list definition :-)
Definition: newgen_list.h:69
sequence statement_sequence(statement)
Get the sequence of a statement sequence.
Definition: statement.c:1328
list statement_block(statement)
Get the list of block statements of a statement sequence.
Definition: statement.c:1338
loop statement_loop(statement)
Get the loop of a statement.
Definition: statement.c:1374
test statement_test(statement)
Get the test of a statement.
Definition: statement.c:1348
whileloop statement_whileloop(statement)
Get the whileloop of a statement.
Definition: statement.c:1383
statement statement_goto(statement)
Get the goto of a statement.
Definition: statement.c:1396
forloop statement_forloop(statement)
Get the forloop of a statement.
Definition: statement.c:1426
bool unlabelled_statement_p(statement)
Definition: statement.c:402
bool statement_test_p(statement)
Definition: statement.c:343
bool statement_sequence_p(statement)
Statement classes induced from instruction type.
Definition: statement.c:335
statement make_assign_statement(expression, expression)
Definition: statement.c:583
void fix_block_statement_declarations(statement)
s is assumed to be a block statement and its declarations field is assumed to be correct,...
Definition: statement.c:2930
statement make_continue_statement(entity)
Definition: statement.c:953
void fix_statement_attributes_if_sequence(statement)
Apply fix_sequence_statement_attributes() on the statement only if it really a sequence.
Definition: statement.c:2078
bool empty_comments_p(const char *)
Definition: statement.c:107
statement normalize_statement(statement)
Make (a bit more) sure that s is gen_defined_p in spite of poor decision for empty fields and that st...
Definition: statement.c:4035
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
list hash_get_default_empty_list(const hash_table h, const void *k)
Like hash_get() but returns an empty list instead of HASH_UNDEFINED_VALUE when a key is not found.
Definition: hash.c:475
void * hash_table_scan(hash_table htp, void *hentryp_arg, void **pkey, void **pval)
Definition: hash.c:844
struct _newgen_struct_control_ * control
enum language_utype get_prettyprint_language_tag()
Definition: language.c:67
#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 exit(code)
Definition: misc-local.h:54
#define abort()
Definition: misc-local.h:53
#define STATEMENT_ORDERING_UNDEFINED
mapping.h inclusion
Definition: newgen-local.h:35
string concatenate(const char *,...)
Return the concatenation of the given strings.
Definition: string.c:183
#define DEFINE_LOCAL_STACK(name, type)
#define HASH_MAP(k, v, code, ht)
Definition: newgen_hash.h:60
@ hash_chunk
Definition: newgen_hash.h:32
@ hash_string
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_put_or_update(h, k, v)
Definition: newgen_hash.h:80
#define string_undefined
Definition: newgen_types.h:40
#define true
Definition: newgen_types.h:81
struct cons * list
Definition: newgen_types.h:106
void print_expression(expression e)
no file descriptor is passed to make is easier to use in a debugging stage.
Definition: expression.c:58
string get_comment_sentinel()
Start a single line comment.
Definition: misc.c:154
void set_bool_property(const char *, bool)
#define GREATER_THAN_OPERATOR_NAME
#define PLUS_OPERATOR_NAME
#define C_NOT_OPERATOR_NAME
#define is_instruction_block
soft block->sequence transition
#define empty_comments
Empty comments (i.e.
#define NOT_OPERATOR_NAME
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 entity_to_module_entity(entity e)
Find the enclosing module of an entity.
Definition: entity.c:2053
entity entity_empty_label(void)
Definition: entity.c:1105
bool entity_empty_label_p(entity e)
Definition: entity.c:666
entity entity_intrinsic(const char *name)
FI: I do not understand this function name (see next one!).
Definition: entity.c:1292
const char * label_local_name(entity e)
END_EOLE.
Definition: entity.c:604
bool expression_call_p(expression e)
Definition: expression.c:415
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 expression_reference_p(expression e)
Test if an expression is a reference.
Definition: expression.c:528
bool entity_static_variable_p(entity)
return true if the entity is declared with the keyword static
Definition: variable.c:1146
expression variable_initial_expression(entity)
Returns a copy of the initial (i.e.
Definition: variable.c:1899
entity generic_clone_variable_with_unique_name(entity, statement, string, string, entity, bool)
clone a variable with a new name.
Definition: variable.c:509
#define loop_body(x)
Definition: ri.h:1644
#define normalized_undefined
Definition: ri.h:1745
#define control_undefined
Definition: ri.h:916
#define CONTROL_(x)
Definition: ri.h:913
#define forloop_initialization(x)
Definition: ri.h:1366
#define control_predecessors(x)
Definition: ri.h:943
#define range_upper(x)
Definition: ri.h:2290
#define forloop_increment(x)
Definition: ri.h:1370
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define instruction_goto(x)
Definition: ri.h:1526
#define value_unknown_p(x)
Definition: ri.h:3077
#define test_false(x)
Definition: ri.h:2837
#define whileloop_evaluation(x)
Definition: ri.h:3166
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
#define instruction_undefined_p(x)
Definition: ri.h:1455
#define CONTROL(x)
CONTROL.
Definition: ri.h:910
@ is_syntax_call
Definition: ri.h:2693
#define range_increment(x)
Definition: ri.h:2292
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define instruction_forloop_p(x)
Definition: ri.h:1536
#define instruction_undefined
Definition: ri.h:1454
#define statement_label(x)
Definition: ri.h:2450
#define expression_undefined
Definition: ri.h:1223
@ is_instruction_goto
Definition: ri.h:1473
@ is_instruction_unstructured
Definition: ri.h:1475
@ is_instruction_whileloop
Definition: ri.h:1472
@ is_instruction_expression
Definition: ri.h:1478
@ is_instruction_test
Definition: ri.h:1470
@ is_instruction_call
Definition: ri.h:1474
@ is_instruction_forloop
Definition: ri.h:1477
@ is_instruction_loop
Definition: ri.h:1471
#define instruction_tag(x)
Definition: ri.h:1511
#define whileloop_label(x)
Definition: ri.h:3164
#define entity_name(x)
Definition: ri.h:2790
#define ENTITY_(x)
Definition: ri.h:2758
#define test_true(x)
Definition: ri.h:2835
#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 instruction_forloop(x)
Definition: ri.h:1538
#define control_successors(x)
Definition: ri.h:945
#define control_undefined_p(x)
Definition: ri.h:917
#define instruction_expression(x)
Definition: ri.h:1541
#define instruction_whileloop(x)
Definition: ri.h:1523
#define range_lower(x)
Definition: ri.h:2288
#define whileloop_body(x)
Definition: ri.h:3162
#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 statement_decls_text(x)
Definition: ri.h:2462
#define loop_range(x)
Definition: ri.h:1642
#define forloop_condition(x)
Definition: ri.h:1368
#define control_statement(x)
Definition: ri.h:941
#define whileloop_condition(x)
Definition: ri.h:3160
#define call_undefined
Definition: ri.h:685
#define statement_number(x)
Definition: ri.h:2452
#define evaluation_before_p(x)
Definition: ri.h:1159
#define forloop_body(x)
Definition: ri.h:1372
#define sequence_undefined_p(x)
Definition: ri.h:2339
@ is_language_fortran
Definition: ri.h:1566
@ is_language_fortran95
Definition: ri.h:1568
@ is_language_c
Definition: ri.h:1567
#define loop_index(x)
Definition: ri.h:1640
#define statement_undefined
Definition: ri.h:2419
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
#define entity_initial(x)
Definition: ri.h:2796
Pvecteur cp
pointeur sur l'egalite ou l'inegalite courante
Definition: sc_read.c:87
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
char * strdup()
return(s1)
#define ifdebug(n)
Definition: sg.c:47
The structure used to build lists in NewGen.
Definition: newgen_list.h:41