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