PIPS
old_controlizer.c File Reference
#include <stdio.h>
#include <strings.h>
#include "linear.h"
#include "genC.h"
#include "ri.h"
#include "ri-util.h"
#include "workspace-util.h"
#include "prettyprint.h"
#include "control.h"
#include "properties.h"
#include "misc.h"
#include "constants.h"
#include "text-util.h"
+ Include dependency graph for old_controlizer.c:

Go to the source code of this file.

Macros

#define LABEL_TABLES_SIZE   10
 
#define ADD_PRED_IF_NOT_ALREADY_HERE(pred, c)   (gen_once(pred,control_predecessors(c)))
 In C, we can have some "goto" inside a block from outside, that translate as any complex control graph into an "unstructured" in the PIPS jargon. More...
 
#define ADD_PRED_AND_COPY_IF_NOT_ALREADY_HERE(pred, c)   (gen_once(pred,gen_copy_seq(control_predecessors(c))))
 
#define UPDATE_CONTROL(c, s, pd, sc)
 Update control c by setting its statement to s, by unioning its predecessor set with pd, and by setting its successor set to sc (i.e. More...
 
#define PREDS_OF_SUCCS   1
 
#define SUCCS_OF_PREDS   2
 

Functions

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 successor succ. More...
 
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 of its predecessors or successors list (according to HOW, PREDS_OF_SUCCS or SUCCS_OF_PREDS). More...
 
static control make_conditional_control (statement st)
 Make a control node from a statement if needed. More...
 
static control get_label_control (string name)
 Get the control node associated to a label name. More...
 
static void update_used_labels (hash_table used_labels, string name, statement st)
 Add the reference to the label NAME in the statement ST. More...
 
static hash_table union_used_labels (hash_table l1, hash_table l2)
 Unions 2 used-label hash maps. More...
 
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 mapping. More...
 
static void add_proper_successor_to_predecessor (control pred, control c_res)
 
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. More...
 
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=1), the test (i<10) and the increment (i=i+1). More...
 
statement loop_test (statement sl)
 
statement loop_inc (statement sl)
 
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 and SUCCessor. More...
 
static statement whileloop_test (statement sl)
 Generate a test statement ts for exiting loop sl. More...
 
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 PREDecessor and SUCCessor. More...
 
statement forloop_header (statement sl)
 
statement forloop_test (statement sl)
 
statement forloop_inc (statement sl)
 
static bool controlize_forloop (statement st, forloop l, control pred, control succ, control c_res, hash_table used_labels)
 
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. More...
 
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, i.e. More...
 
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. More...
 
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 successor. More...
 
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. More...
 
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 and allocate a slot in the Label_control table. More...
 
static void create_statements_of_label (statement st)
 CREATE_STATEMENTS_OF_LABELS gathers in the Label_statements table all the references to the useful label of the statement ST. More...
 
static void create_statements_of_labels (st)
 
static unstructured simplified_unstructured (control top, control bottom, control res)
 SIMPLIFIED_UNSTRUCTURED tries to get rid of top-level and useless unstructured nodes. More...
 
unstructured control_graph (statement st)
 CONTROL_GRAPH returns the control graph of the statement ST. More...
 

Variables

char vcid_control_old_controlizer [] = "$Id: old_controlizer.c 23065 2016-03-02 09:05:50Z coelho $"
 old_controlizer.c More...
 
static list Unreachable
 UNREACHABLE is the hook used as a predecessor of statements that are following a goto. More...
 
static hash_table Label_statements
 LABEL_STATEMENTS maps label names to the list of statements where they appear (either as definition or reference). More...
 
static hash_table Label_control
 LABEL_CONTROL maps label names to their (possible forward) control nodes. More...
 

Function Documentation

◆ covers_labels_p()

static bool covers_labels_p ( statement  st,
hash_table  used_labels 
)
static

Compute whether all the label references in a statement are in a given label name to statement list mapping.

Parameters
stis the statement we want to check if it owns all allusion to the given label name in the used_labels mapping
used_labelsis a hash table mapping a label name to a list of statement that use it, as their label or because it is a goto to it
Returns
true if all the label allusion in st are covered by the used_labels mapping.

ifdebug(5) {

pips_debug(5, "Statement %td (%p): \n ", statement_number(st), st);

print_statement(st);

}

For all the labels in used_labels:

The statements using label name in used_labels:

For all the statements associated to label name:

