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