PIPS
old_controlizer.c
Go to the documentation of this file.
1 /*
2 
3  $Id: old_controlizer.c 23065 2016-03-02 09:05:50Z coelho $
4 
5  Copyright 1989-2016 MINES ParisTech
6 
7  This file is part of PIPS.
8 
9  PIPS is free software: you can redistribute it and/or modify it
10  under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  any later version.
13 
14  PIPS is distributed in the hope that it will be useful, but WITHOUT ANY
15  WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  FITNESS FOR A PARTICULAR PURPOSE.
17 
18  See the GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with PIPS. If not, see <http://www.gnu.org/licenses/>.
22 
23 */
24 #ifdef HAVE_CONFIG_H
25  #include "pips_config.h"
26 #endif
27 
28 #ifndef lint
29 char vcid_control_old_controlizer[] = "$Id: old_controlizer.c 23065 2016-03-02 09:05:50Z coelho $";
30 #endif /* lint */
31 
32 /* \defgroup controlizer Controlizer phase to build the Hierarchical Control Flow Graph
33 
34  It computes the Hierarchical Control Flow Graph of a given statement
35  according the control hierarchy.
36 
37  It is used in PIPS to transform the output of the parsers (the
38  PARSED_CODE resource) into HCFG code (the PARSED_CODE resource).
39 
40  For example if there are some "goto" in a program, it will encapsulated
41  the unstructured graph in an "unstructured" object covering all the
42  goto and their label targets to localize the messy part and this object
43  is put into a normal statement so that seen from above the code keep a
44  good hierarchy.
45 
46  In PIPS the RI (Internal Representation or AST) is quite simple so that
47  it is easy to deal with. But the counterpart is that some complex
48  control structures need to be "unsugared". For example
49  switch/case/break/default are transformed into tests, goto and label,
50  for(;;) with break or continue are transformed into while() loops with
51  goto/label, and so on.
52 
53  There are other phases in PIPS that can be used later to operate on the
54  CODE to optimize it further.
55 
56 
57  WARNINGS:
58 
59  . Temporary locations malloc()ed while recursing in the process are
60  often not freed (to be done latter ... if required)
61 
62  . The desugaring of DO loops is not perfect (in case of side-effects
63  inside loop ranges.
64 
65  Pierre Jouvelot (27/5/89) <- this is a French date :-)
66 
67  MODIFICATIONS (historian fun):
68 
69  . hash_get interface modification: in one hash table an undefined key
70  meant an error; in another one an undefined key was associated to
71  the default value empty_list; this worked as long as NULL was returned
72  as NOT_FOUND value (i.e. HASH_UNDEFINED_VALUE); this would work again
73  if HASH_UNDEFINED_VALUE can be user definable; Francois Irigoin, 7 Sept. 90
74 
75  @{
76 */
77 
78 /*
79  * $Id: old_controlizer.c 23065 2016-03-02 09:05:50Z coelho $
80  */
81 
82 #include <stdio.h>
83 #include <strings.h>
84 
85 #include "linear.h"
86 
87 #include "genC.h"
88 #include "ri.h"
89 #include "ri-util.h"
90 #include "workspace-util.h"
91 #include "prettyprint.h"
92 #include "control.h"
93 #include "properties.h"
94 
95 #include "misc.h"
96 
97 #include "constants.h"
98 
99 #include "text-util.h"
100 
101 #define LABEL_TABLES_SIZE 10
102 
103 static bool controlize(statement st, control pred, control succ, control c_res, hash_table used_labels);
104 
105 /* UNREACHABLE is the hook used as a predecessor of statements that are
106  following a goto. The list of unreachable statements is kept in the
107  successors list. */
108 
110 
111 /* LABEL_STATEMENTS maps label names to the list of statements where
112  they appear (either as definition or reference). */
113 
115 
116 /* LABEL_CONTROL maps label names to their (possible forward) control
117  nodes. */
118 
120 
121 
122 /* In C, we can have some "goto" inside a block from outside, that
123  translate as any complex control graph into an "unstructured" in the
124  PIPS jargon.
125 
126  Unfortunately, that means it break the structured block nesting that
127  may carry declarations with the scoping information.
128 
129  So we need to track this scope information independently of the control
130  graph. This is the aim of this declaration scope stack that is used to
131  track scoping during visiting the RI.
132 */
133 DEFINE_LOCAL_STACK(scoping_statement, statement)
134 
135 
136 /* FI -> PJ:
137  *
138  * The naming for ADD_PRED et ADD_SUCC is misleading. ADD_SUCC is in
139  * fact a SET_SUCC. ADD_PRED is UNION_PRED. When used to Newgen but
140  * not to control, ADD_SUCC reduces readability.
141  *
142  * Furthermore, ADD_SUCC() is dangerous when used on a control that is
143  * a test since the position in the successor list is
144  * significant. true successors are in the odd positions (the first
145  * element is of rank one). false successors are in the odd position.
146  */
147 
148 /* Add control "pred" to the predecessor set of control c if not already
149  here */
150 #define ADD_PRED_IF_NOT_ALREADY_HERE(pred,c) (gen_once(pred,control_predecessors(c)))
151 #define ADD_PRED_AND_COPY_IF_NOT_ALREADY_HERE(pred,c) (gen_once(pred,gen_copy_seq(control_predecessors(c))))
152 
153 /* Update control c by setting its statement to s, by unioning its predecessor
154  * set with pd, and by setting its successor set to sc (i.e. previous successors
155  * are lost, but not previous predecessors).
156  *
157  * Note: This macro does not preserve the consistency of the control
158  * flow graph as pd's successor list and sc predecessor list are not
159  * updated.
160  */
161 #define UPDATE_CONTROL(c,s,pd,sc) { \
162  control_statement(c)=s; \
163  MAPL(preds, {control_predecessors(c) = \
164  ADD_PRED_IF_NOT_ALREADY_HERE(CONTROL(CAR(preds)), c);}, \
165  pd); \
166  gen_free_list(pd);\
167  gen_free_list( control_successors(c));\
168  control_successors(c)=sc; \
169  }
170 
171 #define PREDS_OF_SUCCS 1
172 #define SUCCS_OF_PREDS 2
173 
174 /* PATCH_REFERENCES replaces all occurrences of FNODE by TNODE in the
175  predecessors or successors lists of its predecessors
176  or successors list (according to HOW, PREDS_OF_SUCCS or
177  SUCCS_OF_PREDS).
178 
179  Move all the connection of:
180 
181  - the predecessors of FNODE to point to TNODE
182 
183  - or the successors of FNODE to point from TNODE
184  */
185 static void patch_references(how, fnode, tnode)
186 int how;
187 control fnode, tnode;
188 {
189  MAPL(preds, {
190  control pred = CONTROL(CAR(preds));
191 
192  MAPL(succs, {
193  if(CONTROL(CAR(succs)) == fnode)
194  CONTROL_(CAR(succs)) = tnode;
195  }, (how == SUCCS_OF_PREDS) ?
196  control_successors(pred) :
197  control_predecessors(pred));
198  }, (how == SUCCS_OF_PREDS) ?
199  control_predecessors(fnode) :
200  control_successors(fnode));
201 }
202 
203 
204 /* Make a control node from a statement if needed.
205 
206  It is like make_control() except when the statement @param st
207  has a label and is thus already in Label_control
208 
209  @return the new (in the case of a statement without a label) or already
210  associated (in the case of a statement with a label) control node with
211  the statement
212 
213  It returns NULL if the statement has a label but it is not associated to
214  any control node yet
215  */
217  string label = entity_name(statement_label(st));
218 
219  if (empty_global_label_p(label))
220  /* No label, so there cannot be a control already associated by a
221  label */
222  return make_control(st, NIL, NIL);
223  else
224  /* Get back the control node associated with this statement
225  label. Since we store control object in this hash table, use
226  cast. We rely on the fact that NIL for a list is indeed
227  NULL... */
229 }
230 
231 
232 /* Get the control node associated to a label name
233 
234  It looks for the label name into the Label_control table.
235 
236  The @p name must be the complete entity name, not a local or a user name.
237 
238  @param name is the string name of the label entity
239 
240  @return the associated control
241 */
242 static control get_label_control(string name) {
243  control c;
244 
245  pips_assert("label is not the empty label", !empty_global_label_p(name)) ;
246  c = (control)hash_get(Label_control, name);
247  pips_assert("c is defined", c != (control) HASH_UNDEFINED_VALUE);
248  pips_assert("c is a control", check_control(c));
249  ifdebug(2) {
251  }
252  return(c);
253 }
254 
255 
256 /* Add the reference to the label NAME in the
257  statement ST. A used_label is a hash_table that maps the label
258  name to the list of statements that references it.
259 
260  A statement can appear many times for a label
261 
262  @param used_labels is the hash table used to record the statements
263  related to a label
264 
265  @param name is the label entity name
266 
267  @param st is the statement to be recorded as related to the label
268 */
269 static void update_used_labels(hash_table used_labels,
270  string name,
271  statement st) {
272  list sts ;
273 
274  /* Do something only of there is a label: */
275  if (!empty_global_label_p(name)) {
276  list new_sts;
277  /* Get a previous list of statements related with this label: */
278  sts = hash_get_default_empty_list(used_labels, name) ;
279  /* Add the given statement to the list */
280  new_sts = CONS(STATEMENT, st, sts);
281  if (hash_defined_p(used_labels, name))
282  /* If there was already something associated to the label, register
283  the new list: */
284  hash_update(used_labels, name, new_sts);
285  else
286  /* Or create a new entry: */
287  hash_put(used_labels, name, new_sts);
288  debug(5, "update_used_labels", "Reference to statement %d seen\n",
289  statement_number( st )) ;
290  }
291 }
292 
293 
294 /* Unions 2 used-label hash maps
295 
296  @param l1 is an hash map
297 
298  @param l2 is another hash map
299 
300  @returns the union of @p l1 and @p l2 interpreted as in the context of
301  update_used_labels()
302 */
304  hash_table l2) {
305  HASH_MAP(name, sts, {
306  FOREACH(STATEMENT, s, sts) {
307  update_used_labels(l1, name, s);
308  };
309  }, l2);
310  return l1;
311 }
312 
313 
314 /* Compute whether all the label references in a statement are in a given
315  label name to statement list mapping.
316 
317  @param st is the statement we want to check if it owns all allusion to
318  the given label name in the @p used_labels mapping
319 
320  @param used_labels is a hash table mapping a label name to a list of
321  statement that use it, as their label or because it is a goto to it
322 
323  @return true if all the label allusion in @p st are covered by the @p
324  used_labels mapping.
325 */
326 static bool covers_labels_p(statement st,
327  hash_table used_labels) {
328  // To quiet gcc
329  pips_assert("Statement st is defined", !statement_undefined_p(st));
330  /* ifdebug(5) { */
331  /* pips_debug(5, "Statement %td (%p): \n ", statement_number(st), st); */
332  /* print_statement(st); */
333  /* } */
334  /* For all the labels in used_labels: */
335  HASH_MAP(name, sts, {
336  /* The statements using label name in used_labels: */
337  list stats = (list) sts;
338 
339  /* For all the statements associated to label name: */
341  def,
343  bool found = false;
344  /* Verify that def is in all the statements associated to the
345  label name according to used_labels. */
346  FOREACH(STATEMENT, st, stats) {
347  found |= st == def;
348  }
349 
350  if (!found) {
351  pips_debug(5, "does not cover label %s\n", (char *) name);
352  /* Not useful to go on: */
353  return(false);
354  }
355  }
356  }, used_labels);
357 
358  ifdebug(5)
359  fprintf(stderr, "covers its label usage\n");
360 
361  return(true);
362 }
363 
364 
366 {
367  /* Replaces the following statement: */
368  /* control_successors(pred) = ADD_SUCC(c_res, pred); */
369 
370  /* Usually, too much of a mess: do not try to be too strict! */
371  /*
372  if(statement_test_p(control_statement(pred))) {
373  control_successors(pred) = gen_nconc(control_successors(pred),
374  CONS(CONTROL, c_res, NIL));
375  pips_assert("While building the CFG, "
376  "a test control node may have one or two successors",
377  gen_length(control_successors(pred))<=2);
378  }
379  else {
380  if(gen_length(control_successors(pred))==0) {
381  control_successors(pred) = CONS(CONTROL, c_res, NIL);
382  }
383  else if(gen_length(control_successors(pred))==1) {
384  if(gen_in_list_p(succ,control_successors(pred))) {
385  ;
386  }
387  else {
388  pips_internal_error("Two or more candidate successors "
389  "for a standard statement: %p and %p\n",
390  succ, CONTROL(CAR(control_successors(pred))));
391  }
392  }
393  else {
394  pips_internal_error("Two or more successors for non-test node %p",
395  pred);
396  }
397  }
398  */
399 
401  if(!gen_in_list_p(c_res, control_successors(pred))) {
403  CONS(CONTROL, c_res, NIL));
404  }
405  pips_assert("While building the CFG, "
406  "a test control node may have one or two successors",
407  gen_length(control_successors(pred))<=2);
408  }
409  else {
410  /* Do whatever was done before and let memory leak! */
412  control_successors(pred) = CONS(CONTROL, c_res, NIL);
413  }
414 }
415 
416 
417 /* CONTROLIZE_CALL controlizes the call C of statement ST in C_RES. The deal
418  is to correctly manage STOP; since we don't know how to do it, so we
419  assume this is a usual call with a continuation !!
420 
421  To avoid non-standard successors, IO statement with multiple
422  continuations are not dealt with here. The END= and ERR= clauses are
423  simulated by hidden tests. */
424 
425 static bool controlize_call(statement st,
426  control pred,
427  control succ,
428  control c_res)
429 {
430  pips_debug(5, "(st = %p, pred = %p, succ = %p, c_res = %p)\n",
431  st, pred, succ, c_res);
432 
434  CONS(CONTROL, succ, NIL));
435 
436  /* control_successors(pred) = ADD_SUCC(c_res, pred); */
439  return(false);
440 }
441 
442 /* LOOP_HEADER, LOOP_TEST and LOOP_INC build the desugaring phases of a
443  do-loop L for the loop header (i=1), the test (i<10) and the increment
444  (i=i+1). */
445 
447 {
448  loop l = statement_loop(sl);
450 
452 
455 
456  return hs;
457 }
458 
460 {
461  loop l = statement_loop(sl);
463  string cs = string_undefined;
469  NIL)));
474  string csl = statement_comments(sl);
475  string prev_comm = empty_comments_p(csl)? /* empty_comments */ strdup("") : strdup(csl);
476  const char* lab;
477 
479  lab = ""; // FI: to be replaced by a symbolic constant
480  else
481  lab = label_local_name(loop_label(l));
482 
484  switch(lt) {
485  case is_language_fortran:
487  cs = strdup(concatenate(prev_comm,
488  comment_sentinel(lt),
489  " DO loop ",
490  lab,
491  " with exit had to be desugared\n",
492  NULL));
493  break;
494  case is_language_c:
495  cs = prev_comm;
496  break;
497  default:
498  pips_internal_error("This language is not handled !");
499  break;
500  }
501 
503  statement_number(sl),
505  cs,
508  return ts;
509 }
510 
512 {
513  loop l = statement_loop(sl);
516  call c = make_call(entity_intrinsic(PLUS_OPERATOR_NAME), // Even for C code?
518  I,
521  NIL)));
522  expression I_plus_one =
526 
527  is = make_assign_statement(II, I_plus_one);
529 
530  return is;
531 }
532 
533 /* CONTROLIZE_LOOP computes in C_RES the control graph of the loop L (of
534  statement ST) with PREDecessor and SUCCessor. */
535 
536 static bool controlize_loop(st, l, pred, succ, c_res, used_labels)
537 statement st;
538 loop l;
539 control pred, succ;
540 control c_res;
541 hash_table used_labels;
542 {
543  hash_table loop_used_labels = hash_table_make(hash_string, 0);
547  bool controlized;
548 
549  pips_debug(5, "(st = %p, pred = %p, succ = %p, c_res = %p)\n",
550  st, pred, succ, c_res);
551 
552  controlize(loop_body(l), c_test, c_inc, c_body, loop_used_labels);
553 
554  if(covers_labels_p(loop_body(l),loop_used_labels)) {
555  loop new_l = make_loop(loop_index(l),
556  loop_range(l),
557  control_statement(c_body),
558  loop_label(l),
559  loop_execution(l),
560  loop_locals(l));
561 
562  st = normalize_statement(st);
563  UPDATE_CONTROL(c_res,
565  statement_number(st),
567  statement_comments(st),
573  CONS(CONTROL, succ, NIL)) ;
574  controlized = false;
576  }
577  else {
580  CONS(CONTROL, c_res, CONS(CONTROL, c_inc, NIL)),
582  CONS(CONTROL, succ, CONS(CONTROL, c_body, NIL));
583  control_statement(c_inc) = loop_inc(st);
585  UPDATE_CONTROL(c_res,
586  loop_header(st),
588  CONS(CONTROL, c_test, NIL));
589  controlized = true ;
591  }
593  /* control_successors(pred) = ADD_SUCC(c_res, pred); */
594 
595  union_used_labels( used_labels, loop_used_labels);
596  hash_table_free(loop_used_labels);
597 
598  pips_debug(5, "Exiting\n");
599 
600  return(controlized);
601 }
602 ␌
603 
604 /* Generate a test statement ts for exiting loop sl.
605  * There should be no sharing between sl and ts.
606  */
608 {
611  string cs = string_undefined;
612  call c = call_undefined;
613 
614  switch (get_prettyprint_language_tag()) {
615  case is_language_fortran:
619  NIL));
620  break;
621  case is_language_c:
625  NIL));
626  break;
628  pips_internal_error("Need to update F95 case");
629  break;
630  default:
631  pips_internal_error("Language unknown !");
632  break;
633  }
634 
639  string csl = statement_comments(sl);
640  /* string prev_comm = empty_comments_p(csl)? "" : strdup(csl); */
641  string prev_comm = empty_comments_p(csl)? empty_comments /* strdup("") */ : strdup(csl);
642  const char* lab ;
643 
645  switch (lt) {
646  case is_language_fortran:
649  cs = strdup(concatenate(prev_comm,
650  comment_sentinel(lt),
651  " DO WHILE loop ",
652  "with GO TO exit had to be desugared\n",
653  NULL));
654  } else {
656  cs = strdup(concatenate(prev_comm,
657  comment_sentinel(lt),
658  " DO WHILE loop ",
659  lab,
660  " with GO TO exit had to be desugared\n",
661  NULL));
662  }
663  break;
664  case is_language_c:
665  cs = prev_comm;
666  break;
667  default:
668  pips_internal_error("Language unknown !");
669  break;
670  }
671 
672 
674  statement_number(sl),
676  cs,
679 
680  return ts;
681 }
682 
683 
684 /* CONTROLIZE_WHILELOOP computes in C_RES the control graph of the loop L (of
685  * statement ST) with PREDecessor and SUCCessor
686  *
687  * Derived by FI from controlize_loop()
688  */
689 
690 /* NN : What about other kind of whileloop, evaluation = after ? TO BE IMPLEMENTED */
691 
692 static bool controlize_whileloop(st, l, pred, succ, c_res, used_labels)
693 statement st;
694 whileloop l;
695 control pred, succ;
696 control c_res;
697 hash_table used_labels;
698 {
699  hash_table loop_used_labels = hash_table_make(hash_string, 0);
701  bool controlized;
702 
703  pips_debug(5, "(st = %p, pred = %p, succ = %p, c_res = %p)\n",
704  st, pred, succ, c_res);
705 
706  controlize(whileloop_body(l), c_res, c_res, c_body, loop_used_labels);
707 
708  if(covers_labels_p(whileloop_body(l),loop_used_labels)) {
710  control_statement(c_body),
711  whileloop_label(l),
713 
714  /* The edges between c_res and c_body, created by the above call to
715  * controlize are useless. The edge succ
716  * from c_res to c_body is erased by the UPDATE_CONTROL macro.
717  */
718  gen_remove(&control_successors(c_body), c_res);
719  gen_remove(&control_predecessors(c_body), c_res);
720  gen_remove(&control_predecessors(c_res), c_body);
721 
722  st = normalize_statement(st);
723  UPDATE_CONTROL(c_res,
725  statement_number(st),
729  new_l),
734  CONS(CONTROL, succ, NIL));
735  controlized = false;
736  }
737  else {
738  control_statement(c_res) = whileloop_test(st);
739  /* control_predecessors(c_res) =
740  CONS(CONTROL, pred, control_predecessors(c_res)); */
741  /* ADD_PRED(pred, c_res); */
742  control_predecessors(c_res) =
743  gen_once(pred, control_predecessors(c_res));
744  control_successors(c_res) =
745  CONS(CONTROL, succ, control_successors(c_res));
746  controlized = true ;
747  /* Cannot be consistent yet! */
748  /* ifdebug(5) check_control_coherency(c_res); */
749  }
752  /* control_successors(pred) = ADD_SUCC(c_res, pred); */
753 
755 
756  union_used_labels( used_labels, loop_used_labels);
757  hash_table_free(loop_used_labels);
758 
759  pips_debug(5, "Exiting\n");
760 
761  return(controlized);
762 }
763 
764 
766 {
770 
771  return hs;
772 }
773 
774 
776 {
778  expression cond = forloop_condition(l);
781  copy_expression(cond),
782  NIL));
787  string csl = statement_comments(sl);
788  string cs = empty_comments_p(csl)? empty_comments /* strdup("") */ : strdup(csl);
789 
791  statement_number(sl),
793  cs,
796 
797  /* ifdebug(8) { */
798  /* pips_debug(8, "Condition expression: "); */
799  /* print_expression(cond); */
800  /* } */
801 
802  return ts;
803 }
804 
805 
807 {
809  expression inc = forloop_increment(l);
812 
813  /* ifdebug(8) { */
814  /* pips_debug(8, "Increment expression: "); */
815  /* print_expression(inc); */
816  /* } */
817 
818  return is;
819 }
820 
821 
822 static bool controlize_forloop(st, l, pred, succ, c_res, used_labels)
823 statement st;
824 forloop l;
825 control pred, succ;
826 control c_res;
827 hash_table used_labels;
828 {
829  hash_table loop_used_labels = hash_table_make(hash_string, 0);
833  bool controlized = false; /* To avoid gcc warning about possible
834  non-initialization */
835 
836  pips_debug(5, "(st = %p, pred = %p, succ = %p, c_res = %p)\n",
837  st, pred, succ, c_res);
838  ifdebug(1) {
840  }
841 
842  controlize(forloop_body(l), c_test, c_inc, c_body, loop_used_labels);
843 
844  ifdebug(1) {
846  }
847 
848  if (covers_labels_p(forloop_body(l),loop_used_labels)) {
850 
851  /* Try an unsafe conversion to a Fortran style DO loop: it assumes
852  that the loop body does not define the loop index, but effects are
853  not yet available when the controlizer is run. */
854  if(get_bool_property("FOR_TO_DO_LOOP_IN_CONTROLIZER")) {
855  forloop_body(l)= control_statement(c_body);
856  sequence new_l = for_to_do_loop_conversion(l,st);
857 
858  if(!sequence_undefined_p(new_l)) {
859  ni = make_instruction_sequence( new_l);
860  }
861  }
862 
863  /* If the DO conversion has failed, the WHILE conversion may be requested */
864  if(instruction_undefined_p(ni)) {
865  if(get_bool_property("FOR_TO_WHILE_LOOP_IN_CONTROLIZER")) {
866  /* As a sequence cannot carry comments, the for loop comments
867  are moved to the while loop */
871  control_statement(c_body),
873 
874  /* These three fields have been re-used or freed by the previous call */
878 
879  ni = make_instruction_sequence(wls);
880  }
881  else {
885  control_statement(c_body));
886 
887  ni = make_instruction_forloop(new_l);
888  }
889  }
890 
891  gen_remove(&control_successors(c_body), c_res);
892  gen_remove(&control_predecessors(c_body), c_res);
893  gen_remove(&control_predecessors(c_res), c_body);
894 
895  /* Quite a lot of sharing between st and d_st*/
896  st = normalize_statement(st);
898  statement_number(st),
901  ni,
905  ifdebug(1) {
908  }
909  /* Since we may have replaced a statement that may have comments and
910  labels by a sequence, do not forget to forward them where they can
911  be: */
913  ifdebug(1) {
915  }
916 
917  UPDATE_CONTROL(c_res,
918  d_st,
920  CONS(CONTROL, succ, NIL));
921  controlized = false;
923  }
924  else /* The for loop cannot be preserved as a control structure*/
925  {
926  /* NN : I do not know how to deal with this, the following code does not always work
927 
928  pips_internal_error("Forloop with goto not implemented yet");*/
929 
933  CONS(CONTROL, c_res, CONS(CONTROL, c_inc, NIL)),
935  CONS(CONTROL, succ, CONS(CONTROL, c_body, NIL));
937  control_statement(c_inc) = forloop_inc(st);
939  UPDATE_CONTROL(c_res,
940  forloop_header(st),
942  CONS(CONTROL, c_test, NIL));
943  controlized = true ;
945  }
947  /* control_successors(pred) = ADD_SUCC(c_res, pred); */
948 
950 
951  union_used_labels( used_labels, loop_used_labels);
952  hash_table_free(loop_used_labels);
953 
954  pips_debug(5, "Exiting\n");
955 
956  return(controlized);
957 }
958 
959 
960 /* Move all the declarations found in a list of control to a given
961  statement
962 
963  @ctls is a list of control nodes
964 
965  It is useful in the controlizer to keep scoping of declarations even
966  with unstructured that may destroy the variable scoping rules.
967 
968  If there are conflict names on declarations, they are renamed.
969 
970  It relies on correct calls to push_declarations()/push_declarations()
971  before to track where to put the declarations.
972 
973  FI: let's assume they have become scoping_statement_push/pop...
974 */
975 static void
977  statement s = scoping_statement_head();
978  list declarations = statement_declarations(s);
979  statement s_above = scoping_statement_nth(2);
980  pips_debug(2, "Dealing with block statement %p included into block"
981  " statement %p\n", s, s_above);
982  if (s_above==NULL)
983  /* No block statement above, so it is hard to move something there :-) */
984  return;
985 
986  list declarations_above = statement_declarations(s_above);
987  list new_declarations = NIL;
988  /* The variables created in case of name conflict*/
989  list new_variables = NIL;
990  hash_table old_to_new_variables = hash_table_make(hash_chunk, 0);
991 
992  /* Look for conflicting names: */
993  FOREACH(ENTITY, e, declarations) {
994  const char * name = entity_user_name(e);
995  bool conflict = false;
996  FOREACH(ENTITY, e_above, declarations_above) {
997  const char * name_above = entity_user_name(e_above);
998  pips_debug(2, "Comparing variables %s and %s\n",
999  entity_name(e), entity_name(e_above));
1000 
1001  if (strcmp(name, name_above) == 0) {
1002  /* There is a conflict name between a declaration in the current
1003  statement block and one in the statement block above: */
1004  conflict = true;
1005  break;
1006  }
1007  }
1008  entity v;
1009  if (conflict) {
1010  pips_debug(2, "Conflict on variable %s\n", entity_name(e));
1011 
1012  /* Create a new variable with a non conflicting name: */
1014  s_above,
1015  "",
1016  "_",
1018  new_variables = gen_entity_cons(v , new_variables);
1019  hash_put_or_update(old_to_new_variables, e, v);
1020  }
1021  else
1022  v = e;
1023  /* Add the inner declaration to the upper statement later */
1024  new_declarations = gen_entity_cons(v , new_declarations);
1025  }
1026  /* Remove the inner declaration from the inner statement block:
1027  */
1030 
1031  /* Add all the declarations to the statement block above and keep the
1032  same order: */
1033  statement_declarations(s_above) = gen_nconc(declarations_above,
1034  gen_nreverse(new_declarations));
1035 
1036  /* Replace all the references on old variables to references to the new
1037  ones in all the corresponding control nodes by in the code */
1038  HASH_MAP(old, new, {
1039  FOREACH(CONTROL, c, ctls) {
1041  replace_entity(s, old, new);
1042  }
1043  /* We should free in some way the old variable... */
1044  }, old_to_new_variables);
1045  hash_table_free(old_to_new_variables);
1046 }
1047 
1048 
1049 /* Take a list of controls @p ctls coming from a controlize_list() and
1050  compact the successive statements, i.e. concatenates (i=1) followed by
1051  (j=2) in a single control with a block statement (i=1;j=2).
1052 
1053  @return the last control node of the remaining control list. It may not
1054  be @p c_end if this one has been fused with a previous control node.
1055 
1056  Added a set to avoid investigating a removed node. Many memory leaks
1057  removed. RK.
1058 
1059  This procedure cannot be replaced by fuse_sequences_in_unstructured()
1060  since the API is not the same and because of various goto from/to
1061  outside, this control list may belong to quite larger unstructured.
1062  */
1064  control c_end)
1065 {
1066  control c_res;
1067  set processed_nodes;
1068  /* Pointer to the end of the current unstructured: */
1069  control c_last = c_end ;
1070 
1071  ifdebug(5) {
1072  pips_debug(5, "Begin with list c_end %p, ctls:", c_end);
1074  fprintf(stderr, "\n");
1075  }
1076 
1077  if (ENDP(ctls)) {
1078  /* Empty statement control list, clearly nothing to do: */
1079  return c_last;
1080  }
1081 
1082  processed_nodes = set_make(set_pointer);
1083 
1084  /* This is the iterator on the first element of the control list: */
1085  c_res = CONTROL(CAR(ctls));
1086 
1087  for(ctls = CDR(ctls); !ENDP(ctls); ctls = CDR(ctls)) {
1088  cons *succs, *succs_of_succ;
1089  instruction i, succ_i;
1090  statement st, succ_st;
1091  control succ;
1092 
1093  if (set_belong_p(processed_nodes, (char *) c_res)) {
1094  /* Do not reprocess an already seen node. */
1095  c_res = CONTROL(CAR(ctls));
1096  continue;
1097  }
1098 
1099  if (gen_length(succs=control_successors(c_res)) != 1 ||
1100  gen_length(control_predecessors(succ=CONTROL(CAR(succs)))) != 1 ||
1101  gen_length(succs_of_succ=control_successors(succ)) != 1 ||
1102  CONTROL(CAR(succs_of_succ)) == c_res ) {
1103  /* We are at a non structured node or at the exit: keep
1104  the node and go on inspecting next node from the
1105  list. RK */
1106  c_res = CONTROL(CAR(ctls));
1107  continue;
1108  }
1109 
1110  st = control_statement(c_res) ;
1111 
1112  // NL: If it's uncomment, it remove some pragma in some case, I don't
1113  // know why. For instance C_syntax/pragma05
1114  // // if there is an extension for the statement don't make fusion
1115  // if (!empty_extensions_p(statement_extensions(st))) {
1116  // c_res = CONTROL(CAR(ctls));
1117  // continue;
1118  // }
1119 
1120  ifdebug(1) {
1122  pips_assert("st is a block or a continue or st carries no delarations",
1123  statement_block_p(st)
1124  || continue_statement_p(st)
1125  || ENDP(statement_declarations(st)));
1126  }
1127  /* Ok, succ is defined. RK */
1128  succ_st = control_statement(succ);
1129  set_add_element(processed_nodes, processed_nodes, (char *) succ);
1130 
1134  /* Verify if the control node is not reachable on its label: */
1136  string ln = entity_name(l);
1137  control c = get_label_control(ln);
1138  if(!control_undefined_p(c)) {
1139  /* There is a label that may be used on this control node: do
1140  not fuse */
1141  if (c==succ) {
1142  /* This happens quite often in Syntax with no
1143  consequences; this leads to a core dump for
1144  C_syntax/block_scope13.c */
1145  pips_debug(2, "Do not fuse control %p since we will have a latent goto on it through label \"%s\"\n",
1146  c_res, ln);
1147  /* Do not fuse: go to next control node: */
1148  c_res = CONTROL(CAR(ctls));
1149  continue;
1150  }
1151  else
1152  pips_internal_error("Inconsistent hash table Label_control: "
1153  "same label points towards two different controls");
1154  }
1155  }
1156  if(c_res != succ) {
1157  /* If it is not a loop on c_res, fuse the nodes: */
1159  || (statement_block_p(succ_st) && !ENDP(statement_declarations(succ_st)))
1160  || (statement_block_p(succ_st) && !empty_extensions_p(statement_extensions(succ_st)))
1161  ) {
1162  /* You need a new block to fuse and to respect the scopes */
1164  CONS(STATEMENT, succ_st, NIL)));
1165  control_statement(c_res) =
1170  i,NIL,NULL,
1172  ;
1173  }
1174  else {
1175  if(!ENDP(statement_declarations(st))
1176  && !continue_statement_p(st)) {
1177  pips_user_warning("Declarations carried by a statement \"%s\""
1178  " which is not a block nor a continue!\n",
1180  }
1183  control_statement(c_res) =
1188  i,NIL,NULL,
1190  }
1191  if(instruction_block_p(succ_i=statement_instruction(succ_st))){
1192  instruction_block(i) =
1194  instruction_block(succ_i));
1195  pips_debug(8, "Free statement %p with identification %s from control succ %p\n",
1196  succ_st, statement_identification(succ_st), succ);
1198  free_statement(succ_st);
1199  succ_st = statement_undefined;
1201  }
1202  else {
1203  instruction_block(i) =
1205  CONS(STATEMENT, succ_st, NIL));
1206  }
1207  }
1208  ifdebug(1) {
1209  pips_assert("control succ and its statement are consistent",
1210  control_consistent_p(succ));
1211  }
1212  /* Remove the useless control: */
1215  }
1216 
1217  if(succ == c_last) {
1218  /* We are at the end and the last node has
1219  disappeared... Update the pointer to the new one: */
1220  c_last = c_res;
1221  break;
1222  }
1223  ifdebug(1) {
1225  statement_consistent_p(succ_st);
1226  }
1227  }
1228  set_free(processed_nodes);
1229  return c_last;
1230 }
1231 
1232 
1233 /* Do the equivalent of a mapcar of controlize on statement list @p sts.
1234 
1235  The trick is to keep a list of the controls to compact them later. Note
1236  that if a statement is controlized, then the predecessor has to be
1237  computed (i.e. is not the previous control of @p sts); this is the
1238  purpose of c_in.
1239 
1240  This function used to update its formal parameters pred and c_res, which
1241  makes stack visualization and debugging difficult.
1242 */
1244  control i_pred,
1245  control i_succ,
1246  control i_c_res,
1247  hash_table used_labels) {
1248  /* The list of all the control nodes associated to this statement
1249  list: */
1250  list ctls = NIL;
1251  control pred = i_pred;
1252  control succ = i_succ;
1253  control c_res = i_c_res;
1254 
1255  /* On all the statement list: */
1256  for(; !ENDP(sts); sts = CDR(sts)) {
1257  statement st = STATEMENT(CAR(sts));
1258  /* Create a control node for the successor of this statement if
1259  not the last one: */
1260  control c_next = ENDP(CDR(sts)) ? succ :
1262  bool controlized;
1263  bool unreachable;
1264 
1265  ifdebug(5) {
1266  pips_debug(5, "Nodes linked with pred %p:\n", pred);
1268  }
1269 
1270  ifdebug(1) {
1273  check_control_coherency(c_next);
1274  check_control_coherency(c_res);
1275  }
1276 
1277  /* Controlize the current statement: */
1278  controlized = controlize(st, pred, c_next, c_res, used_labels);
1279  unreachable = ENDP(control_predecessors(c_next));
1280 
1281  /* Keep track of the control node associated to this statement: */
1282  ctls = CONS(CONTROL, c_res, ctls);
1283 
1284  if (unreachable) {
1285  /* Keep track globally of the unreachable code: */
1287  /* ifdebug(2) { */
1288  /* pips_debug(2, "There is a new unreachable statement:\n"); */
1289  /* print_statement(st); */
1290  /* } */
1291  }
1292 
1293  if (controlized) {
1294  /* The previous controlize() returned a non structured control */
1296 
1297  ctls = CONS(CONTROL, c_in, ctls);
1298  /* Insert c_in as a predecessor of c_next
1299 
1300  RK: I do not understand why this is needed...
1301  */
1303  control_successors(c_in) = CONS(CONTROL, c_next, NIL);
1305  control_predecessors(c_next) = CONS(CONTROL, c_in, NIL) ;
1306  pred = c_in;
1307  }
1308  else {
1309  /* If the next control node is unreachable, it will not be
1310  connected to the previous predecessor, so allocate a new one
1311  so that it has a predecessor that is completely unconnected of
1312  previous control graph. */
1313  pred = (unreachable) ?
1315  c_res;
1316  }
1317  /* The next control node is the control node of the next
1318  statement: */
1319  c_res = c_next ;
1320  }
1321 
1322  ifdebug(1) {
1323  /* The consistency check should be applied to all elements in
1324  ctls. Let's hope all controls in ctls are linked one way or
1325  the other. */
1326  control c = CONTROL(CAR(ctls));
1327  pips_debug(5, "Nodes from c %p\n", c);
1330 
1333  check_control_coherency(c_res);
1334  pips_debug(5, "(pred = %p, succ = %p, c_res = %p)\n",
1335  pred, succ, c_res);
1336  pips_debug(5, "Nodes from pred %p\n", pred);
1338  pips_debug(5, "Nodes from succ %p\n", succ);
1340  pips_debug(5, "Nodes from c_res %p\n", c_res);
1342  }
1343 
1344  /* Since we built the list in reverse order to have a O(n)
1345  construction: */
1346  return gen_nreverse(ctls);
1347 }
1348 
1349 
1350 /* Computes in @p c_res the control graph of the list @p sts (of statement
1351  @p st) with @p pred predecessor and @p succ successor.
1352 
1353  We try to minimize the number of graphs by looking for graphs with one
1354  node only and picking the statement in that case.
1355 
1356  @return true if the code is not a structured control.
1357  */
1359  list sts,
1360  control pred,
1361  control succ,
1362  control c_res,
1363  hash_table used_labels)
1364 {
1365  hash_table block_used_labels = hash_table_make(hash_string, 0);
1366  control c_block = control_undefined;
1368  control c_last = c_end;
1369  list ctls;
1370  bool controlized;
1371  bool hierarchized_labels;
1372 
1373  ifdebug(1) {
1374  pips_debug(5, "Begin with (st = %p, pred = %p, succ = %p, c_res = %p)\n",
1375  st, pred, succ, c_res);
1376  ifdebug(8) {
1377  pips_debug(8, "\nControl nodes linked to pred = %p:\n", pred);
1379  pips_debug(8, "\n");
1380  }
1381 
1385  check_control_coherency(c_res);
1386  }
1387 
1388  if(ENDP(sts)) {
1389  /* Empty statement list. It looks like from controlize() that we
1390  cannot be called with an empty statement list... So I guess this
1391  is dead code here. RK */
1393  string dt
1395  strdup("")
1397  string ct = string_undefined_p(statement_comments(st))?
1398  string_undefined /* Should be empty_comments ? */
1399  : strdup(statement_comments(st));
1400 
1401  /* FI: the statement extension of st is lost */
1403  NIL, NIL);
1404  /*
1405  pips_assert("declarations are preserved in control",
1406  gen_length(statement_declarations(st))
1407  ==gen_length(statement_declarations(control_statement(c_block))));
1408  */
1409  }
1410  else {
1411  /* What happens to the declarations and comments attached to st? */
1412  /* Create a control node to hold what was the statement block, with
1413  the first statement in it: */
1414  c_block = make_conditional_control(STATEMENT(CAR(sts)));
1415  /*
1416  pips_assert("declarations are preserved in conditional control",
1417  gen_length(statement_declarations(st))
1418  ==gen_length(statement_declarations(control_statement(c_block))));
1419  */
1420  }
1421 
1422  ifdebug(1) {
1424  }
1425 
1426  /* Do the real transformation of a statement list into a control
1427  graph: */
1428  ctls = controlize_list_1(sts, pred, c_end, c_block, block_used_labels);
1429 
1430  /* Compute if there are goto from/to the statements of the statement
1431  list: */
1432  hierarchized_labels = covers_labels_p(st, block_used_labels);
1433 
1434  if (!hierarchized_labels) {
1435  /* We are in trouble since we will have an unstructured with goto
1436  from or to outside this statement sequence, but the statement
1437  sequence that define the scoping rules is going to disappear...
1438  So we gather all the declaration and push them up: */
1440  }
1441  /* Since we have generated a big control graph from what could be a
1442  more structured statement block, try to restructure things a little
1443  bit, with c_last pointing to the last control node of the list: */
1444  c_last = compact_list(ctls, c_end);
1445  /* To avoid compact list: c_last = c_end; */
1446  //c_last = c_end;
1447  gen_free_list(ctls);
1448  ifdebug(5) {
1449  pips_debug(5, "Nodes from c_block %p\n", c_block);
1451  pips_debug(5, "Nodes from c_last %p\n", c_last);
1453  }
1454  /*
1455  pips_assert("declarations are preserved in list",
1456  gen_length(statement_declarations(st))
1457  ==gen_length(statement_declarations(control_statement(c_block))));
1458  */
1459 
1460  if (hierarchized_labels) {
1461  /* There is no GOTO to/from outside the statement list:
1462  hierarchize the control graph. */
1463  statement new_st = statement_undefined;
1464 
1465  /* Unlink the c_block from the unstructured. RK. */
1466  unlink_2_control_nodes(pred, c_block);
1467  unlink_2_control_nodes(c_block, c_end);
1468 
1469  if(ENDP(control_predecessors(c_block)) &&
1470  ENDP(control_successors(c_block))) {
1471  /* c_block is a lonely control node: */
1472  new_st = control_statement(c_block);
1473 
1474  ///* FI: fragile attempt at keeping local declarations and their scope */
1475  ///* Does not work when st has been changed... */
1476  //if(/*!statement_block_p(new_st) &&*/ !ENDP(statement_declarations(st))) {
1477  // /* new_st = st*/;
1478  //}
1479 
1480  /* PJ: fragile attempt at keeping local declarations and their scope */
1481  ifdebug(1) {
1483  }
1484  if(!ENDP(statement_declarations(st))) {
1485  pips_assert("the declarations are carried by a block",
1486  statement_block_p(st));
1487  ifdebug(8) {
1488  pips_debug(8, "Block declarations to copy: ");
1490  pips_debug(8, "End of declarations.\n");
1491  }
1492  if(statement_block_p(new_st)) {
1493  if(ENDP(statement_declarations(new_st))) {
1494  statement_declarations(new_st) =
1496  }
1497  else {
1498  new_st = make_block_statement(CONS(STATEMENT, new_st, NIL));
1499  statement_declarations(new_st) =
1501  }
1502  }
1503  else {
1504  new_st = make_block_statement(CONS(STATEMENT, new_st, NIL));
1505  statement_declarations(new_st) =
1507  }
1508  /* FI: Can't we remove the declarations in st? Why are
1509  they gen_copy_seq? */
1510  }
1512  ///* it will add block for statement before add the extension
1513  // * ie, statement* -> { statement* }
1514  // * not need in fact,
1515  // * either block is already present, so no need to add
1516  // * or block are useless, so no need to add
1517  // */
1518  //if (!instruction_block_p(statement_instruction(new_st))
1519  // && instruction_block_p(statement_instruction(st))
1520  // ) {
1521  // new_st = make_block_statement(CONS(STATEMENT, new_st, NIL));
1522  //}
1524  }
1525 
1527  free_control(c_block);
1528 
1529  /* FI: no need to update declarations as the code is structured */
1530  ifdebug(1) {
1532  }
1533  }
1534  else {
1535  /* The control is kept in an unstructured: */
1536  unstructured u = make_unstructured(c_block, c_last);
1537  instruction i =
1539 
1540  ifdebug(1) {
1543  }
1544  /* FI: So here you are putting declarations in an
1545  unstructured? No surprise we end up in trouble
1546  later. */
1547  st = normalize_statement(st);
1548  if(ENDP(statement_declarations(st))) {
1550  statement_number(st),
1553  i,
1557  }
1558  else {
1559  statement us =
1561  statement_number(st),
1564  i,
1565  NIL,
1566  strdup(""),
1568  new_st =
1572  empty_comments);
1574  statement_instruction(new_st) =
1576  }
1577  }
1578 
1579  /* Not a good idea from mine to add this free... RK
1580  free_statement(control_statement(c_res)); */
1581 
1582  control_statement(c_res) = new_st;
1583 
1584  /* FI: when going down controlize list, these two nodes are
1585  already linked, and they are relinked unconditionnally by
1586  link_2_control_nodes() which does not check that its input
1587  assumption is met. */
1588  unlink_2_control_nodes(pred, c_res);
1589 
1590  link_2_control_nodes(pred, c_res);
1591  link_2_control_nodes(c_res, succ);
1592  controlized = false;
1593  }
1594  else {
1595  pips_debug(2, "There are goto to/from outside this statement list\n");
1596  /* Update c_res to reflect c_block in fact: */
1597  /* We alredy have pred linked to c_block and the exit node
1598  linked to succ. RK */
1599  UPDATE_CONTROL(c_res,
1600  control_statement(c_block),
1602  control_successors(c_block));
1604  control_successors(c_end) = CONS(CONTROL, succ, NIL);
1605  patch_references(PREDS_OF_SUCCS, c_block, c_res);
1606  patch_references(SUCCS_OF_PREDS, c_block, c_res);
1607  controlized = true;
1608  /*
1609  pips_assert("declarations are preserved",
1610  gen_length(statement_declarations(st))
1611  ==gen_length(statement_declarations(control_statement(c_res))));
1612  */
1613  }
1614 
1615  ifdebug(1) {
1617  }
1618 
1619  union_used_labels(used_labels, block_used_labels);
1620 
1621  hash_table_free(block_used_labels);
1622 
1623  pips_debug(5, "Exiting with controlized = %s\n",
1624  bool_to_string(controlized));
1625  ifdebug(1) {
1626  ifdebug(8) {
1627  pips_debug(8, "\nNodes linked to pred %p\n", pred);
1629  pips_debug(8, "\n");
1630  }
1633  check_control_coherency(c_res);
1634  /*
1635  pips_assert("declarations are preserved",
1636  gen_length(statement_declarations(st))
1637  ==gen_length(statement_declarations(control_statement(c_res))));
1638  */
1639 
1641  }
1642  return(controlized);
1643 }
1644 
1645 
1646 /* Builds the control node of a statement @p st in @p c_res which is a
1647  test statement @p t.
1648 
1649  @return true if the control node generated is not structured_.
1650  */
1651 static bool controlize_test(st, t, pred, succ, c_res, used_labels)
1652 test t;
1653 statement st;
1654 control pred, succ;
1655 control c_res;
1656 hash_table used_labels;
1657 {
1658  hash_table
1659  t_used_labels = hash_table_make(hash_string, 0),
1660  f_used_labels = hash_table_make(hash_string, 0);
1664  statement s_t = test_true(t);
1665  statement s_f = test_false(t);
1666  bool controlized;
1667 
1668  pips_debug(5, "Entering (st = %p, pred = %p, succ = %p, c_res = %p)\n",
1669  st, pred, succ, c_res);
1670 
1671  ifdebug(5) {
1672  /* pips_debug(1, "THEN at entry:\n"); */
1673  /* print_statement(s_t); */
1674  /* pips_debug(1, "c1 at entry:\n"); */
1675  /* print_statement(control_statement(c1)); */
1676  /* pips_debug(1, "ELSE at entry:\n"); */
1677  /* print_statement(s_f); */
1678  /* pips_debug(1, "c2 at entry:\n"); */
1679  /* print_statement(control_statement(c2)); */
1682  check_control_coherency(c_res);
1683  }
1684 
1685  controlize(s_t, c_res, c_join, c1, t_used_labels);
1686  /* Just put the IF statement in c_res so that
1687  add_proper_successor_to_predecessor() that may be called from the
1688  next controlize() here behave correctly: */
1689  control_statement(c_res) = st;
1690  controlize(s_f, c_res, c_join, c2, f_used_labels);
1691 
1692  if(covers_labels_p(s_t, t_used_labels) &&
1693  covers_labels_p(s_f, f_used_labels)) {
1694  /* If all the label jumped to from the THEN/ELSE statements are in
1695  their respecive statement, we can replace the unstructured test by
1696  a structured one: */
1697  test it = make_test(test_condition(t),
1698  control_statement(c1),
1699  control_statement(c2));
1700  /* c1 & c2 are no longer useful: */
1703 
1704  st = normalize_statement(st);
1705  UPDATE_CONTROL(c_res,
1707  statement_number(st),
1715  CONS(CONTROL, succ, NIL));
1717  controlized = false;
1718  }
1719  else {
1720  // Keep the unstructured test:
1721  UPDATE_CONTROL(c_res, st,
1723  CONS(CONTROL, c1, CONS(CONTROL, c2, NIL)));
1726  control_predecessors(succ) = ADD_PRED_IF_NOT_ALREADY_HERE(c_join, succ);
1727  control_successors(c_join) = CONS(CONTROL, succ, NIL);
1728  controlized = true;
1729  }
1730 
1731  /* Be very careful when chaining c_res as successor of pred: if pred is
1732  associated to a test, the position of c_res as first or second
1733  successor of c_res is unknown. It should have been set by the
1734  caller.
1735 
1736  You might survive, using the fact that the true branch has been
1737  processed first because of the order of the two recursive calls to
1738  controlize(). The false branch whill be linked as second
1739  successor. But another controlize_xxx might have decided to link pred
1740  and c_res before calling controlize() and controlize_test(). Too much
1741  guessing IMHO (FI). */
1742 
1743  /* control_successors(pred) = ADD_SUCC(c_res, pred); */
1745 
1746  union_used_labels(used_labels,
1747  union_used_labels(t_used_labels, f_used_labels));
1748 
1749  hash_table_free(t_used_labels);
1750  hash_table_free(f_used_labels);
1751 
1752  ifdebug(5) {
1753  /* pips_debug(1, "IF at exit:\n"); */
1754  /* print_statement(st); */
1758  check_control_coherency(c_res);
1759  }
1760  pips_debug(5, "Exiting\n");
1761 
1762  return(controlized);
1763 }
1764 ␌
1765 /* INIT_LABEL puts the reference in the statement ST to the label NAME
1766  int the Label_statements table and allocate a slot in the Label_control
1767  table. */
1768 
1769 static void init_label(name, st )
1770 string name;
1771 statement st;
1772 {
1773  if(!empty_global_label_p(name)) {
1775  list sts = CONS(STATEMENT, st, used);
1776  /* Just append st to the list of statements pointing to
1777  this label. */
1778  if (hash_defined_p(Label_statements, name))
1779  hash_update(Label_statements, name, sts);
1780  else
1781  hash_put(Label_statements, name, sts);
1782 
1783  if (! hash_defined_p(Label_control, name)) {
1785  control c = make_control( new_st, NIL, NIL);
1786  pips_debug(8, "control %p allocated for label \"%s\"", c, name);
1787  hash_put(Label_control, name, c);
1788  }
1789  }
1790 }
1791 
1792 /* CREATE_STATEMENTS_OF_LABELS gathers in the Label_statements table all
1793  the references to the useful label of the statement ST. Note that for
1794  loops, the label in the DO statement is NOT introduced. Label_control is
1795  also created. */
1796 
1798 statement st;
1799 {
1800  string name = entity_name(statement_label(st));
1801  instruction i;
1802 
1803  init_label(name, st);
1804 
1805  switch(instruction_tag(i = statement_instruction(st))) {
1806  case is_instruction_goto: {
1807  string where = entity_name(statement_label(instruction_goto(i)));
1808 
1809  init_label(where, st);
1810  break;
1811  }
1812 
1814  pips_internal_error("Found unstructured", "");
1815 
1816  default:
1817  ;
1818  }
1819 }
1820 
1821 
1823 statement st ;
1824 {
1825  gen_recurse(st,
1827  gen_true,
1829 }
1830 
1831 ␌
1832 /* SIMPLIFIED_UNSTRUCTURED tries to get rid of top-level and useless
1833  unstructured nodes.
1834 
1835  top is the entry node, bottom the exit node. result is ? (see
1836  assert below... Looks like it is the second node. RK)
1837 
1838  All the comments below are from RK who is reverse engineering all
1839  that stuff... :-(
1840 
1841  Looks like there are many memory leaks. */
1842 static unstructured
1844  control bottom,
1845  control res)
1846 {
1847  list succs;
1848  statement st;
1849  unstructured u;
1850  instruction i;
1851 
1852  ifdebug(4) {
1853  pips_debug(4, "Accessible nodes from top:\n");
1856  pips_debug(1, "Accessible nodes from bottom:\n");
1858  check_control_coherency(bottom);
1859  pips_debug(1, "Accessible nodes from res:\n");
1862  }
1863 
1864  ifdebug(1) {
1865  control_consistent_p(top);
1866 
1867  control_consistent_p(bottom);
1868  }
1869 
1870  u = make_unstructured(top, bottom);
1871 
1872  ifdebug(1) {
1874  }
1875 
1876  if(!ENDP(control_predecessors(top))) {
1877  free_control(res);
1878  /* There are goto on the entry node: */
1879  return(u);
1880  }
1881 
1882  if(gen_length(succs=control_successors(top)) != 1) {
1883  free_control(res);
1884  /* The entry node is not a simple node sequence: */
1885  return(u);
1886  }
1887 
1888  pips_assert("The successor of \"top\" is \"res\"",
1889  CONTROL(CAR(succs)) == res);
1890 
1891  if(gen_length(control_predecessors(res)) != 1) {
1892  free_control(res);
1893  /* The second node has more than 1 goto on it: */
1894  return(u);
1895  }
1896 
1897  if(gen_length(succs=control_successors(res)) != 1) {
1898  free_control(res);
1899  /* Second node is not a simple node sequence: */
1900  return(u);
1901  }
1902 
1903  if(CONTROL(CAR(succs)) != bottom) {
1904  /* The third node is not the exit node: */
1905  return(u);
1906  }
1907 
1908  if(gen_length(control_predecessors(bottom)) != 1) {
1909  free_control(res);
1910  /* The exit node has more than 1 goto on it: */
1911  return(u);
1912  }
1913 
1914  if(!ENDP(control_successors(bottom))) {
1915  free_control(res);
1916  /* The exit node has a successor: */
1917  return(u);
1918  }
1919 
1920  /* Here we have a sequence of 3 control node: top, res and
1921  bottom. */
1925  st = control_statement(res);
1926 
1928  /* If the second node is an unstructured, just return it
1929  instead of top and bottom: (??? Lot of assumptions. RK) */
1930  ifdebug(1) {
1932  }
1935  free_statement(st);
1936  return iu;
1937  }
1938 
1939  /* Just keep the second node as an unstructured with only 1
1940  control node: */
1942  ifdebug(1) {
1944  }
1945  return(u);
1946 }
1947 
1948 
1949 /* Computes in @p c_res the control node of the statement @p st whose
1950  predecessor control node is @p pred and successor @p succ.
1951 
1952  The @p used_LABELS is modified to deal with local use of labels.
1953 
1954  The invariant is that it links predecessors and successors of @p c_res,
1955  updates the successors of @p pred and the predecessors of @p succ.
1956 
1957  In fact, it cannot update the successors of @p pred because it cannot
1958  know which successor of @p pred @p c_RES is when @p pred is associated
1959  to a test. @p pred and @p c_res must be linked together when you enter
1960  controlize(), or they must be linked later by the caller. But they
1961  cannot be linked here thru the successor list of @p pred and, if the
1962  consistency is true here, they cannot be linked either by the
1963  predecessor list of @p succ. If they are linked later, it is useless to
1964  pass @p pred down. If they are linked earlier, they might have to be
1965  unlinked when structured code is found.
1966 
1967  @return true if the current statement isn't a structured control.
1968 */
1969 static bool controlize(statement st,
1970  control pred,
1971  control succ,
1972  control c_res,
1973  hash_table used_labels)
1974 {
1976  entity elabel = statement_label(st);
1977  string label = entity_name(elabel);
1978  bool controlized = false;
1979  control n_succ = control_undefined; // To be used in case of goto
1980 
1981  ifdebug(5) {
1982  pips_debug(1,
1983  "Begin with (st = %p, pred = %p, succ = %p, c_res = %p)\n"
1984  "st at entry:\n",
1985  st, pred, succ, c_res);
1986  ifdebug(1) {
1988  }
1989  /* print_statement(st); */
1990  /*
1991  pips_assert("pred is a predecessor of c_res",
1992  gen_in_list_p(pred, control_predecessors(c_res)));
1993  pips_assert("c_res is a successor of pred",
1994  gen_in_list_p(c_res, control_successors(pred)));
1995  */
1996  pips_debug(1, "Begin with result c_res %p:\n", c_res);
2000  check_control_coherency(c_res);
2001  }
2002 
2003  switch(instruction_tag(i)) {
2004  case is_instruction_block: {
2005  /* A C block may have a label and even goto from outside on it. */
2006  /* A block may only contain declarations with initializations
2007  and side effects on the store */
2008  if(ENDP(instruction_block(i))) {
2009  /* Empty block */
2010  controlized = controlize_call(st, pred, succ, c_res);
2011  ifdebug(1) {
2013  }
2014  }
2015  else {
2016  ifdebug(1) {
2018  }
2019  scoping_statement_push(st);
2020  controlized = controlize_list(st, instruction_block(i),
2021  pred, succ, c_res, used_labels);
2022  ifdebug(1) {
2024  }
2025 
2026  ifdebug(5) {
2027  pips_debug(1, "CFG consistency check before list6 controlization."
2028  " Control \"pred\" %p:\n", pred);
2030  pips_debug(1, "Control \"succ\" %p:\n", succ);
2032 
2035  check_control_coherency(c_res);
2036  }
2037  /* If st carries local declarations, so should the statement
2038  associated to c_res. */
2039  if(controlized && !ENDP(statement_declarations(st))
2042  pips_user_warning("Some local declarations may have been lost\n");
2043  }
2044  scoping_statement_pop();
2045  ifdebug(1) {
2047  }
2048  }
2049  break;
2050  }
2051  case is_instruction_test:
2052  controlized = controlize_test(st, instruction_test(i),
2053  pred, succ, c_res, used_labels);
2054  ifdebug(1) {
2056  }
2057  break;
2058  case is_instruction_loop:
2059  controlized = controlize_loop(st, instruction_loop(i),
2060  pred, succ, c_res, used_labels);
2061  ifdebug(1) {
2063  }
2064  break;
2066  controlized = controlize_whileloop(st, instruction_whileloop(i),
2067  pred, succ, c_res, used_labels);
2068  ifdebug(1) {
2070  }
2071  break;
2072  case is_instruction_goto: {
2073  /* Get the label name of the statement the goto point to: */
2074  string name = entity_name(statement_label(instruction_goto(i)));
2076 
2079  // Well, let's try this for the time being. What is the scope?!?
2082 
2083  n_succ = get_label_control(name);
2084 
2085  ifdebug(5) {
2086  pips_debug(1, "CFG consistency check before goto controlization."
2087  " Control \"pred\" %p:\n", pred);
2089  pips_debug(1, "Control \"n_succ\" %p:\n", n_succ);
2092  check_control_coherency(n_succ);
2093  check_control_coherency(c_res);
2094  }
2095 
2096  /* Memory leak in CONS(CONTROL, pred, NIL). Also forgot to
2097  unlink the predecessor of the former successor of pred. RK */
2098  /* control_successors(pred) = ADD_SUCC(c_res, pred); */
2100  UPDATE_CONTROL(c_res, nop,
2101  CONS(CONTROL, pred, NIL),
2102  CONS(CONTROL, n_succ, NIL));
2103  control_predecessors(n_succ) = ADD_PRED_IF_NOT_ALREADY_HERE(c_res, n_succ);
2104  /* I do not know why, but my following code does not work. So
2105  I put back former one above... :-( RK. */
2106 #if 0
2107  /* Use my procedures instead to set a GOTO from pred to
2108  c_res. RK */
2109  if (gen_length(control_successors(pred)) == 1)
2111  link_2_control_nodes(pred, c_res);
2112  link_2_control_nodes(c_res, n_succ);
2113  /* Hmmm... A memory leak on the previous statement of c_res? */
2114  control_statement(c_res) = nop;
2115 #endif
2116  update_used_labels(used_labels, name, st);
2117  controlized = true;
2118  break;
2119  }
2120  case is_instruction_call:
2121  /* FI: IO calls may have control effects; they should be handled here! */
2122  controlized = controlize_call(st, pred, succ, c_res);
2123  ifdebug(1) {
2125  }
2126  break;
2128  pips_assert("We are really dealing with a for loop",
2130  controlized = controlize_forloop(st, instruction_forloop(i),
2131  pred, succ, c_res, used_labels);
2132  ifdebug(1) {
2134  }
2135  /* SG+EC:some label may have been lost in the process
2136  fix it here instead of understanding why */
2137  if(!same_entity_p(statement_label(st),elabel)) {
2138  statement_label(st)=elabel;
2139  }
2140  break;
2142  /* PJ: controlize_call() controlize any "nice" statement */
2143  controlized = return_instruction_p(i) || controlize_call(st, pred, succ, c_res);
2144 
2145  ifdebug(1) {
2147  }
2148  break;
2150  pips_internal_error("is_instruction_unstructured not treated, never happen?");
2151  break;
2153  pips_internal_error("is_instruction_multitest not treated, never happen?");
2154  break;
2155  default:
2156  pips_internal_error("Unknown instruction tag %d", instruction_tag(i));
2157  /* no break */
2158  }
2159 
2160  ifdebug(5) {
2162  /* pips_debug(1, "st %p at exit:\n", st); */
2163  /* print_statement(st); */
2164  pips_debug(1, "Resulting Control c_res %p at exit:\n", c_res);
2166  fprintf(stderr, "---\n");
2167  /* The declarations may be preserved at a lower level
2168  if(!ENDP(statement_declarations(st))
2169  && ENDP(statement_declarations(control_statement(c_res)))) {
2170  pips_internal_error("Lost local declarations");
2171  }
2172  */
2174  if(control_undefined_p(n_succ))
2176  else
2177  check_control_coherency(n_succ);
2178  check_control_coherency(c_res);
2179  }
2180 
2181  /* Update the association between the current statement and its label:
2182  */
2183  update_used_labels(used_labels, label, st);
2184 
2185  return(controlized);
2186 }
2187 
2188 
2189 /* CONTROL_GRAPH returns the control graph of the statement ST. */
2191 {
2192  control result, top, bottom;
2193  hash_table used_labels = hash_table_make(hash_string, 0);
2195 
2196  ifdebug(1) {
2197  pips_assert("Statement should be OK.", statement_consistent_p(st));
2198  set_bool_property("PRETTYPRINT_BLOCKS", true);
2199  set_bool_property("PRETTYPRINT_EMPTY_BLOCKS", true);
2200  }
2201 
2202  /* Since the controlizer does not seem to accept GOTO inside
2203  sequence from outside but it appears in the code with
2204  READ/WRITE with I/O exceptions (end=, etc), first remove
2205  useless blocks. RK */
2206  clean_up_sequences(st);
2207 
2208  ifdebug(1) {
2210  }
2211 
2215 
2216  result = make_conditional_control(st);
2219  Unreachable = NIL;
2220 
2221  ifdebug(1) {
2223  }
2224 
2225  /* To track declaration scoping independently of control structure: */
2226  make_scoping_statement_stack();
2227 
2228  /* FI: structured or not, let's build an unstructured... */
2229  (void) controlize(st, top, bottom, result, used_labels);
2230 
2231  /* Clean up scoping stack: */
2232  free_scoping_statement_stack();
2233 
2234  /* The statement st is not consistent anymore here. */
2235  //statement_consistent_p(st);
2236 
2237  if(!ENDP(Unreachable)) {
2238  pips_user_warning("Some statements are unreachable\n");
2239  pips_user_warning("Unreachable statements:\n");
2241  // This interesting information makes library control dependent on library prettyprint
2242  pips_user_warning("Statement:\n%s\n", text_to_string(statement_to_text(s)));
2243  if (statement_number(s) != -1) {
2244  pips_user_warning("Statement number: %d\n", statement_number(s));
2245  }
2246  }
2247  }
2250  hash_table_free(used_labels);
2251 
2252  u = simplified_unstructured(top, bottom, result);
2253 
2254  ifdebug(5) {
2255  pips_debug(1,
2256  "Nodes in unstructured %p (entry %p, exit %p) from entry:\n",
2259  pips_debug(1, "Accessible nodes from exit:\n");
2261  }
2262 
2263  /* Since the controlizer is a sensitive pass, avoid leaking basic
2264  errors... */
2265  ifdebug(1) {
2267  }
2268 
2271 
2272  ifdebug(1) {
2275  pips_assert("Unstructured should be OK.", unstructured_consistent_p(u));
2276  }
2277 
2278  return(u);
2279 }
2280 
2281 /*
2282  @}
2283 */
unstructured make_unstructured(control a1, control a2)
Definition: ri.c:2778
call make_call(entity a1, list a2)
Definition: ri.c:269
bool unstructured_consistent_p(unstructured p)
Definition: ri.c:2751
instruction make_instruction_forloop(forloop _field_)
Definition: ri.c:1193
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
loop make_loop(entity a1, range a2, statement a3, entity a4, execution a5, list a6)
Definition: ri.c:1301
void free_control(control p)
Definition: ri.c:490
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(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
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
FILE * c_in
Definition: c_syntax.h:291
bool clean_up_sequences(statement s)
Recursively clean up the statement sequences by fusing them if possible and by removing useless one.
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.
static string c_test(test t, bool breakable)
bool return_label_p(const char *s)
Definition: entity_names.c:272
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
statement make_block_statement(list)
Make a block statement from a list of statement.
Definition: statement.c:616
statement instruction_to_statement(instruction)
Build a statement from a give instruction.
Definition: statement.c:597
statement make_empty_statement_with_declarations_and_comments(list, string, string)
Build an empty statement with declaration list, declaration text and comment.
Definition: statement.c:638
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 display_address_of_control_nodes(list cs)
Display the adresses a list of control nodes.
Definition: control.c:612
void link_2_control_nodes(control source, control target)
Add an edge between 2 control nodes.
Definition: control.c:1193
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 check_control_coherency(control c)
Test the coherency of a control node network from a control node.
Definition: control.c:487
statement 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...
static bool controlize_call(statement st, control pred, control succ, control c_res)
CONTROLIZE_CALL controlizes the call C of statement ST in C_RES.
statement loop_test(statement sl)
static statement whileloop_test(statement sl)
Generate a test statement ts for exiting loop sl.
#define PREDS_OF_SUCCS
static hash_table Label_control
LABEL_CONTROL maps label names to their (possible forward) control nodes.
unstructured control_graph(statement st)
CONTROL_GRAPH returns the control graph of the statement ST.
static control compact_list(list ctls, control c_end)
Take a list of controls ctls coming from a controlize_list() and compact the successive statements,...
statement forloop_header(statement sl)
static bool controlize_forloop(statement st, forloop l, control pred, control succ, control c_res, hash_table used_labels)
static list Unreachable
UNREACHABLE is the hook used as a predecessor of statements that are following a goto.
static list controlize_list_1(list sts, control i_pred, control i_succ, control i_c_res, hash_table used_labels)
Do the equivalent of a mapcar of controlize on statement list sts.
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 sl)
static void create_statements_of_labels(st)
static hash_table Label_statements
LABEL_STATEMENTS maps label names to the list of statements where they appear (either as definition o...
statement loop_inc(statement sl)
#define ADD_PRED_AND_COPY_IF_NOT_ALREADY_HERE(pred, c)
static bool controlize_test(statement st, test t, control pred, control succ, control c_res, hash_table used_labels)
Builds the control node of a statement st in c_res which is a test statement t.
static void add_proper_successor_to_predecessor(control pred, control c_res)
static bool controlize_whileloop(statement st, whileloop l, control pred, control succ, control c_res, hash_table used_labels)
CONTROLIZE_WHILELOOP computes in C_RES the control graph of the loop L (of statement ST) with PREDece...
#define SUCCS_OF_PREDS
#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...
#define LABEL_TABLES_SIZE
statement forloop_test(statement sl)
static bool controlize(statement st, control pred, control succ, control c_res, hash_table used_labels)
Computes in c_res the control node of the statement st whose predecessor control node is pred and suc...
static bool controlize_loop(statement st, loop l, control pred, control succ, control c_res, hash_table used_labels)
CONTROLIZE_LOOP computes in C_RES the control graph of the loop L (of statement ST) with PREDecessor ...
static void patch_references(int how, control fnode, control tnode)
PATCH_REFERENCES replaces all occurrences of FNODE by TNODE in the predecessors or successors lists o...
#define UPDATE_CONTROL(c, s, pd, sc)
Update control c by setting its statement to s, by unioning its predecessor set with pd,...
static unstructured simplified_unstructured(control top, control bottom, control res)
SIMPLIFIED_UNSTRUCTURED tries to get rid of top-level and useless unstructured nodes.
static bool controlize_list(statement st, list sts, control pred, control succ, control c_res, hash_table used_labels)
Computes in c_res the control graph of the list sts (of statement st) with pred predecessor and succ ...
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_instruction_block(list statements)
Build an instruction block from a list of statements.
Definition: instruction.c:106
bool return_instruction_p(instruction i)
Test if an instruction is a C or Fortran "return".
Definition: instruction.c:185
#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 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
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 MAPL(_map_list_cp, _code, _l)
Apply some code on the addresses of all the elements of a list.
Definition: newgen_list.h:203
list gen_full_copy_list(list l)
Copy a list structure with element copy.
Definition: list.c:535
loop statement_loop(statement)
Get the loop of a statement.
Definition: statement.c:1374
bool statement_test_p(statement)
Definition: statement.c:343
statement make_assign_statement(expression, expression)
Definition: statement.c:583
string statement_identification(statement)
Like external_statement_identification(), but with internal information, the hexadecimal address of t...
Definition: statement.c:1700
bool continue_statement_p(statement)
Test if a statement is a CONTINUE, that is the FORTRAN nop, the ";" in C or the "pass" in Python....
Definition: statement.c:203
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
string comment_sentinel(tag)
Start a single line comment.
Definition: statement.c:4420
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
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_user_warning
Definition: misc-local.h:146
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define pips_internal_error
Definition: misc-local.h:149
void debug(const int the_expected_debug_level, const char *calling_function_name, const char *a_message_format,...)
ARARGS0.
Definition: debug.c:189
#define STATEMENT_ORDERING_UNDEFINED
mapping.h inclusion
Definition: newgen-local.h:35
string bool_to_string(bool)
Definition: string.c:243
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
void set_free(set)
Definition: set.c:332
bool set_belong_p(const set, const void *)
Definition: set.c:194
@ set_pointer
Definition: newgen_set.h:44
set set_make(set_type)
Create an empty set of any type but hash_private.
Definition: set.c:102
set set_add_element(set, const set, const void *)
Definition: set.c:152
int tag
TAG.
Definition: newgen_types.h:92
#define string_undefined
Definition: newgen_types.h:40
#define true
Definition: newgen_types.h:81
#define string_undefined_p(s)
Definition: newgen_types.h:41
struct cons * list
Definition: newgen_types.h:106
char vcid_control_old_controlizer[]
old_controlizer.c
static control make_conditional_control(statement st)
Make a control node from a statement if needed.
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 m...
static void update_used_labels(hash_table used_labels, string name, statement st)
Add the reference to the label NAME in the statement ST.
static void create_statements_of_label(statement st)
CREATE_STATEMENTS_OF_LABELS gathers in the Label_statements table all the references to the useful la...
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.
static control get_label_control(string name)
Get the control node associated to a label name.
static hash_table union_used_labels(hash_table l1, hash_table l2)
Unions 2 used-label hash maps.
text statement_to_text(statement)
Definition: statement.c:124
void set_bool_property(const char *, bool)
void reset_unstructured_number()
Reset the unstructured number for a new module reordering.
Definition: reorder.c:56
bool unstructured_reorder(unstructured u)
Reorder an unstructured.
Definition: reorder.c:166
#define instruction_block_p(i)
#define GREATER_THAN_OPERATOR_NAME
#define PLUS_OPERATOR_NAME
#define statement_block_p(stat)
#define STATEMENT_NUMBER_UNDEFINED
default values
#define unstructured_control
After the modification in Newgen: unstructured = entry:control x exit:control we have create a macro ...
#define C_NOT_OPERATOR_NAME
#define is_instruction_block
soft block->sequence transition
#define instruction_block(i)
#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
bool same_entity_p(entity e1, entity e2)
predicates on entities
Definition: entity.c:1321
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
void print_entities(list l)
Definition: entity.c:167
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
expression make_entity_expression(entity e, cons *inds)
Definition: expression.c:176
bool empty_extensions_p(extensions es)
Definition: extension.c:50
extensions empty_extensions(void)
extension.c
Definition: extension.c:43
entity clone_variable_with_unique_name(entity, statement, string, string, entity)
Clone a variable with a new user name.
Definition: variable.c:562
#define loop_body(x)
Definition: ri.h:1644
#define normalized_undefined
Definition: ri.h:1745
#define control_undefined
Definition: ri.h:916
#define loop_execution(x)
Definition: ri.h:1648
#define CONTROL_(x)
Definition: ri.h:913
#define forloop_initialization(x)
Definition: ri.h:1366
#define extensions_undefined_p(x)
Definition: ri.h:1309
#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_loop(x)
Definition: ri.h:1520
#define instruction_goto(x)
Definition: ri.h:1526
#define test_false(x)
Definition: ri.h:2837
#define whileloop_evaluation(x)
Definition: ri.h:3166
#define unstructured_undefined
Definition: ri.h:2980
#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_multitest
Definition: ri.h:1476
@ 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 test_true(x)
Definition: ri.h:2835
#define statement_extensions(x)
Definition: ri.h:2464
#define instruction_forloop(x)
Definition: ri.h:1538
#define control_successors(x)
Definition: ri.h:945
#define loop_label(x)
Definition: ri.h:1646
#define control_undefined_p(x)
Definition: ri.h:917
#define unstructured_exit(x)
Definition: ri.h:3006
#define instruction_unstructured_p(x)
Definition: ri.h:1530
#define loop_locals(x)
Definition: ri.h:1650
#define test_condition(x)
Definition: ri.h:2833
#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 extensions_extension(x)
Definition: ri.h:1330
#define control_statement(x)
Definition: ri.h:941
#define instruction_test(x)
Definition: ri.h:1517
#define statement_undefined_p(x)
Definition: ri.h:2420
#define whileloop_condition(x)
Definition: ri.h:3160
#define call_undefined
Definition: ri.h:685
#define statement_number(x)
Definition: ri.h:2452
#define forloop_body(x)
Definition: ri.h:1372
#define sequence_undefined_p(x)
Definition: ri.h:2339
#define instruction_unstructured(x)
Definition: ri.h:1532
@ 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
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
char * strdup()
#define ifdebug(n)
Definition: sg.c:47
FI: I do not understand why the type is duplicated at the set level.
Definition: set.c:59
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
string text_to_string(text t)
SG: moved here from ricedg.
Definition: print.c:239