Verify that def is in all the statements associated to the label name according to used_labels.

Not useful to go on:

Definition at line 326 of file old_controlizer.c.

327  {
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 }
static hash_table Label_statements
LABEL_STATEMENTS maps label names to the list of statements where they appear (either as definition o...
#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
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
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define HASH_MAP(k, v, code, ht)
Definition: newgen_hash.h:60
#define true
Definition: newgen_types.h:81
struct cons * list
Definition: newgen_types.h:106
static char * usage
Definition: pips.c:63
#define statement_undefined_p(x)
Definition: ri.h:2420
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
return(s1)
#define ifdebug(n)
Definition: sg.c:47
The structure used to build lists in NewGen.
Definition: newgen_list.h:41

References FOREACH, fprintf(), hash_get_default_empty_list(), HASH_MAP, ifdebug, Label_statements, pips_assert, pips_debug, STATEMENT, and statement_undefined_p.

Referenced by controlize_forloop(), controlize_list(), controlize_loop(), controlize_test(), and controlize_whileloop().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ create_statements_of_label()

static void create_statements_of_label ( statement  st)
static

CREATE_STATEMENTS_OF_LABELS gathers in the Label_statements table all the references to the useful label of the statement ST.

Note that for loops, the label in the DO statement is NOT introduced. Label_control is also created.

Definition at line 1797 of file old_controlizer.c.

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 }
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...
#define pips_internal_error
Definition: misc-local.h:149
#define instruction_goto(x)
Definition: ri.h:1526
#define statement_label(x)
Definition: ri.h:2450
@ is_instruction_goto
Definition: ri.h:1473
@ is_instruction_unstructured
Definition: ri.h:1475
#define instruction_tag(x)
Definition: ri.h:1511
#define entity_name(x)
Definition: ri.h:2790
#define statement_instruction(x)
Definition: ri.h:2458

References entity_name, init_label(), instruction_goto, instruction_tag, is_instruction_goto, is_instruction_unstructured, pips_internal_error, statement_instruction, and statement_label.

Referenced by create_statements_of_labels().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ get_label_control()

static control get_label_control ( string  name)
static

Get the control node associated to a label name.

It looks for the label name into the Label_control table.

The name must be the complete entity name, not a local or a user name.

Parameters
nameis the string name of the label entity
Returns
the associated control

Definition at line 242 of file old_controlizer.c.

242  {
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 }
control check_control(control p)
Definition: ri.c:493
bool empty_global_label_p(const char *gln)
Definition: entity_names.c:264
void check_control_coherency(control c)
Test the coherency of a control node network from a control node.
Definition: control.c:487
static hash_table Label_control
LABEL_CONTROL maps label names to their (possible forward) control nodes.
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
struct _newgen_struct_control_ * control
#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

References check_control(), check_control_coherency(), empty_global_label_p(), hash_get(), HASH_UNDEFINED_VALUE, ifdebug, Label_control, and pips_assert.

Referenced by compact_list(), and controlize().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ make_conditional_control()

static control make_conditional_control ( statement  st)
static

Make a control node from a statement if needed.

It is like make_control() except when the statement

Parameters
sthas a label and is thus already in Label_control
Returns
the new (in the case of a statement without a label) or already associated (in the case of a statement with a label) control node with the statement

It returns NULL if the statement has a label but it is not associated to any control node yet

No label, so there cannot be a control already associated by a label

Get back the control node associated with this statement label. Since we store control object in this hash table, use cast. We rely on the fact that NIL for a list is indeed NULL...

Definition at line 216 of file old_controlizer.c.

216  {
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 }
control make_control(statement a1, list a2, list a3)
Definition: ri.c:523
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47

References empty_global_label_p(), entity_name, hash_get_default_empty_list(), Label_control, make_control(), NIL, and statement_label.

Referenced by control_graph(), controlize_forloop(), controlize_list(), controlize_list_1(), controlize_loop(), controlize_test(), and controlize_whileloop().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ move_declaration_control_node_declarations_to_statement()

static void move_declaration_control_node_declarations_to_statement ( list  ctls)
static

Move all the declarations found in a list of control to a given statement.

@ctls is a list of control nodes

It is useful in the controlizer to keep scoping of declarations even with unstructured that may destroy the variable scoping rules.

If there are conflict names on declarations, they are renamed.

It relies on correct calls to push_declarations()/push_declarations() before to track where to put the declarations.

FI: let's assume they have become scoping_statement_push/pop...

