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