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