No block statement above, so it is hard to move something there :-)

The variables created in case of name conflict

Look for conflicting names:

There is a conflict name between a declaration in the current statement block and one in the statement block above:

Create a new variable with a non conflicting name:

Add the inner declaration to the upper statement later

Remove the inner declaration from the inner statement block:

Add all the declarations to the statement block above and keep the same order:

Replace all the references on old variables to references to the new ones in all the corresponding control nodes by in the code

We should free in some way the old variable...

Definition at line 976 of file old_controlizer.c.

976  {
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 }
list gen_entity_cons(entity p, list l)
Definition: ri.c:2537
void replace_entity(void *s, entity old, entity new)
per variable version of replace_entities.
Definition: replace.c:113
list gen_nreverse(list cp)
reverse a list in place
Definition: list.c:304
list gen_nconc(list cp1, list cp2)
physically concatenates CP1 and CP2 but do not duplicates the elements
Definition: list.c:344
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327
hash_table hash_table_make(hash_key_type key_type, size_t size)
Definition: hash.c:294
void hash_table_free(hash_table htp)
this function deletes a hash table that is no longer useful.
Definition: hash.c:327
@ hash_chunk
Definition: newgen_hash.h:32
#define hash_put_or_update(h, k, v)
Definition: newgen_hash.h:80
const char * entity_user_name(entity e)
Since entity_local_name may contain PIPS special characters such as prefixes (label,...
Definition: entity.c:487
entity entity_to_module_entity(entity e)
Find the enclosing module of an entity.
Definition: entity.c:2053
entity clone_variable_with_unique_name(entity, statement, string, string, entity)
Clone a variable with a new user name.
Definition: variable.c:562
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define CONTROL(x)
CONTROL.
Definition: ri.h:910
#define statement_declarations(x)
Definition: ri.h:2460
#define control_statement(x)
Definition: ri.h:941

References clone_variable_with_unique_name(), CONTROL, control_statement, ENTITY, entity_name, entity_to_module_entity(), entity_user_name(), FOREACH, gen_entity_cons(), gen_free_list(), gen_nconc(), gen_nreverse(), hash_chunk, HASH_MAP, hash_put_or_update, hash_table_free(), hash_table_make(), NIL, pips_debug, replace_entity(), and statement_declarations.

Referenced by controlize_list().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ union_used_labels()

static hash_table union_used_labels ( hash_table  l1,
hash_table  l2 
)
static

Unions 2 used-label hash maps.

Parameters
l1is an hash map
l2is another hash map
Returns
the union of l1 and l2 interpreted as in the context of update_used_labels()

Definition at line 303 of file old_controlizer.c.

304  {
305  HASH_MAP(name, sts, {
306  FOREACH(STATEMENT, s, sts) {
307  update_used_labels(l1, name, s);
308  };
309  }, l2);
310  return l1;
311 }
static void update_used_labels(hash_table used_labels, string name, statement st)
Add the reference to the label NAME in the statement ST.

References FOREACH, HASH_MAP, STATEMENT, and update_used_labels().

Referenced by controlize_forloop(), controlize_list(), controlize_loop(), controlize_test(), and controlize_whileloop().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ update_used_labels()

static void update_used_labels ( hash_table  used_labels,
string  name,
statement  st 
)
static

Add the reference to the label NAME in the statement ST.

A used_label is a hash_table that maps the label name to the list of statements that references it.

A statement can appear many times for a label

Parameters
used_labelsis the hash table used to record the statements related to a label
nameis the label entity name
stis the statement to be recorded as related to the label

Do something only of there is a label:

Get a previous list of statements related with this label:

Add the given statement to the list

If there was already something associated to the label, register the new list:

Or create a new entry:

Definition at line 269 of file old_controlizer.c.

271  {
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 }
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
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
bool hash_defined_p(const hash_table htp, const void *key)
true if key has e value in htp.
Definition: hash.c:484
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_number(x)
Definition: ri.h:2452

References CONS, debug(), empty_global_label_p(), hash_defined_p(), hash_get_default_empty_list(), hash_put(), hash_update(), STATEMENT, and statement_number.

Referenced by controlize(), and union_used_labels().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ vcid_control_old_controlizer

char vcid_control_old_controlizer[] = "$Id: old_controlizer.c 23065 2016-03-02 09:05:50Z coelho $"

old_controlizer.c

Definition at line 29 of file old_controlizer.c.