710b900f2f9517ae7a7e09007f68265885a9383c
[libfirm] / ir / ir / irgraph.c
1 /* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
2 ** All rights reserved.
3 **
4 ** Authors: Martin Trapp, Christian Schaefer
5 **
6 **
7 */
8
9 /* $Id$ */
10
11 #ifdef HAVE_CONFIG_H
12 # include <config.h>
13 #endif
14
15 # include <string.h>
16
17 # include "ircons.h"
18 # include "irgraph_t.h"
19 # include "irprog_t.h"
20 # include "iropt_t.h"
21 # include "array.h"
22 # include "irgmod.h"
23 # include "mangle.h"
24
25 ir_graph *current_ir_graph;
26 INLINE ir_graph *get_current_ir_graph() {
27   return current_ir_graph;
28 }
29 INLINE void set_current_ir_graph(ir_graph *graph) {
30   current_ir_graph = graph;
31 }
32
33
34 bool interprocedural_view = false;
35 INLINE bool get_interprocedural_view() {
36   return interprocedural_view;
37 }
38 INLINE void set_interprocedural_view(bool state) {
39   interprocedural_view = state;
40 }
41
42 #if USE_EXPLICIT_PHI_IN_STACK
43 /* really defined in ircons.c */
44 typedef struct Phi_in_stack Phi_in_stack;
45 Phi_in_stack *new_Phi_in_stack();
46 void free_Phi_in_stack(Phi_in_stack *s);
47 #endif
48
49 /* Allocates a list of nodes:
50     - The start block containing a start node and Proj nodes for it's four
51       results (X, M, P, Tuple).
52     - The end block containing an end node. This block is not matured after
53       new_ir_graph as predecessors need to be added to it.
54     - The current block, which is empty and also not matured.
55    Further it allocates several datastructures needed for graph construction
56    and optimization.
57 */
58 ir_graph *
59 new_ir_graph (entity *ent, int n_loc)
60 {
61   int i;
62   ir_graph *res;
63   ir_node *first_block;
64   ir_node *projX;
65
66   res = (ir_graph *) malloc (sizeof (ir_graph));
67   current_ir_graph = res;
68   add_irp_irg(res);          /* remember this graph global. */
69
70   /** Internal information for graph construction either held in the graph or
71   *** initialized for each graph. **/
72 #if PRECISE_EXC_CONTEXT
73   res->n_loc = n_loc + 1 + 1; /* number of local variables that are never
74                                  dereferenced in this graph plus one for
75                                  the store plus one for links to fragile
76                                  operations.  n_loc is not the number of
77                                  parameters to the procedure!  */
78 #else
79   res->n_loc = n_loc + 1;  /* number of local variables that are never
80                               dereferenced in this graph plus one for
81                               the store. This is not the number of parameters
82                               to the procedure!  */
83 #endif
84
85   res->visited = 0;     /* visited flag, for the ir walker */
86   res->block_visited=0; /* visited flag, for the 'block'-walker */
87
88 #if USE_EXPLICIT_PHI_IN_STACK
89   res->Phi_in_stack = new_Phi_in_stack();  /* A stack needed for automatic Phi
90                                 generation */
91 #endif
92   res->obst      = (struct obstack *) xmalloc (sizeof (struct obstack));
93   obstack_init (res->obst);
94   res->value_table = new_identities (); /* value table for global value
95                                            numbering for optimizing use in
96                                            iropt.c */
97   res->outs = NULL;
98
99   res->phase_state = phase_building;
100   res->pinned = pinned;
101   res->outs_state = no_outs;
102   res->dom_state = no_dom;
103
104   /** Type information for the procedure of the graph **/
105   res->ent = ent;
106   set_entity_irg(ent, res);
107
108   /** A type that represents the stack frame.  A class type so that it can
109       contain "inner" methods as in Pascal. **/
110   res->frame_type = new_type_class(mangle(get_entity_ident(ent),
111           id_from_str(FRAME_TP_SUFFIX, strlen(FRAME_TP_SUFFIX))));
112   /* Remove type from type list.  Must be treated differently than other types. */
113   remove_irp_type_from_list(res->frame_type);
114
115   /** Nodes needed in every graph **/
116   res->end_block = new_immBlock ();
117   res->end       = new_End ();
118
119   res->start_block = new_immBlock ();
120   res->start   = new_Start ();
121   res->bad     = new_ir_node (NULL, res, res->start_block, op_Bad, mode_T, 0, NULL);
122   res->unknown = new_ir_node (NULL, res, res->start_block, op_Unknown, mode_T, 0, NULL);
123
124   /* Proj results of start node */
125   projX        = new_Proj (res->start, mode_X, pns_initial_exec);
126   set_store (new_Proj (res->start, mode_M, pns_global_store));
127   res->frame   = new_Proj (res->start, mode_P, pns_frame_base);
128   res->globals = new_Proj (res->start, mode_P, pns_globals);
129   res->args    = new_Proj (res->start, mode_T, pns_args);
130
131   add_in_edge(res->start_block, projX);
132   /*
133    * The code generation needs it. leave it in now.
134    * Use of this edge is matter of discussion, unresolved. Also possible:
135    * add_in_edge(res->start_block, res->start_block), but invalid typed.
136    */
137   mature_block (res->current_block);
138
139   /** Make a block to start with **/
140   first_block = new_immBlock ();
141   add_in_edge (first_block, projX);
142
143   return res;
144 }
145
146
147 /* Make a rudimentary ir graph for the constant code.
148    Must look like a correct irg, spare everything else. */
149 ir_graph *new_const_code_irg() {
150   ir_graph *res;
151   ir_node *projX;
152
153   res = (ir_graph *) malloc (sizeof (ir_graph));
154   current_ir_graph = res;
155   res->n_loc = 1;      /* Only the memory. */
156   res->visited = 0;     /* visited flag, for the ir walker */
157   res->block_visited=0; /* visited flag, for the 'block'-walker */
158 #if USE_EXPLICIT_PHI_IN_STACK
159   res->Phi_in_stack = NULL;
160 #endif
161   res->obst      = (struct obstack *) xmalloc (sizeof (struct obstack));
162   obstack_init (res->obst);
163   res->pinned = pinned;
164   res->value_table = new_identities (); /* value table for global value
165                                            numbering for optimizing use in
166                                            iropt.c */
167   res->ent = NULL;
168   res->frame_type = NULL;
169   res->start_block = new_immBlock ();
170   res->end_block = new_immBlock ();
171   res->end       = new_End ();
172   mature_block(get_cur_block());
173   res->bad = new_ir_node (NULL, res, res->start_block, op_Bad, mode_T, 0, NULL);
174   res->unknown = new_ir_node (NULL, res, res->start_block, op_Unknown, mode_T, 0, NULL);
175   res->start   = new_Start ();
176   /* Proj results of start node */
177   projX        = new_Proj (res->start, mode_X, pns_initial_exec);
178   set_store (new_Proj (res->start, mode_M, pns_global_store));
179   add_in_edge(res->start_block, projX);
180   mature_block (res->current_block);
181   add_in_edge (new_immBlock (), projX);
182   mature_block(get_cur_block());
183   /* Set the visited flag high enough that the block will never be visited. */
184   set_irn_visited(get_cur_block(), -1);
185   set_Block_block_visited(get_cur_block(), -1);
186   set_Block_block_visited(res->start_block, -1);
187   return res;
188 }
189
190 /* Frees the passed irgraph.
191    Deallocates all nodes in this graph and the ir_graph structure.
192    Sets the field irgraph in the corresponding entity to NULL.
193    Does not remove the irgraph from the list in irprog (requires
194    inefficient search, call remove_irp_irg by hand).
195    Does not free types, entities or modes that are used only by this
196    graph, nor the entity standing for this graph. */
197 void free_ir_graph (ir_graph *irg) {
198   set_entity_irg(irg->ent, NULL);
199   free(irg->obst);
200 #if USE_EXPLICIT_PHI_IN_STACK
201   free_Phi_in_stack(irg->Phi_in_stack);
202 #endif
203   free(irg);
204 }
205
206 /* access routines for all ir_graph attributes:
207    templates:
208    {attr type} get_irg_{attribute name} (ir_graph *irg);
209    void set_irg_{attr name} (ir_graph *irg, {attr type} {attr}); */
210
211 ir_node *
212 get_irg_start_block (ir_graph *irg)
213 {
214   return irg->start_block;
215 }
216
217 void
218 set_irg_start_block (ir_graph *irg, ir_node *node)
219 {
220   irg->start_block = node;
221 }
222
223 ir_node *
224 get_irg_start (ir_graph *irg)
225 {
226   return irg->start;
227 }
228
229 void
230 set_irg_start(ir_graph *irg, ir_node *node)
231 {
232   irg->start = node;
233 }
234
235 ir_node *
236 get_irg_end_block (ir_graph *irg)
237 {
238   return irg->end_block;
239 }
240
241 void
242 set_irg_end_block (ir_graph *irg, ir_node *node)
243 {
244   irg->end_block = node;
245 }
246
247 ir_node *
248 get_irg_end (ir_graph *irg)
249 {
250   return irg->end;
251 }
252
253 void
254 set_irg_end (ir_graph *irg, ir_node *node)
255 {
256   irg->end = node;
257 }
258
259 ir_node *
260 get_irg_cstore (ir_graph *irg)
261 {
262   return irg->cstore;
263 }
264
265 void
266 set_irg_cstore (ir_graph *irg, ir_node *node)
267 {
268   irg->cstore = node;
269 }
270
271 ir_node *
272 get_irg_frame (ir_graph *irg)
273 {
274   return irg->frame;
275 }
276
277 void
278 set_irg_frame (ir_graph *irg, ir_node *node)
279 {
280   irg->frame = node;
281 }
282
283 ir_node *
284 get_irg_globals (ir_graph *irg)
285 {
286   return irg->globals;
287 }
288
289 void
290 set_irg_globals (ir_graph *irg, ir_node *node)
291 {
292   irg->globals = node;
293 }
294
295 ir_node *
296 get_irg_args (ir_graph *irg)
297 {
298   return irg->args;
299 }
300
301 void
302 set_irg_args (ir_graph *irg, ir_node *node)
303 {
304   irg->args = node;
305 }
306
307 ir_node *
308 get_irg_bad (ir_graph *irg)
309 {
310   return irg->bad;
311 }
312
313 void
314 set_irg_bad (ir_graph *irg, ir_node *node)
315 {
316   irg->bad = node;
317 }
318
319 ir_node *
320 get_irg_unknown (ir_graph *irg)
321 {
322   return irg->unknown;
323 }
324
325 void
326 set_irg_unknown (ir_graph *irg, ir_node *node)
327 {
328   irg->unknown = node;
329 }
330
331 ir_node *
332 get_irg_current_block (ir_graph *irg)
333 {
334   return irg->current_block;
335 }
336
337 void
338 set_irg_current_block (ir_graph *irg, ir_node *node)
339 {
340   irg->current_block = node;
341 }
342
343 entity *
344 get_irg_ent (ir_graph *irg)
345 {
346   assert(irg && irg->ent);
347   return irg->ent;
348 }
349
350 void
351 set_irg_ent (ir_graph *irg, entity *ent)
352 {
353   irg->ent = ent;
354 }
355
356 type *
357 get_irg_frame_type (ir_graph *irg)
358 {
359   assert(irg && irg->frame_type);
360   return irg->frame_type;
361 }
362
363 void
364 set_irg_frame_type (ir_graph *irg, type *ftp)
365 {
366   irg->frame_type = ftp;
367 }
368
369
370 /* To test for a frame type */
371 int
372 is_frame_type(type *ftp) {
373   return ((is_class_type(ftp) || is_struct_type(ftp)) &&
374           id_is_suffix(id_from_str(FRAME_TP_SUFFIX, strlen(FRAME_TP_SUFFIX)),
375                        get_type_ident(ftp)));
376 }
377
378 int
379 get_irg_n_locs (ir_graph *irg)
380 {
381 #if PRECISE_EXC_CONTEXT
382   return irg->n_loc - 1 - 1;
383 #else
384   return irg->n_loc - 1;
385 #endif
386 }
387
388 void
389 set_irg_n_loc (ir_graph *irg, int n_loc)
390 {
391 #if PRECISE_EXC_CONTEXT
392   irg->n_loc = n_loc + 1 + 1;
393 #else
394   irg->n_loc = n_loc + 1;
395 #endif
396 }
397
398 irg_phase_state get_irg_phase_state (ir_graph *irg) {
399   return irg->phase_state;
400 }
401
402 void set_irg_phase_low(ir_graph *irg) {
403   irg->phase_state = phase_low;
404 }
405
406 op_pinned
407 get_irg_pinned (ir_graph *irg) {
408   return irg->pinned;
409 }
410
411 irg_outs_state get_irg_outs_state(ir_graph *irg) {
412   return irg->outs_state;
413 }
414
415 void set_irg_outs_inconsistent(ir_graph *irg) {
416   irg->outs_state = outs_inconsistent;
417 }
418
419 irg_dom_state get_irg_dom_state(ir_graph *irg) {
420   return irg->dom_state;
421 }
422
423 void set_irg_dom_inconsistent(ir_graph *irg) {
424   irg->dom_state = dom_inconsistent;
425 }
426
427 INLINE void
428 set_irg_pinned (ir_graph *irg, op_pinned p) {
429   irg->pinned = p;
430 }
431
432 INLINE void
433 set_irg_link (ir_graph *irg, void *thing) {
434   irg->link = thing;
435 }
436
437 INLINE void *
438 get_irg_link (ir_graph *irg) {
439   return irg->link;
440 }
441
442 /* maximum visited flag content of all ir_graph visited fields. */
443 static int max_irg_visited = 0;
444
445 unsigned long
446 get_irg_visited (ir_graph *irg)
447 {
448   return irg->visited;
449 }
450
451 void
452 set_irg_visited (ir_graph *irg, unsigned long visited)
453 {
454   irg->visited = visited;
455   if (irg->visited > max_irg_visited) {
456     max_irg_visited = irg->visited;
457   }
458 }
459
460 void
461 inc_irg_visited (ir_graph *irg)
462 {
463   if (++irg->visited > max_irg_visited) {
464     max_irg_visited = irg->visited;
465   }
466 }
467
468 unsigned long
469 get_max_irg_visited(void)
470 {
471   int i;
472   //for(i = 0; i < get_irp_n_irgs(); i++)
473   //  assert(max_irg_visited >= get_irg_visited(get_irp_irg(i)));
474   return max_irg_visited;
475 }
476
477 void set_max_irg_visited(int val) {
478   max_irg_visited = val;
479 }
480
481 unsigned long
482 inc_max_irg_visited(void)
483 {
484   int i;
485   //  for(i = 0; i < get_irp_n_irgs(); i++)
486   //assert(max_irg_visited >= get_irg_visited(get_irp_irg(i)));
487   max_irg_visited++;
488   return max_irg_visited;
489 }
490
491 unsigned long
492 get_irg_block_visited (ir_graph *irg)
493 {
494   return irg->block_visited;
495 }
496
497 void
498 set_irg_block_visited (ir_graph *irg, unsigned long visited)
499 {
500   irg->block_visited = visited;
501 }
502
503 void
504 inc_irg_block_visited (ir_graph *irg)
505 {
506   ++irg->block_visited;
507 }