PIPS
graph.c
Go to the documentation of this file.
1 /*
2 
3  $Id: graph.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 #include <stdio.h>
29 #include <strings.h>
30 
31 #include "linear.h"
32 
33 #include "genC.h"
34 #include "ri.h"
35 #include "text.h"
36 #include "text-util.h"
37 #include "database.h"
38 
39 #include "misc.h"
40 #include "ri-util.h"
41 #include "resources.h"
42 #include "pipsdbm.h"
43 #include "control.h"
44 
45 /* global mapping from statements to their control in the full control graph
46  */
48 
49 /* the crtl_graph is freed by hand, because the default behavior is
50  * not convenient for my purpose. I would have needed a persistant
51  * statement in the control, but it is not desired in pips.
52  */
54 {
55  CONTROLMAP_MAP(s, c,
56  {
57  pips_debug(7, "statement (%td,%td)\n",
60 
66  },
67  get_ctrl_graph());
68 
69  close_ctrl_graph(); /* now it can be freed safely */
70 }
71 
72 /* add (s1) --> (s2),
73  * that is s2 as successor of s1 and s1 as predecessor of s2.
74  * last added put in first place.
75  * this property is used for a depth first enumeration.
76  */
77 static void
79 {
80  control
81  c1 = load_ctrl_graph(s1),
82  c2 = load_ctrl_graph(s2);
83 
84  pips_debug(7, "(%td,%td:%td) -> (%td,%td;%td)\n",
90  statement_number(s2));
91 
94 }
95 
96 static void add_arrows_in_ctrl_graph(statement s, /* statement */ list l)
97 {
98  for(; !ENDP(l); l=CDR(l))
100 }
101 
102 list /* of statement */
104 {
105  list /* of statements */ ls = NIL;
106  MAP(CONTROL, c, ls = CONS(STATEMENT, control_statement(c), ls), lc);
107  return ls;
108 }
109 
110 static void statement_arrows(statement s, /* statement */ list next)
111 {
113  tag t = instruction_tag(i);
114 
115  switch(t)
116  {
118  {
119  statement current, succ;
120  list /* of statements */
121  l = instruction_block(i),
122  just_next;
123 
124  if (ENDP(l))
125  {
126  add_arrows_in_ctrl_graph(s, next);
127  return;
128  }
129  /* else
130  */
132 
133  for(current = STATEMENT(CAR(l)),
134  l = CDR(l),
135  succ = ENDP(l) ? statement_undefined : STATEMENT(CAR(l)),
136  just_next = CONS(STATEMENT, succ, NIL);
137  !ENDP(l);
138  current = succ,
139  l = CDR(l),
140  succ = ENDP(l) ? statement_undefined : STATEMENT(CAR(l)),
141  STATEMENT_(CAR(just_next)) = succ)
142  {
143  statement_arrows(current, just_next);
144  }
145 
146  gen_free_list(just_next), just_next=NIL;
147 
148  statement_arrows(current, next);
149  break;
150  }
151  case is_instruction_test:
152  {
153  test
154  x = instruction_test(i);
155  statement
156  strue = test_true(x),
157  sfalse = test_false(x);
158 
159  add_arrow_in_ctrl_graph(s, sfalse),
160  statement_arrows(sfalse, next);
161 
162  add_arrow_in_ctrl_graph(s, strue), /* true is before false */
163  statement_arrows(strue, next);
164 
165  break;
166  }
168  case is_instruction_loop:
169  {
170  statement b;
171  list /* of statements */ just_next =
172  gen_nconc(gen_copy_seq(next), CONS(STATEMENT, s, NIL));
173 
174  if(instruction_loop_p(i)) {
175  loop l = instruction_loop(i);
176  b = loop_body(l);
177  }
178  else {
180  b = whileloop_body(l);
181  }
182 
183  add_arrows_in_ctrl_graph(s, next); /* no iteration */
184  add_arrow_in_ctrl_graph(s, b); /* some iterations, first */
185 
186  statement_arrows(b, just_next);
187 
188  gen_free_list(just_next), just_next=NIL;
189 
190  break;
191  }
192  case is_instruction_call:
193  add_arrows_in_ctrl_graph(s, next);
194  break;
196  {
198  list /* of statements */
199  blocks = NIL,
200  lstat = NIL;
201  statement x;
203 
205 
206  /* hmmm... I'm not too confident in this loop.
207  * ??? what should be done with next?
208  * ??? should I trust the graph? I hope I can.
209  */
210  CONTROL_MAP(c,
211  {
212  x = control_statement(c);
214  (control_successors(c));
215 
216  statement_arrows(x, lstat);
217  gen_free_list(lstat);
218  },
219  c_in,
220  blocks);
221 
223 
224  break;
225  }
226  case is_instruction_goto:
227  default:
228  pips_internal_error("unexpected instruction tag (%d)", t);
229  }
230 }
231 
232 static void stmt_rewrite(statement s)
233 {
234  if (!bound_ctrl_graph_p(s))
236 }
237 
239 {
240  pips_debug(3, "statement (%td,%td:%td)\n",
243  statement_number(s));
244 
245  /* first pass to initialize the ctrl_graph controls
246  */
247  init_ctrl_graph();
249  statement_domain, gen_true, stmt_rewrite, /* STATEMENT */
250  NULL);
251 
252  /* second pass to link the statements
253  */
254  statement_arrows(s, NIL);
255 }
256 
257 /* FULL CONTROL GRAPH for module NAME
258  */
259 void full_control_graph(string name)
260 {
261  statement s = (statement) db_get_memory_resource(DBR_CODE, name, true);
263 
264  /* should put something in the db if made as a pass
265  */
266 }
267 
268 /* TRAVELLING on the control graph
269  *
270  * init, next, close functions.
271  * - the init function is given a starting point (statement) s and a
272  * decision function decision. The function should say whether to
273  * go on with the successors of its arguments.
274  * - the next function gives the next visited statement.
275  * - the close function frees the static data.
276  */
277 
278 #ifndef bool_undefined
279  #define bool_undefined ((bool) (-15))
280  #define bool_undefined_p(b) ((b)==bool_undefined)
281 #endif
282 
283 /* Static data for the travel.
284  * - the stack stores the statements to see
285  * - the mapping stores the already stacked statements
286  * - decision function...
287  */
289 GENERIC_LOCAL_MAPPING(stacked, bool, statement)
290 static bool (*travel_decision)(statement);
291 
293 {
294  if (load_statement_stacked(s)!=true)
295  {
296  to_see_push(s);
297  store_statement_stacked(s, true);
298  }
299 }
300 
301 /* it is pushed in *reverse* order to preserve the depth first view.
302  */
303 static void push(/* control */ list l)
304 {
305  if (!ENDP(l))
306  push(CDR(l)),
308 }
309 
311 {
313 }
314 
315 void init_ctrl_graph_travel(statement s, bool (*decision)(statement))
316 {
317  make_to_see_stack(); /* initializations */
318  make_stacked_map();
319  travel_decision = decision;
320 
321  store_statement_stacked(s, true); /* no loop back */
322  push_successors(s);
323 }
324 
326 {
327  while (!to_see_empty_p())
328  {
329  *ps = to_see_pop();
330  if ((*travel_decision)(*ps))
331  {
332  push_successors(*ps);
333  return true;
334  }
335  }
336 
337  return false;
338 }
339 
341 {
342  free_to_see_stack();
343  free_stacked_map();
344 }
345 
346 /* That's all
347  */
static void push_if_necessary(statement s)
Definition: graph.c:292
static void push(list l)
it is pushed in reverse order to preserve the depth first view.
Definition: graph.c:303
list control_list_to_statement_list(list lc)
of statement
Definition: graph.c:103
static void push_successors(statement s)
Definition: graph.c:310
static void stmt_rewrite(statement s)
Definition: graph.c:232
static void add_arrow_in_ctrl_graph(statement s1, statement s2)
add (s1) --> (s2), that is s2 as successor of s1 and s1 as predecessor of s2.
Definition: graph.c:78
static void add_arrows_in_ctrl_graph(statement s, list l)
Definition: graph.c:96
bool next_ctrl_graph_travel(statement *ps)
Definition: graph.c:325
static void statement_arrows(statement s, list next)
Definition: graph.c:110
void clean_ctrl_graph()
global mapping from statements to their control in the full control graph
Definition: graph.c:53
void close_ctrl_graph_travel(void)
Definition: graph.c:340
static bool(* travel_decision)(statement)
Static data for the travel.
Definition: graph.c:290
void init_ctrl_graph_travel(statement s, bool(*decision)(statement))
Definition: graph.c:315
void build_full_ctrl_graph(statement s)
Definition: graph.c:238
void full_control_graph(string name)
FULL CONTROL GRAPH for module NAME.
Definition: graph.c:259
control make_control(statement a1, list a2, list a3)
Definition: ri.c:523
FILE * c_in
Definition: c_syntax.h:291
struct _newgen_struct_statement_ * statement
Definition: cloning.h:21
static list blocks
lisp of loops
controlmap get_ctrl_graph(void)
void store_ctrl_graph(statement, control)
void close_ctrl_graph(void)
control load_ctrl_graph(statement)
void init_ctrl_graph(void)
bool bound_ctrl_graph_p(statement)
#define CONTROL_MAP(ctl, code, c, list)
Macro to walk through all the controls reachable from a given control node of an unstructured.
void gen_multi_recurse(void *o,...)
Multi recursion visitor function.
Definition: genClib.c:3428
bool gen_true(__attribute__((unused)) gen_chunk *unused)
Return true and ignore the argument.
Definition: genClib.c:2780
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
#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
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
list gen_nconc(list cp1, list cp2)
physically concatenates CP1 and CP2 but do not duplicates the elements
Definition: list.c:344
#define CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
#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 pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
#define pips_internal_error
Definition: misc-local.h:149
#define GENERIC_GLOBAL_FUNCTION(name, type)
#define GENERIC_LOCAL_MAPPING(name, result, type)
to allow mappings local to a file.
#define DEFINE_LOCAL_STACK(name, type)
int tag
TAG.
Definition: newgen_types.h:92
#define ORDERING_NUMBER(o)
#define ORDERING_STATEMENT(o)
#define unstructured_control
After the modification in Newgen: unstructured = entry:control x exit:control we have create a macro ...
#define is_instruction_block
soft block->sequence transition
#define instruction_block(i)
#define STATEMENT_(x)
Definition: ri.h:2416
#define loop_body(x)
Definition: ri.h:1644
#define instruction_loop_p(x)
Definition: ri.h:1518
#define control_predecessors(x)
Definition: ri.h:943
#define CONTROLMAP_MAP(k, v, c, f)
Definition: ri.h:900
#define instruction_loop(x)
Definition: ri.h:1520
#define statement_ordering(x)
Definition: ri.h:2454
#define test_false(x)
Definition: ri.h:2837
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
#define CONTROL(x)
CONTROL.
Definition: ri.h:910
@ is_instruction_goto
Definition: ri.h:1473
@ 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_loop
Definition: ri.h:1471
#define instruction_tag(x)
Definition: ri.h:1511
#define test_true(x)
Definition: ri.h:2835
#define control_successors(x)
Definition: ri.h:945
#define instruction_whileloop(x)
Definition: ri.h:1523
#define whileloop_body(x)
Definition: ri.h:3162
#define statement_instruction(x)
Definition: ri.h:2458
#define control_statement(x)
Definition: ri.h:941
#define instruction_test(x)
Definition: ri.h:1517
#define statement_number(x)
Definition: ri.h:2452
#define instruction_unstructured(x)
Definition: ri.h:1532
#define statement_undefined
Definition: ri.h:2419
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
s1
Definition: set.c:247
static char * x
Definition: split_file.c:159
static size_t current
Definition: string.c:115
The structure used to build lists in NewGen.
Definition: newgen_list.h:41