Add a lot of const
[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)(const 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)(const 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)(const 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)(const 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)(const 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)(const 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)(const 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)(const 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)(const 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)(const 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)(const ir_graph *irg) {
386   return __get_irg_initial_mem(irg);
387 }
388
389 void
390 (set_irg_initial_mem)(ir_graph *irg, ir_node *node) {
391   __set_irg_initial_mem(irg, node);
392 }
393
394 ir_node *
395 (get_irg_args)(const ir_graph *irg) {
396   return __get_irg_args(irg);
397 }
398
399 void
400 (set_irg_args)(ir_graph *irg, ir_node *node) {
401   __set_irg_args(irg, node);
402 }
403
404 ir_node *
405 (get_irg_bad)(const ir_graph *irg) {
406   return __get_irg_bad(irg);
407 }
408
409 void
410 (set_irg_bad)(ir_graph *irg, ir_node *node) {
411   __set_irg_bad(irg, node);
412 }
413
414 /* GL removed: we need unknown with mode for analyses.
415 ir_node *
416 get_irg_unknown (ir_graph *irg)
417 {
418   return irg->unknown;
419 }
420
421 void
422 set_irg_unknown (ir_graph *irg, ir_node *node)
423 {
424   irg->unknown = node;
425 }
426 */
427
428 ir_node *
429 (get_irg_current_block)(const ir_graph *irg) {
430   return __get_irg_current_block(irg);
431 }
432
433 void
434 (set_irg_current_block)(ir_graph *irg, ir_node *node) {
435   __set_irg_current_block(irg, node);
436 }
437
438 entity *
439 (get_irg_entity)(const ir_graph *irg) {
440   return __get_irg_entity(irg);
441 }
442
443 void
444 (set_irg_entity)(ir_graph *irg, entity *ent) {
445   __set_irg_entity(irg, ent);
446 }
447
448 type *
449 (get_irg_frame_type)(const ir_graph *irg) {
450   return __get_irg_frame_type(irg);
451 }
452
453 void
454 (set_irg_frame_type)(ir_graph *irg, type *ftp) {
455   __set_irg_frame_type(irg, ftp);
456 }
457
458
459 /* To test for a frame type */
460 int
461 is_frame_type(const type *ftp) {
462   int i;
463   if (is_class_type(ftp)) {
464     for (i = 0; i < get_irp_n_irgs(); i++) {
465       const type *frame_tp = get_irg_frame_type(get_irp_irg(i));
466       if (ftp == frame_tp) return true;
467     }
468   }
469   return false;
470 }
471
472 int
473 get_irg_n_locs (ir_graph *irg)
474 {
475   if (get_opt_precise_exc_context())
476     return irg->n_loc - 1 - 1;
477   else
478     return irg->n_loc - 1;
479 }
480
481 void
482 set_irg_n_loc (ir_graph *irg, int n_loc)
483 {
484   if (get_opt_precise_exc_context())
485     irg->n_loc = n_loc + 1 + 1;
486   else
487     irg->n_loc = n_loc + 1;
488 }
489
490
491
492 /* Returns the obstack associated with the graph. */
493 struct obstack *
494 (get_irg_obstack)(const ir_graph *irg) {
495   return __get_irg_obstack(irg);
496 }
497
498 /*
499  * Returns true if the node n is allocated on the storage of graph irg.
500  *
501  * Implementation is GLIBC specific as is uses the internal _obstack_chunk implementation.
502  */
503 int node_is_in_irgs_storage(ir_graph *irg, ir_node *n)
504 {
505   struct _obstack_chunk *p;
506
507   /*
508    * checks wheater the ir_node pointer i on the obstack.
509    * A more sophisticated check would test the "whole" ir_node
510    */
511   for (p = irg->obst->chunk; p; p = p->prev) {
512     if (((char *)p->contents <= (char *)n) && ((char *)n < (char *)p->limit))
513       return 1;
514   }
515
516   return 0;
517 }
518
519 irg_phase_state
520 (get_irg_phase_state)(const ir_graph *irg) {
521   return __get_irg_phase_state(irg);
522 }
523
524 void
525 (set_irg_phase_low)(ir_graph *irg) {
526   __set_irg_phase_low(irg);
527 }
528
529 op_pin_state
530 (get_irg_pinned)(const ir_graph *irg) {
531   return __get_irg_pinned(irg);
532 }
533
534 irg_outs_state
535 (get_irg_outs_state)(const ir_graph *irg) {
536   return __get_irg_outs_state(irg);
537 }
538
539 void
540 (set_irg_outs_inconsistent)(ir_graph *irg) {
541   __set_irg_outs_inconsistent(irg);
542 }
543
544 irg_dom_state
545 (get_irg_dom_state)(const ir_graph *irg) {
546   return __get_irg_dom_state(irg);
547 }
548
549 void
550 (set_irg_dom_inconsistent)(ir_graph *irg) {
551   __set_irg_dom_inconsistent(irg);
552 }
553
554 irg_loopinfo_state
555 (get_irg_loopinfo_state)(const ir_graph *irg) {
556   return __get_irg_loopinfo_state(irg);
557 }
558
559 void
560 (set_irg_loopinfo_state)(ir_graph *irg, irg_loopinfo_state s) {
561   __set_irg_loopinfo_state(irg, s);
562 }
563
564 void
565 set_irg_loopinfo_inconsistent(ir_graph *irg) {
566   if (irg->loopinfo_state == loopinfo_ip_consistent)
567     irg->loopinfo_state = loopinfo_ip_inconsistent;
568
569   else if (irg->loopinfo_state == loopinfo_consistent)
570     irg->loopinfo_state = loopinfo_inconsistent;
571
572   else if (irg->loopinfo_state == loopinfo_cf_ip_consistent)
573     irg->loopinfo_state = loopinfo_cf_ip_inconsistent;
574
575   else if (irg->loopinfo_state == loopinfo_cf_consistent)
576     irg->loopinfo_state = loopinfo_cf_inconsistent;
577 }
578
579 void
580 (set_irg_pinned)(ir_graph *irg, op_pin_state p) {
581   __set_irg_pinned(irg, p);
582 }
583
584 irg_callee_info_state
585 (get_irg_callee_info_state)(const ir_graph *irg) {
586   return __get_irg_callee_info_state(irg);
587 }
588
589 void
590 (set_irg_callee_info_state)(ir_graph *irg, irg_callee_info_state s) {
591   __set_irg_callee_info_state(irg, s);
592 }
593
594 irg_inline_property
595 (get_irg_inline_property)(const ir_graph *irg) {
596   return __get_irg_inline_property(irg);
597 }
598
599 void
600 (set_irg_inline_property)(ir_graph *irg, irg_inline_property s) {
601   __set_irg_inline_property(irg, s);
602 }
603
604 void
605 (set_irg_link)(ir_graph *irg, void *thing) {
606   __set_irg_link(irg, thing);
607 }
608
609 void *
610 (get_irg_link)(const ir_graph *irg) {
611   return __get_irg_link(irg);
612 }
613
614 /* maximum visited flag content of all ir_graph visited fields. */
615 static int max_irg_visited = 0;
616
617 unsigned long
618 (get_irg_visited)(const ir_graph *irg) {
619   return __get_irg_visited(irg);
620 }
621
622 void
623 set_irg_visited (ir_graph *irg, unsigned long visited)
624 {
625   irg->visited = visited;
626   if (irg->visited > max_irg_visited) {
627     max_irg_visited = irg->visited;
628   }
629 }
630
631 void
632 inc_irg_visited (ir_graph *irg)
633 {
634   if (++irg->visited > max_irg_visited) {
635     max_irg_visited = irg->visited;
636   }
637 }
638
639 unsigned long
640 get_max_irg_visited(void)
641 {
642   /*
643   int i;
644   for(i = 0; i < get_irp_n_irgs(); i++)
645   assert(max_irg_visited >= get_irg_visited(get_irp_irg(i)));
646    */
647   return max_irg_visited;
648 }
649
650 void set_max_irg_visited(int val) {
651   max_irg_visited = val;
652 }
653
654 unsigned long
655 inc_max_irg_visited(void)
656 {
657   /*
658   int i;
659   for(i = 0; i < get_irp_n_irgs(); i++)
660   assert(max_irg_visited >= get_irg_visited(get_irp_irg(i)));
661   */
662   max_irg_visited++;
663   return max_irg_visited;
664 }
665
666 unsigned long
667 (get_irg_block_visited)(const ir_graph *irg) {
668   return __get_irg_block_visited(irg);
669 }
670
671 void
672 (set_irg_block_visited)(ir_graph *irg, unsigned long visited) {
673   __set_irg_block_visited(irg, visited);
674 }
675
676 void
677 (inc_irg_block_visited)(ir_graph *irg) {
678   __inc_irg_block_visited(irg);
679 }
680
681 /* is irg a pseudo graph for analysis? */
682 int is_pseudo_ir_graph(ir_graph *irg)
683 {
684   int res = false;
685   entity *ent;
686
687   assert(irg && "nothing here");
688   assert(is_ir_graph(irg) && "no ir_graph given");
689
690   ent = get_irg_entity(irg);
691   if(visibility_external_allocated == get_entity_visibility(ent)
692      && peculiarity_existent == get_entity_peculiarity(ent)) {
693     res = true;
694   }
695   return(res);
696 }