PIPS
full_spaghettify.c
Go to the documentation of this file.
1 /*
2 
3  $Id: full_spaghettify.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  * The spaghettifier is used in context of PHRASE project while
29  * creating "Finite State Machine"-like code portions in order to synthetise
30  * them in reconfigurables units.
31  *
32  * This phases transforms all the module in a unique
33  * unstructured statement where all the control nodes are:
34  * - CALL
35  * - or TEST
36  * - or SEQUENCE
37  *
38  * In fact the module becomes a sequence statement with a beginning
39  * statement, the unstructured statement and a final statement
40  *
41  * full_spaghettify > MODULE.code
42  * < PROGRAM.entities
43  * < MODULE.code
44  *
45  */
46 
47 #include <stdio.h>
48 #include <ctype.h>
49 
50 #include "genC.h"
51 #include "linear.h"
52 #include "ri.h"
53 #include "effects.h"
54 
55 #include "resources.h"
56 
57 #include "misc.h"
58 #include "ri-util.h"
59 #include "prettyprint.h"
60 #include "effects-util.h"
61 #include "pipsdbm.h"
62 
63 #include "text-util.h"
64 
65 #include "dg.h"
66 
67 #include "control.h"
68 #include "callgraph.h"
69 
70 #include "spaghettify.h"
71 #include "phrase_tools.h"
72 
74  const char* module_name,
75  unstructured u,
76  control current_control,
77  control next_control);
78 
79 static control connect_unstructured (statement unstructured_statement,
80  control current_control,
81  control next_control);
82 
83 static void reduce_sequence (control current_control,
84  sequence seq,
85  control* new_entry,
86  control* new_exit);
87 
88 static void flatten_unstructured (unstructured the_unstructured);
89 
91  control current_control);
92 
94  const char* module_name)
95 {
96  statement returned_statement;
97  unstructured new_unstructured;
98  instruction unstructured_instruction;
99  control entry;
100  control exit;
101  list blocs = NIL ;
102  int stat_number;
103  int stat_ordering;
104 
106  (entity_empty_label()), NIL, NIL);
108  (entity_empty_label()), NIL, NIL);
109  link_2_control_nodes (entry, exit);
110  new_unstructured
111  = make_unstructured(entry, exit);
112 
113  unstructured_instruction = make_instruction(is_instruction_unstructured,
114  new_unstructured);
115 
116 
117  stat_number = statement_number(module_statement);
118  stat_ordering = statement_ordering(module_statement);
119 
121  module_name,
122  new_unstructured,
123  entry,
124  exit);
125 
126  returned_statement = make_statement(entity_empty_label(),
127  stat_number,
128  stat_ordering,
130  unstructured_instruction,
131  NIL, NULL,
133 
134  pips_assert("Statement is consistent after FULL_SPAGUETTIFY",
135  statement_consistent_p(returned_statement));
136 
137  ifdebug(2) {
138  CONTROL_MAP (current_control, {
139  pips_assert("Statement is consistent after FULL_SPAGUETTIFY",
140  statement_consistent_p(control_statement(current_control)));
141  debug_control("FSM STATE: Module control =======================================",current_control, 2);
142  }, entry, blocs);
143  }
144  return returned_statement;
145 }
146 
147 /**
148  * This function reduce the sequence seq at the position in the control
149  * graph indicated by control current_control. The sequence is reduced by
150  * the creation of new control nodes corresponding to all the statements
151  * in the sequence. In addition new_entry and new_exit control pointers
152  * are updated according to the transformation.
153  * NOTE: this function don't do recursively the job, but is generally called
154  * by flatten_unstructured which do the job recursively.
155  */
156 static void reduce_sequence (control current_control,
157  sequence seq,
158  control* new_entry,
159  control* new_exit)
160 {
161  control first_control = NULL;
162  control last_control = NULL;
163  control new_control = NULL;
164  bool is_first_control;
165  int i;
166 
167  if(gen_length(sequence_statements(seq)) == 0)
168  {
169  *new_entry = control_undefined;
170  *new_exit = control_undefined;
171  return;
172  }
173 
174  /* Conserve lists of predecessors and successors */
175  list predecessors = gen_copy_seq (control_predecessors(current_control));
176  list successors = gen_copy_seq (control_successors(current_control));
177 
178  pips_debug(5,"CONTROL [%p]\n", current_control);
179  ifdebug(5) {
180  print_statement (control_statement(current_control));
181  }
182 
183  /* Deconnect all the predecessors */
184  for (i=0; i<(int)gen_length(predecessors); i++) {
185  pips_debug(5,"Unlink predecessor [%p-%p]\n",
187  current_control);
188  unlink_2_control_nodes (CONTROL(gen_nth(i,predecessors)), current_control);
189  }
190 
191  /* Deconnect all the successors */
192  for (i=0; i<(int)gen_length(successors); i++) {
193  pips_debug(5,"Unlink successor [%p-%p]\n",
194  current_control,
196  unlink_2_control_nodes (current_control, CONTROL(gen_nth(i,successors)));
197  }
198 
199  is_first_control = true;
200 
201  /* We iterate on each statement in the sequence */
202  FOREACH(STATEMENT, current_stat, sequence_statements(seq))
203  {
204  /* We build a new control node from current statement */
205  new_control = make_control (current_stat, NIL, NIL);
206  ifdebug(5) {
207  print_statement (current_stat);
208  }
209  if (is_first_control) {
210  /* For the first statement... */
211  first_control = new_control;
212  is_first_control = false;
213  pips_debug(5,"First control %p\n", first_control);
214  *new_entry = first_control;
215  /* Reconnect all the predecessors */
216  /* ATTENTION link_2_control_nodes add to the list at the first position,
217  so we need to reconnect in the reverse order */
218  for (i=gen_length(predecessors)-1; i>=0; i--) {
219  pips_debug(5,"Relink predecessor [%p-%p]\n",
221  first_control);
223  link_2_control_nodes (c, first_control);
224  }
225  /* Reconnect all the successors */
226  /* ATTENTION link_2_control_nodes add to the list at the first position,
227  so we need to reconnect in the reverse order */
228  for (i=gen_length(successors)-1; i>=0; i--) {
229  pips_debug(5,"Relink successor [%p-%p]\n",
230  first_control,
232  link_2_control_nodes (first_control, CONTROL(gen_nth(i,successors)));
233  }
234  }
235  else {
236  /* If this is not the first statement, we have to link
237  it with the previous one */
238  link_2_control_nodes (last_control, new_control);
239  pips_debug(5,"Other control %p [%p-%p]\n",
240  new_control, last_control, new_control);
241  /* Deconnect all the OLD successors */
242  for (i=0; i<(int)gen_length(successors); i++) {
243  pips_debug(5,"Unlink successor [%p-%p]\n",
244  last_control,
246  unlink_2_control_nodes (last_control, CONTROL(gen_nth(i,successors)));
247  }
248  /* Reconnect all the NEW successors */
249  /* ATTENTION link_2_control_nodes add to the list at the first position,
250  so we need to reconnect in the reverse order */
251  for (i=gen_length(successors)-1; i>=0; i--) {
252  pips_debug(5,"Relink successor [%p-%p]\n",
253  new_control,
255  link_2_control_nodes (new_control, CONTROL(gen_nth(i,successors)));
256  }
257  }
258  last_control = new_control;
259  *new_exit = new_control;
260  }
261 }
262 
263 
264 /**
265  * This function takes as entry an unstructured and flatten it:
266  * - by reducing hierarchical unstructured
267  * - by reducing sequence statement (the sequence control node is
268  * replaced by a sequence of new control nodes formed with the
269  * statements inside the sequence)
270  */
271 static void flatten_unstructured (unstructured the_unstructured)
272 {
273  list blocs = NIL;
274  list sequences_to_reduce = NIL;
275  list unstructured_to_flatten = NIL;
276  int nb_of_sequences_to_reduce;
277  int nb_of_unstructured_to_flatten;
278  int debug_iteration = 0;
279 
280  /* Repeat until there is no more sequences to
281  reduce and unstructured to flatten */
282 
283  do {
284 
285  blocs = NIL;
286  debug_iteration++;
287  pips_debug(2,"New iteration %d\n", debug_iteration);
288 
289  sequences_to_reduce = NIL;
290  unstructured_to_flatten = NIL;
291 
292  ifdebug(5) {
293  short_debug_unstructured (the_unstructured, 2);
294  }
295 
296  /* First, check all the sequences to reduce */
297  CONTROL_MAP (current_control, {
298  instruction i;
299  i = statement_instruction(control_statement(current_control));
300  switch (instruction_tag(i)) {
302  {
303  sequences_to_reduce
304  = CONS(CONTROL,
305  current_control,
306  sequences_to_reduce);
307  pips_debug (5, "MARKING SEQUENCE: %p\n", current_control);
308  debug_control ("SEQUENCE: ", current_control, 5);
309  }
310  default:
311  break;
312  }
313  }, unstructured_entry (the_unstructured), blocs);
314 
315  nb_of_sequences_to_reduce = gen_length (sequences_to_reduce);
316 
317  /* Do the job on the sequences */
318  FOREACH(CONTROL, current_control, sequences_to_reduce)
319  {
321  control new_entry_of_imbricated = control_undefined;
322  control new_exit_of_imbricated = control_undefined;
323  pips_debug(2,"Imbricated sequence: REDUCING\n");
324  debug_control ("REDUCE SEQUENCE: ", current_control, 5);
325  reduce_sequence (current_control,
327  &new_entry_of_imbricated,
328  &new_exit_of_imbricated);
329  pips_debug(5,"Entry of imbricated sequence is %p\n",new_entry_of_imbricated);
330  pips_debug(5,"Exit of imbricated sequence is %p\n",new_exit_of_imbricated);
331  if (current_control == unstructured_entry (the_unstructured)) {
332  pips_debug(5,"Changing entry %p for %p\n",
333  unstructured_entry (the_unstructured),
334  new_entry_of_imbricated);
335  unstructured_entry (the_unstructured) = new_entry_of_imbricated;
336  }
337  else if (current_control == unstructured_exit (the_unstructured)) {
338  pips_debug(5,"Changing exit %p for %p\n",
339  unstructured_exit (the_unstructured),
340  new_exit_of_imbricated);
341  unstructured_exit (the_unstructured) = new_exit_of_imbricated;
342  }
343  /*free_control(current_control);*/
344  }
345 
346  /* Check the unstructured to flatten */
347  CONTROL_MAP (current_control, {
349  switch (instruction_tag(i)) {
351  {
352  unstructured_to_flatten
353  = CONS(CONTROL,
354  current_control,
355  unstructured_to_flatten);
356  pips_debug (5, "MARKING UNSTRUCTURED: %p\n", current_control);
357  debug_control ("UNSTRUCTURED: ", current_control, 5);
358  }
359  default:
360  break;
361  }
362  }, unstructured_entry (the_unstructured), blocs);
363 
364  nb_of_unstructured_to_flatten = gen_length (unstructured_to_flatten);
365 
366  /* Do the job on the unstructured */
367  MAP (CONTROL, current_control, {
370  pips_debug(2,"Imbricated unstructured: FLATTENING\n");
371  pips_debug(5,"Flatten unstructured\n");
372  debug_control ("FLATTEN UNSTRUCTURED: ", current_control, 5);
373  replace_control_with_unstructured (u, current_control);
374  /*free_control(current_control);*/
375  }, unstructured_to_flatten);
376 
377  }
378  while (((nb_of_sequences_to_reduce > 0)
379  || (nb_of_unstructured_to_flatten > 0)) && (debug_iteration < 3));
380 
381 }
382 
383 /**
384  * This function connect the unstructured unstructured_statement to the
385  * current Control Flow Graph between control nodes current_control and
386  * next_control
387  */
388 static control connect_unstructured (statement unstructured_statement,
389  control current_control,
390  control next_control)
391 {
392  unstructured the_unstructured
393  = instruction_unstructured(statement_instruction(unstructured_statement));
394  control exit;
395 
396  pips_assert("Control with 1 successors in CONNECT_UNSTRUCTURED",
397  gen_length(control_successors(current_control)) == 1);
398  pips_assert("Control with 1 predecessor in CONNECT_UNSTRUCTURED",
399  gen_length(control_predecessors(next_control)) == 1);
400  pips_assert("Control connections in CONNECT_UNSTRUCTURED",
401  CONTROL(gen_nth(0,control_successors(current_control)))
402  == next_control);
403 
404  exit = unstructured_exit (the_unstructured);
405 
406  pips_assert("Exit with no successors in CONNECT_UNSTRUCTURED",
408  /* pips_assert("Entry with no predecessor in CONNECT_UNSTRUCTURED",
409  gen_length(control_predecessors(entry)) == 0); */
410 
411  pips_debug(5,"connect_unstructured BEFORE flatten_unstructured()\n");
412  ifdebug(5) {
413  print_statement (unstructured_statement);
414  }
415 
416  flatten_unstructured (the_unstructured);
417 
418  pips_debug(5,"connect_unstructured AFTER flatten_unstructured()\n");
419  ifdebug(5) {
420  print_statement (unstructured_statement);
421  }
422 
423  exit = unstructured_exit (the_unstructured);
424  unlink_2_control_nodes (current_control, next_control);
425  link_2_control_nodes (current_control, unstructured_entry(the_unstructured));
426  link_2_control_nodes (unstructured_exit(the_unstructured), next_control);
427 
428  return exit;
429 }
430 
431 /**
432  * This function connect the unstructured the_unstructured to the
433  * current Control Flow Graph at the place of specified control
434  * the_control. The predecessors and successors will be the same as
435  * the_control predecessors and successors.
436  * Return the new current control, which is the exit of passed unstructured
437  */
439  control current_control)
440 {
441  control entry, exit;
442  int i;
443 
444  /* Conserve lists of predecessors and successors */
445  list predecessors = gen_copy_seq (control_predecessors(current_control));
446  list successors = gen_copy_seq (control_successors(current_control));
447 
448  /* Deconnect all the predecessors */
449  for (i=0; i<(int)gen_length(predecessors); i++) {
450  unlink_2_control_nodes (CONTROL(gen_nth(i,predecessors)), current_control);
451  }
452 
453  /* Deconnect all the successors */
454  for (i=0; i<(int)gen_length(successors); i++) {
455  unlink_2_control_nodes (current_control, CONTROL(gen_nth(i,successors)));
456  }
457 
458  flatten_unstructured (the_unstructured);
459 
460  entry = unstructured_entry (the_unstructured);
461  exit = unstructured_exit (the_unstructured);
462 
463  /*pips_assert("Entry of unstructured has no predecessor",
464  gen_length(control_predecessors(entry)) == 0);*/
465 
466  pips_assert("Exit of unstructured has no successor",
468 
469  /* Reconnect all the predecessors */
470  /* ATTENTION link_2_control_nodes add to the list at the first position,
471  so we need to reconnect in the reverse order */
472  for (i=gen_length(predecessors)-1; i>=0; i--) {
474  }
475 
476  /* Reconnect all the successors */
477  /* ATTENTION link_2_control_nodes add to the list at the first position,
478  so we need to reconnect in the reverse order */
479  for (i=gen_length(successors)-1; i>=0; i--) {
481  }
482 
483  return exit;
484 }
485 
486 /**
487  * This function recursively takes the stat statement and transform the
488  * Control Flow Graph module_unstructured in order to generate equivalent
489  * code. The statement to transform is assumed to be executed between
490  * controls current_control and next_control.
491  *
492  * Generated unstructured is equivalent to a FSM where all the states are
493  * the different nodes of the Control Flow Graph
494  *
495  * This function return the control node corresponding to the new position
496  * in the Control Flow Graph
497  */
499  const char* module_name,
500  unstructured module_unstructured,
501  control current_control,
502  control next_control)
503 {
504 
506 
507  ifdebug(2) {
508  debug_statement("FULL_SPAGHETTIFY: Module statement: =====================================", stat, 2);
509 
510  pips_assert("Control with 1 successors in FULL_SPAGHETTIFY",
511  gen_length(control_successors(current_control)) == 1);
512  pips_assert("Control with 1 predecessor in FULL_SPAGHETTIFY",
513  gen_length(control_predecessors(next_control)) == 1);
514  pips_assert("Control connections in FULL_SPAGHETTIFY",
515  CONTROL(gen_nth(0,control_successors(current_control)))
516  == next_control);
517  }
518 
519  switch (instruction_tag(i)) {
520  case is_instruction_test:
521  {
522  pips_debug(2, "full_spaghettify_statement: TEST\n");
523  return
525  current_control,
526  next_control);
527  break;
528  }
530  {
532  control last_control = current_control;
533  pips_debug(2, "full_spaghettify_statement: SEQUENCE\n");
534  MAP(STATEMENT, current_stat,
535  {
536  last_control = full_spaghettify_statement (current_stat,
537  module_name,
538  module_unstructured,
539  last_control,
540  next_control);
541  }, sequence_statements(seq));
542  /*free_statement(stat);*/
543  return last_control;
544  break;
545  }
546  case is_instruction_loop: {
547  pips_debug(2, "full_spaghettify_statement: LOOP\n");
548  return
550  current_control,
551  next_control);
552  break;
553  }
555  pips_debug(2, "full_spaghettify_statement: WHILELOOP\n");
556  return
558  current_control,
559  next_control);
560  break;
561  }
562  case is_instruction_forloop: {
563  pips_debug(2, "full_spaghettify_statement: FORLOOP\n");
565  current_control,
566  next_control);
567  break;
568  }
569  case is_instruction_call: {
570  control new_control = make_control (stat, NIL, NIL);
571  pips_debug(2, "full_spaghettify_statement: CALL\n");
572  unlink_2_control_nodes (current_control, next_control);
573  link_2_control_nodes (current_control, new_control);
574  link_2_control_nodes (new_control, next_control);
575  return new_control;
576  break;
577  }
579  pips_debug(2, "full_spaghettify_statement: UNSTRUCTURED\n");
580  ifdebug(5) {
581  print_statement (stat);
582  }
583  return
584  connect_unstructured (stat,
585  current_control,
586  next_control);
587  break;
588  }
589  default:
590  pips_user_warning("full_spaghettify_statement: UNDEFINED\n");
591  return current_control;
592  break;
593  }
594 
595 
596 }
597 
598 
599 /*********************************************************
600  * Phase main
601  *********************************************************/
602 
603 bool full_spaghettify(const char* module_name)
604 {
605  /* get the resources */
606  statement stat = (statement) db_get_memory_resource(DBR_CODE,
607  module_name,
608  true);
609 
612 
613  debug_on("SPAGUETTIFY_DEBUG_LEVEL");
614 
615  /* Now do the job */
616  stat = full_spaghettify_module(stat, module_name);
617 
618  pips_assert("Statement is consistent after FULL_SPAGUETTIFY",
619  statement_consistent_p(stat));
620 
621  pips_assert("Unstructured is consistent after FULL_SPAGUETTIFY",
623 
624  /* Reorder the module, because new statements have been added */
625  module_reorder(stat);
626 
627  ifdebug(5) {
628  pips_debug(5,"====================================================\n");
629  pips_debug(5,"Statement BEFORE simple_restructure_statement\n");
630  print_statement (stat);
631  }
632 
633  /* Restructure the module */
635 
636  ifdebug(5) {
637  pips_debug(5,"====================================================\n");
638  pips_debug(5,"Statement AFTER simple_restructure_statement\n");
639  print_statement (stat);
640  }
641 
642  /* Reorder the module, because new statements have been added */
643  module_reorder(stat);
644 
645  pips_assert("Statement is consistent after FULL_SPAGUETTIFY",
646  statement_consistent_p(stat));
647 
648  /**
649  * ATTENTION
650  * after simple_restructure_statement, statement stat is
651  * not longer a unstructured, but may be a sequence !!!
652  */
653 
654  DB_PUT_MEMORY_RESOURCE(DBR_CODE, module_name, stat);
655  DB_PUT_MEMORY_RESOURCE(DBR_CALLEES, module_name,
656  compute_callees(stat));
657 
658  /* update/release resources */
661 
662  debug_off();
663 
664  return true;
665 }
666 
unstructured make_unstructured(control a1, control a2)
Definition: ri.c:2778
bool unstructured_consistent_p(unstructured p)
Definition: ri.c:2751
bool statement_consistent_p(statement p)
Definition: ri.c:2195
statement make_statement(entity a1, intptr_t a2, intptr_t a3, string a4, instruction a5, list a6, string a7, extensions a8, synchronization a9)
Definition: ri.c:2222
instruction make_instruction(enum instruction_utype tag, void *val)
Definition: ri.c:1166
synchronization make_synchronization_none(void)
Definition: ri.c:2424
control make_control(statement a1, list a2, list a3)
Definition: ri.c:523
static statement module_statement
Definition: alias_check.c:125
void const char const char const int
callees compute_callees(const statement stat)
Recompute the callees of a module statement.
Definition: callgraph.c:355
struct _newgen_struct_statement_ * statement
Definition: cloning.h:21
static list predecessors(statement st, graph tg)
static list successors(list l)
void simple_restructure_statement(statement)
A simple cleaning of the control graph without major topological restructuring.
const char * module_name(const char *s)
Return the module part of an entity name.
Definition: entity_names.c:296
statement spaghettify_forloop(statement stat, const char *module_name)
This function takes the statement stat as parameter and return a new spaghettized statement,...
static void flatten_unstructured(unstructured the_unstructured)
This function takes as entry an unstructured and flatten it:
static control full_spaghettify_statement(statement stat, const char *module_name, unstructured u, control current_control, control next_control)
The spaghettifier is used in context of PHRASE project while creating "Finite State Machine"-like cod...
static control connect_unstructured(statement unstructured_statement, control current_control, control next_control)
This function connect the unstructured unstructured_statement to the current Control Flow Graph betwe...
static statement full_spaghettify_module(statement module_statement, const char *module_name)
static void reduce_sequence(control current_control, sequence seq, control *new_entry, control *new_exit)
This function reduce the sequence seq at the position in the control graph indicated by control curre...
bool full_spaghettify(const char *module_name)
full_spaghettify.c
static control replace_control_with_unstructured(unstructured the_unstructured, control current_control)
This function connect the unstructured the_unstructured to the current Control Flow Graph at the plac...
void unlink_2_control_nodes(control source, control target)
Remove all edged between 2 control nodes.
Definition: control.c:1276
void link_2_control_nodes(control source, control target)
Add an edge between 2 control nodes.
Definition: control.c:1193
#define CONTROL_MAP(ctl, code, c, list)
Macro to walk through all the controls reachable from a given control node of an unstructured.
void reset_current_module_entity(void)
Reset the current module entity.
Definition: static.c:97
void reset_current_module_statement(void)
Reset the current module statement.
Definition: static.c:221
statement set_current_module_statement(statement)
Set the current module statement.
Definition: static.c:165
entity set_current_module_entity(entity)
static.c
Definition: static.c:66
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
list gen_copy_seq(list l)
Copy a list structure.
Definition: list.c:501
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
#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
gen_chunk gen_nth(int n, const list l)
to be used as ENTITY(gen_nth(3, l))...
Definition: list.c:710
#define MAP(_map_CASTER, _map_item, _map_code, _map_list)
Apply/map an instruction block on all the elements of a list (old fashioned)
Definition: newgen_list.h:226
string db_get_memory_resource(const char *rname, const char *oname, bool pure)
Return the pointer to the resource, whatever it is.
Definition: database.c:755
#define DB_PUT_MEMORY_RESOURCE(res_name, own_name, res_val)
conform to old interface.
Definition: pipsdbm-local.h:66
unstructured statement_unstructured(statement stat)
Get the unstructured of a statement.
Definition: statement.c:1416
statement make_continue_statement(entity)
Definition: statement.c:953
statement spaghettify_loop(statement stat, const char *module_name)
This function takes the statement stat as parameter and return a new spaghettized statement,...
#define debug_on(env)
Definition: misc-local.h:157
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
#define pips_user_warning
Definition: misc-local.h:146
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define debug_off()
Definition: misc-local.h:160
#define exit(code)
Definition: misc-local.h:54
statement spaghettify_test(statement, const char *)
test_spaghettify.c
void short_debug_unstructured(unstructured, int)
DEBUG FUNCTION: print debugging informations for an unstructured an_unstructured (short version)
Definition: phrase_tools.c:213
void debug_statement(const char *, statement, int)
DEBUG FUNCTION: print debugging informations for a statement stat.
Definition: phrase_tools.c:111
void debug_control(const char *, control, int)
DEBUG FUNCTION: print debugging informations for a control a_control.
Definition: phrase_tools.c:134
statement spaghettify_whileloop(statement, const char *)
whileloop_spaghettify.c
void print_statement(statement)
Print a statement on stderr.
Definition: statement.c:98
bool module_reorder(statement body)
Reorder a module and recompute order to statement if any.
Definition: reorder.c:244
#define empty_comments
Empty comments (i.e.
entity module_name_to_entity(const char *mn)
This is an alias for local_name_to_top_level_entity.
Definition: entity.c:1479
entity entity_empty_label(void)
Definition: entity.c:1105
#define control_undefined
Definition: ri.h:916
#define control_predecessors(x)
Definition: ri.h:943
#define statement_ordering(x)
Definition: ri.h:2454
#define CONTROL(x)
CONTROL.
Definition: ri.h:910
@ is_instruction_unstructured
Definition: ri.h:1475
@ is_instruction_whileloop
Definition: ri.h:1472
@ is_instruction_test
Definition: ri.h:1470
@ is_instruction_call
Definition: ri.h:1474
@ is_instruction_sequence
Definition: ri.h:1469
@ is_instruction_forloop
Definition: ri.h:1477
@ is_instruction_loop
Definition: ri.h:1471
#define instruction_tag(x)
Definition: ri.h:1511
#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 control_successors(x)
Definition: ri.h:945
#define unstructured_exit(x)
Definition: ri.h:3006
#define unstructured_entry(x)
Definition: ri.h:3004
#define statement_instruction(x)
Definition: ri.h:2458
#define control_statement(x)
Definition: ri.h:941
#define statement_number(x)
Definition: ri.h:2452
#define instruction_unstructured(x)
Definition: ri.h:1532
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
#define ifdebug(n)
Definition: sg.c:47
The structure used to build lists in NewGen.
Definition: newgen_list.h:41