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