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