- add functions for global (ir_prog) resource management
[libfirm] / ir / ir / irgraph.c
1 /*
2  * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief    Entry point to the representation of procedure code.
23  * @author   Martin Trapp, Christian Schaefer, Goetz Lindenmaier, Michael Beck
24  * @version  $Id$
25  */
26 #include "config.h"
27
28 #ifdef HAVE_STRING_H
29 # include <string.h>
30 #endif
31 #ifdef HAVE_STDDEF_H
32 # include <stddef.h>
33 #endif
34
35 #include "xmalloc.h"
36 #include "ircons_t.h"
37 #include "irgraph_t.h"
38 #include "irprog_t.h"
39 #include "irgraph_t.h"
40 #include "irnode_t.h"
41 #include "iropt_t.h"
42 #include "irflag_t.h"
43 #include "array.h"
44 #include "irgmod.h"
45 #include "irouts.h"
46 #include "irhooks.h"
47 #include "irtools.h"
48 #include "irgwalk.h"
49 #include "irbackedge_t.h"
50 #include "iredges_t.h"
51 #include "type_t.h"
52 #include "irmemory.h"
53
54 #define INITIAL_IDX_IRN_MAP_SIZE 1024
55
56 /**
57  * Indicates, whether additional data can be registered to graphs.
58  * If set to 1, this is not possible anymore.
59  */
60 static int forbid_new_data = 0;
61
62 /**
63  * The amount of additional space for custom data to be allocated upon
64  * creating a new graph.
65  */
66 static size_t additional_graph_data_size = 0;
67
68 ir_graph *current_ir_graph;
69 ir_graph *get_current_ir_graph(void) {
70         return current_ir_graph;
71 }
72
73 void set_current_ir_graph(ir_graph *graph) {
74         current_ir_graph = graph;
75 }
76
77 #ifdef INTERPROCEDURAL_VIEW
78 int firm_interprocedural_view = 0;
79
80 int (get_interprocedural_view)(void) {
81         return _get_interprocedural_view();
82 }
83
84 void (set_interprocedural_view)(int state) {
85         firm_interprocedural_view = state;
86
87         /* set function vectors for faster access */
88         if (state) {
89                 _get_irn_arity = _get_irn_inter_arity;
90                 _get_irn_n     = _get_irn_inter_n;
91         }
92         else {
93                 _get_irn_arity = _get_irn_intra_arity;
94                 _get_irn_n     = _get_irn_intra_n;
95         }
96 }
97 #endif
98
99 /** contains the suffix for frame type names */
100 static ident *frame_type_suffix = NULL;
101
102 /* initialize the IR graph module */
103 void firm_init_irgraph(void) {
104         frame_type_suffix = new_id_from_str(FRAME_TP_SUFFIX);
105         forbid_new_data   = 1;
106 }
107
108 /**
109  * Allocate a new IR graph.
110  * This function respects the registered graph data. The only reason for
111  * this function is, that there are two locations, where graphs are
112  * allocated (new_r_ir_graph, new_const_code_irg).
113  * @return Memory for a new graph.
114  */
115 static ir_graph *alloc_graph(void) {
116         ir_graph *res;
117         size_t   size = sizeof(ir_graph) + additional_graph_data_size;
118         char     *ptr = xmalloc(size);
119         memset(ptr, 0, size);
120
121         res = (ir_graph *)(ptr + additional_graph_data_size);
122         res->kind = k_ir_graph;
123
124         /* initialize the idx->node map. */
125         res->idx_irn_map = NEW_ARR_F(ir_node *, INITIAL_IDX_IRN_MAP_SIZE);
126         memset(res->idx_irn_map, 0, INITIAL_IDX_IRN_MAP_SIZE * sizeof(res->idx_irn_map[0]));
127
128         return res;
129 }
130
131 /**
132  * Frees an allocated IR graph
133  */
134 static void free_graph(ir_graph *irg) {
135         char *ptr = (char *)irg;
136         int  i;
137
138         for (i = 0; i < EDGE_KIND_LAST; ++i)
139                 edges_deactivate_kind(irg, i);
140         DEL_ARR_F(irg->idx_irn_map);
141         free(ptr - additional_graph_data_size);
142 }
143
144 #if USE_EXPLICIT_PHI_IN_STACK
145 /* really defined in ircons.c */
146 typedef struct Phi_in_stack Phi_in_stack;
147 Phi_in_stack *new_Phi_in_stack();
148 void free_Phi_in_stack(Phi_in_stack *s);
149 #endif
150
151 /**
152  * Set the number of locals for a given graph.
153  *
154  * @param irg    the graph
155  * @param n_loc  number of locals
156  */
157 void irg_set_nloc(ir_graph *res, int n_loc) {
158         assert(res->phase_state == phase_building);
159
160         if (get_opt_precise_exc_context()) {
161                 res->n_loc = n_loc + 1 + 1; /* number of local variables that are never
162                                                dereferenced in this graph plus one for
163                                                the store plus one for links to fragile
164                                                operations.  n_loc is not the number of
165                                                parameters to the procedure!  */
166         } else {
167                 res->n_loc = n_loc + 1;     /* number of local variables that are never
168                                                dereferenced in this graph plus one for
169                                                the store. This is not the number of parameters
170                                                to the procedure!  */
171         }
172         if (res->loc_descriptions) {
173                 xfree(res->loc_descriptions);
174                 res->loc_descriptions = NULL;
175         }
176 }
177
178 /* Allocates a list of nodes:
179     - The start block containing a start node and Proj nodes for it's four
180       results (X, M, P, Tuple).
181     - The end block containing an end node. This block is not matured after
182       new_ir_graph as predecessors need to be added to it.
183     - The current block, which is empty and also not matured.
184    Further it allocates several datastructures needed for graph construction
185    and optimization.
186 */
187 ir_graph *new_r_ir_graph(ir_entity *ent, int n_loc) {
188         ir_graph *res;
189         ir_node  *first_block;
190         ir_node  *end, *start, *start_block, *initial_mem, *projX;
191
192         res = alloc_graph();
193
194         /* inform statistics here, as blocks will be already build on this graph */
195         hook_new_graph(res, ent);
196
197         current_ir_graph = res;
198
199         /*-- initialized for each graph. --*/
200         res->kind = k_ir_graph;
201         res->obst = XMALLOC(struct obstack);
202         obstack_init(res->obst);
203
204         res->phase_state = phase_building;
205         irg_set_nloc(res, n_loc);
206
207         /* descriptions will be allocated on demand */
208         res->loc_descriptions = NULL;
209
210         res->visited       = 0; /* visited flag, for the ir walker */
211         res->block_visited = 0; /* visited flag, for the 'block'-walker */
212
213 #if USE_EXPLICIT_PHI_IN_STACK
214         res->Phi_in_stack = new_Phi_in_stack();  /* A stack needed for automatic Phi
215                                                     generation */
216 #endif
217         res->extbb_obst = NULL;
218
219         res->last_node_idx = 0;
220
221         res->value_table = new_identities (); /* value table for global value
222                                                  numbering for optimizing use in iropt.c */
223         res->outs = NULL;
224
225         res->inline_property       = irg_inline_any;
226         res->additional_properties = mtp_property_inherited;  /* inherited from type */
227
228         res->irg_pinned_state    = op_pin_state_pinned;
229         res->outs_state          = outs_none;
230         res->dom_state           = dom_none;
231         res->pdom_state          = dom_none;
232         res->typeinfo_state      = ir_typeinfo_none;
233         set_irp_typeinfo_inconsistent();           /* there is a new graph with typeinfo_none. */
234         res->callee_info_state   = irg_callee_info_none;
235         res->loopinfo_state      = loopinfo_none;
236         res->class_cast_state    = ir_class_casts_transitive;
237         res->extblk_state        = ir_extblk_info_none;
238         res->execfreq_state      = exec_freq_none;
239         res->fp_model            = fp_model_precise;
240         res->entity_usage_state  = ir_entity_usage_not_computed;
241         res->mem_disambig_opt    = aa_opt_inherited;
242
243         /*-- Type information for the procedure of the graph --*/
244         res->ent = ent;
245         set_entity_irg(ent, res);
246
247         /*--  a class type so that it can contain "inner" methods as in Pascal. --*/
248         res->frame_type = new_type_frame(mangle(get_entity_ident(ent), frame_type_suffix));
249
250         /* the Anchor node must be created first */
251         res->anchor = new_Anchor(res);
252
253         /*-- Nodes needed in every graph --*/
254         set_irg_end_block (res, new_immBlock());
255         end               = new_End();
256         set_irg_end       (res, end);
257         set_irg_end_reg   (res, end);
258         set_irg_end_except(res, end);
259
260         start_block = new_immBlock();
261         set_irg_start_block(res, start_block);
262         set_irg_bad        (res, new_ir_node(NULL, res, start_block, op_Bad, mode_T, 0, NULL));
263         set_irg_no_mem     (res, new_ir_node(NULL, res, start_block, op_NoMem, mode_M, 0, NULL));
264         start = new_Start();
265         set_irg_start      (res, start);
266
267         /* Proj results of start node */
268         projX                   = new_Proj(start, mode_X, pn_Start_X_initial_exec);
269         set_irg_initial_exec    (res, projX);
270         set_irg_frame           (res, new_Proj(start, mode_P_data, pn_Start_P_frame_base));
271         set_irg_tls             (res, new_Proj(start, mode_P_data, pn_Start_P_tls));
272         set_irg_args            (res, new_Proj(start, mode_T,      pn_Start_T_args));
273         set_irg_value_param_base(res, new_Proj(start, mode_P_data, pn_Start_P_value_arg_base));
274         initial_mem             = new_Proj(start, mode_M, pn_Start_M);
275         set_irg_initial_mem(res, initial_mem);
276
277         add_immBlock_pred(start_block, projX);
278         set_store(initial_mem);
279
280         res->index       = get_irp_new_irg_idx();
281 #ifdef DEBUG_libfirm
282         res->graph_nr    = get_irp_new_node_nr();
283 #endif
284
285         /*
286          * The code generation needs it. leave it in now.
287          * Use of this edge is matter of discussion, unresolved. Also possible:
288          * add_immBlock_pred(res->start_block, res->start_block), but invalid typed.
289          */
290         mature_immBlock(res->current_block);
291
292         /*-- Make a block to start with --*/
293         first_block = new_immBlock();
294         add_immBlock_pred(first_block, projX);
295
296         res->method_execution_frequency = -1.0;
297         res->estimated_node_count       = 0;
298
299         return res;
300 }
301
302 ir_graph *new_ir_graph(ir_entity *ent, int n_loc) {
303         ir_graph *res = new_r_ir_graph(ent, n_loc);
304         add_irp_irg(res);          /* remember this graph global. */
305         return res;
306 }
307
308 /* Make a rudimentary IR graph for the constant code.
309    Must look like a correct irg, spare everything else. */
310 ir_graph *new_const_code_irg(void) {
311         ir_graph *res;
312         ir_node  *end, *start_block, *start, *projX;
313
314         res = alloc_graph();
315
316         /* inform statistics here, as blocks will be already build on this graph */
317         hook_new_graph(res, NULL);
318
319         current_ir_graph = res;
320         res->n_loc = 1;         /* Only the memory. */
321         res->visited = 0;       /* visited flag, for the ir walker */
322         res->block_visited = 0; /* visited flag, for the 'block'-walker */
323 #if USE_EXPLICIT_PHI_IN_STACK
324         res->Phi_in_stack = NULL;
325 #endif
326         res->obst       = XMALLOC(struct obstack);
327         obstack_init (res->obst);
328         res->extbb_obst = NULL;
329
330         res->last_node_idx = 0;
331
332         res->phase_state      = phase_building;
333         res->irg_pinned_state = op_pin_state_pinned;
334         res->extblk_state     = ir_extblk_info_none;
335         res->fp_model         = fp_model_precise;
336
337         res->value_table = new_identities(); /* value table for global value
338                                            numbering for optimizing use in
339                                            iropt.c */
340         res->ent = NULL;
341         res->frame_type  = NULL;
342
343         /* the Anchor node must be created first */
344         res->anchor = new_Anchor(res);
345
346         /* -- The end block -- */
347         set_irg_end_block (res, new_immBlock());
348         end = new_End();
349         set_irg_end       (res, end);
350         set_irg_end_reg   (res, end);
351         set_irg_end_except(res, end);
352         mature_immBlock(get_cur_block());  /* mature the end block */
353
354         /* -- The start block -- */
355         start_block        = new_immBlock();
356         set_irg_start_block(res, start_block);
357         set_irg_bad        (res, new_ir_node (NULL, res, start_block, op_Bad, mode_T, 0, NULL));
358         set_irg_no_mem     (res, new_ir_node (NULL, res, start_block, op_NoMem, mode_M, 0, NULL));
359         start              = new_Start();
360         set_irg_start      (res, start);
361
362         /* Proj results of start node */
363         set_irg_initial_mem(res, new_Proj(start, mode_M, pn_Start_M));
364         projX = new_Proj(start, mode_X, pn_Start_X_initial_exec);
365         add_immBlock_pred(start_block, projX);
366         mature_immBlock  (start_block);  /* mature the start block */
367
368         add_immBlock_pred(new_immBlock(), projX);
369         mature_immBlock  (get_cur_block());   /* mature the 'body' block for expressions */
370
371         /* Set the visited flag high enough that the blocks will never be visited. */
372         set_irn_visited(get_cur_block(), -1);
373         set_Block_block_visited(get_cur_block(), -1);
374         set_Block_block_visited(start_block, -1);
375         set_irn_visited(start_block, -1);
376         set_irn_visited(get_irg_bad(res), -1);
377         set_irn_visited(get_irg_no_mem(res), -1);
378
379         res->phase_state = phase_high;
380
381         return res;
382 }
383
384 /**
385  * Pre-Walker: Copies blocks and nodes from the original method graph
386  * to the copied graph.
387  *
388  * @param n    A node from the original method graph.
389  * @param env  The copied graph.
390  */
391 static void copy_all_nodes(ir_node *n, void *env) {
392         ir_graph *irg = env;
393         ir_op    *op  = get_irn_op(n);
394         ir_node  *nn;
395
396         nn = new_ir_node(get_irn_dbg_info(n),
397                          irg,
398                          NULL,            /* no block yet, will be set later */
399                          op,
400                          get_irn_mode(n),
401                          get_irn_arity(n),
402                          get_irn_in(n) + 1);
403
404
405         /* Copy the attributes.  These might point to additional data.  If this
406            was allocated on the old obstack the pointers now are dangling.  This
407            frees e.g. the memory of the graph_arr allocated in new_immBlock. */
408         copy_node_attr(n, nn);
409         new_backedge_info(nn);
410         set_irn_link(n, nn);
411
412         /* fix the irg for blocks */
413         if (is_Block(nn))
414                 nn->attr.block.irg = irg;
415
416         /* fix access to entities on the stack frame */
417         if (is_Sel(nn)) {
418                 ir_entity *ent = get_Sel_entity(nn);
419                 ir_type   *tp = get_entity_owner(ent);
420
421                 if (is_frame_type(tp)) {
422                         /* replace by the copied entity */
423                         ent = get_entity_link(ent);
424
425                         assert(is_entity(ent));
426                         assert(get_entity_owner(ent) == get_irg_frame_type(irg));
427                         set_Sel_entity(nn, ent);
428                 }
429         }
430 }
431
432 /**
433  * Post-walker: Set the predecessors of the copied nodes.
434  * The copied nodes are set as link of their original nodes. The links of
435  * "irn" predecessors are the predecessors of copied node.
436  */
437 static void set_all_preds(ir_node *irn, void *env) {
438         int      i;
439         ir_node  *nn, *pred;
440         (void) env;
441
442         nn = get_irn_link(irn);
443
444         if (is_Block(irn)) {
445                 ir_node *mbh = get_Block_MacroBlock(irn);
446                 set_Block_MacroBlock(nn, get_irn_link(mbh));
447                 for (i = get_Block_n_cfgpreds(irn) - 1; i >= 0; i--) {
448                         pred = get_Block_cfgpred(irn, i);
449                         set_Block_cfgpred(nn, i, get_irn_link(pred));
450                 }
451         } else {
452                 /* First we set the block our copy if it is not a block.*/
453                 set_nodes_block(nn, get_irn_link(get_nodes_block(irn)));
454                 for (i = get_irn_arity(irn) - 1; i >= 0; i--) {
455                         pred = get_irn_n(irn, i);
456                         set_irn_n(nn, i, get_irn_link(pred));
457                 }
458         }
459 }
460
461 #define NN(irn)  get_irn_link(irn)
462
463 /*
464  * Create a new graph that is a copy of a given one.
465  */
466 ir_graph *create_irg_copy(ir_graph *irg) {
467         ir_graph *res;
468
469         res = alloc_graph();
470
471         res->n_loc = 0;
472         res->visited = 0;       /* visited flag, for the ir walker */
473         res->block_visited = 0; /* visited flag, for the 'block'-walker */
474 #if USE_EXPLICIT_PHI_IN_STACK
475         res->Phi_in_stack = NULL;
476 #endif
477         res->obst       = XMALLOC(struct obstack);
478         obstack_init(res->obst);
479         res->extbb_obst = NULL;
480
481         res->last_node_idx = 0;
482
483         res->phase_state      = irg->phase_state;
484         res->irg_pinned_state = irg->irg_pinned_state;
485         res->extblk_state     = ir_extblk_info_none;
486         res->fp_model         = irg->fp_model;
487
488         res->value_table = new_identities();
489
490         /* clone the frame type here for safety */
491         res->frame_type  = clone_frame_type(irg->frame_type);
492
493         res->phase_state = irg->phase_state;
494
495         ir_reserve_resources(irg, IR_RESOURCE_IRN_LINK);
496
497         /* copy all nodes from the graph irg to the new graph res */
498         irg_walk_anchors(irg, copy_all_nodes, set_all_preds, res);
499
500         /* copy the Anchor node */
501         res->anchor = NN(irg->anchor);
502
503         /* -- The end block -- */
504         set_irg_end_block (res, NN(get_irg_end_block(irg)));
505         set_irg_end       (res, NN(get_irg_end(irg)));
506         set_irg_end_reg   (res, NN(get_irg_end_reg(irg)));
507         set_irg_end_except(res, NN(get_irg_end_except(irg)));
508
509         /* -- The start block -- */
510         set_irg_start_block(res, NN(get_irg_start_block(irg)));
511         set_irg_bad        (res, NN(get_irg_bad(irg)));
512         set_irg_no_mem     (res, NN(get_irg_no_mem(irg)));
513         set_irg_start      (res, NN(get_irg_start(irg)));
514
515         /* Proj results of start node */
516         set_irg_initial_mem(res, NN(get_irg_initial_mem(irg)));
517
518         /* Copy the node count estimation. Would be strange if this
519            is different from the original one. */
520         res->estimated_node_count = irg->estimated_node_count;
521
522         ir_free_resources(irg, IR_RESOURCE_IRN_LINK);
523
524         return res;
525 }
526 #undef NN
527
528
529 /* Frees the passed irgraph.
530    Deallocates all nodes in this graph and the ir_graph structure.
531    Sets the field irgraph in the corresponding entity to NULL.
532    Does not remove the irgraph from the list in irprog (requires
533    inefficient search, call remove_irp_irg by hand).
534    Does not free types, entities or modes that are used only by this
535    graph, nor the entity standing for this graph. */
536 void free_ir_graph(ir_graph *irg) {
537         assert(is_ir_graph(irg));
538
539         edges_deactivate(irg);
540
541         hook_free_graph(irg);
542         if (irg->outs_state != outs_none)
543                 free_irg_outs(irg);
544         if (irg->frame_type)
545                 free_type(irg->frame_type);
546         if (irg->value_table)
547                 del_identities(irg->value_table);
548         if (irg->ent) {
549                 ir_peculiarity pec = get_entity_peculiarity (irg->ent);
550                 set_entity_peculiarity (irg->ent, peculiarity_description);
551                 set_entity_irg(irg->ent, NULL);  /* not set in const code irg */
552                 set_entity_peculiarity (irg->ent, pec);
553         }
554
555         free_End(get_irg_end(irg));
556         obstack_free(irg->obst,NULL);
557         free(irg->obst);
558 #if USE_EXPLICIT_PHI_IN_STACK
559         free_Phi_in_stack(irg->Phi_in_stack);
560 #endif
561         if (irg->loc_descriptions)
562                 free(irg->loc_descriptions);
563         irg->kind = k_BAD;
564         free_graph(irg);
565 }
566
567 /* access routines for all ir_graph attributes:
568    templates:
569    {attr type} get_irg_{attribute name} (ir_graph *irg);
570    void set_irg_{attr name} (ir_graph *irg, {attr type} {attr}); */
571
572 int
573 (is_ir_graph)(const void *thing) {
574         return _is_ir_graph(thing);
575 }
576
577 #ifdef DEBUG_libfirm
578 /* Outputs a unique number for this node */
579 long get_irg_graph_nr(const ir_graph *irg) {
580         return irg->graph_nr;
581 }
582 #else
583 long get_irg_graph_nr(const ir_graph *irg) {
584         return PTR_TO_INT(irg);
585 }
586 #endif
587
588 int get_irg_idx(const ir_graph *irg) {
589         return irg->index;
590 }
591
592 ir_node *
593 (get_irg_start_block)(const ir_graph *irg) {
594         return _get_irg_start_block(irg);
595 }
596
597 void
598 (set_irg_start_block)(ir_graph *irg, ir_node *node) {
599         _set_irg_start_block(irg, node);
600 }
601
602 ir_node *
603 (get_irg_start)(const ir_graph *irg) {
604         return _get_irg_start(irg);
605 }
606
607 void
608 (set_irg_start)(ir_graph *irg, ir_node *node) {
609         _set_irg_start(irg, node);
610 }
611
612 ir_node *
613 (get_irg_end_block)(const ir_graph *irg) {
614         return _get_irg_end_block(irg);
615 }
616
617 void
618 (set_irg_end_block)(ir_graph *irg, ir_node *node) {
619   _set_irg_end_block(irg, node);
620 }
621
622 ir_node *
623 (get_irg_end)(const ir_graph *irg) {
624         return _get_irg_end(irg);
625 }
626
627 void
628 (set_irg_end)(ir_graph *irg, ir_node *node) {
629         _set_irg_end(irg, node);
630 }
631
632 ir_node *
633 (get_irg_end_reg)(const ir_graph *irg) {
634         return _get_irg_end_reg(irg);
635 }
636
637 void
638 (set_irg_end_reg)(ir_graph *irg, ir_node *node) {
639         _set_irg_end_reg(irg, node);
640 }
641
642 ir_node *
643 (get_irg_end_except)(const ir_graph *irg) {
644         return _get_irg_end_except(irg);
645 }
646
647 void
648 (set_irg_end_except)(ir_graph *irg, ir_node *node) {
649         assert(get_irn_op(node) == op_EndExcept || is_End(node));
650         _set_irg_end_except(irg, node);
651 }
652
653 ir_node *
654 (get_irg_initial_exec)(const ir_graph *irg) {
655         return _get_irg_initial_exec(irg);
656 }
657
658 void
659 (set_irg_initial_exec)(ir_graph *irg, ir_node *node) {
660         _set_irg_initial_exec(irg, node);
661 }
662
663 ir_node *
664 (get_irg_frame)(const ir_graph *irg) {
665         return _get_irg_frame(irg);
666 }
667
668 void
669 (set_irg_frame)(ir_graph *irg, ir_node *node) {
670         _set_irg_frame(irg, node);
671 }
672
673 ir_node *
674 (get_irg_tls)(const ir_graph *irg) {
675         return _get_irg_tls(irg);
676 }
677
678 void
679 (set_irg_tls)(ir_graph *irg, ir_node *node) {
680         _set_irg_tls(irg, node);
681 }
682
683 ir_node *
684 (get_irg_initial_mem)(const ir_graph *irg) {
685         return _get_irg_initial_mem(irg);
686 }
687
688 void
689 (set_irg_initial_mem)(ir_graph *irg, ir_node *node) {
690         _set_irg_initial_mem(irg, node);
691 }
692
693 ir_node *
694 (get_irg_args)(const ir_graph *irg) {
695         return _get_irg_args(irg);
696 }
697
698 void
699 (set_irg_args)(ir_graph *irg, ir_node *node) {
700         _set_irg_args(irg, node);
701 }
702
703 ir_node *
704 (get_irg_value_param_base)(const ir_graph *irg) {
705         return _get_irg_value_param_base(irg);
706 }
707
708 void
709 (set_irg_value_param_base)(ir_graph *irg, ir_node *node) {
710         _set_irg_value_param_base(irg, node);
711 }
712
713 ir_node *
714 (get_irg_bad)(const ir_graph *irg) {
715         return _get_irg_bad(irg);
716 }
717
718 void
719 (set_irg_bad)(ir_graph *irg, ir_node *node) {
720         _set_irg_bad(irg, node);
721 }
722
723 ir_node *
724 (get_irg_no_mem)(const ir_graph *irg) {
725         return _get_irg_no_mem(irg);
726 }
727
728 void
729 (set_irg_no_mem)(ir_graph *irg, ir_node *node) {
730         _set_irg_no_mem(irg, node);
731 }
732
733 ir_node *
734 (get_irg_current_block)(const ir_graph *irg) {
735         return _get_irg_current_block(irg);
736 }
737
738 void
739 (set_irg_current_block)(ir_graph *irg, ir_node *node) {
740         _set_irg_current_block(irg, node);
741 }
742
743 ir_entity *
744 (get_irg_entity)(const ir_graph *irg) {
745         return _get_irg_entity(irg);
746 }
747
748 void
749 (set_irg_entity)(ir_graph *irg, ir_entity *ent) {
750         _set_irg_entity(irg, ent);
751 }
752
753 ir_type *
754 (get_irg_frame_type)(ir_graph *irg) {
755         return _get_irg_frame_type(irg);
756 }
757
758 void
759 (set_irg_frame_type)(ir_graph *irg, ir_type *ftp) {
760         _set_irg_frame_type(irg, ftp);
761 }
762
763 int
764 get_irg_n_locs(ir_graph *irg) {
765         if (get_opt_precise_exc_context())
766                 return irg->n_loc - 1 - 1;
767         else
768                 return irg->n_loc - 1;
769 }
770
771 void
772 set_irg_n_loc(ir_graph *irg, int n_loc) {
773         if (get_opt_precise_exc_context())
774                 irg->n_loc = n_loc + 1 + 1;
775         else
776                 irg->n_loc = n_loc + 1;
777 }
778
779
780
781 /* Returns the obstack associated with the graph. */
782 struct obstack *
783 (get_irg_obstack)(const ir_graph *irg) {
784         return _get_irg_obstack(irg);
785 }
786
787 /*
788  * Returns true if the node n is allocated on the storage of graph irg.
789  *
790  * Implementation is GLIBC specific as is uses the internal _obstack_chunk implementation.
791  */
792 int node_is_in_irgs_storage(ir_graph *irg, ir_node *n) {
793         struct _obstack_chunk *p;
794
795         /*
796          * checks weather the ir_node pointer is on the obstack.
797          * A more sophisticated check would test the "whole" ir_node
798          */
799         for (p = irg->obst->chunk; p; p = p->prev) {
800                 if (((char *)p->contents <= (char *)n) && ((char *)n < (char *)p->limit))
801                         return 1;
802         }
803
804         return 0;
805 }
806
807 irg_phase_state
808 (get_irg_phase_state)(const ir_graph *irg) {
809         return _get_irg_phase_state(irg);
810 }
811
812 void
813 (set_irg_phase_state)(ir_graph *irg, irg_phase_state state) {
814         _set_irg_phase_state(irg, state);
815 }
816
817 op_pin_state
818 (get_irg_pinned)(const ir_graph *irg) {
819         return _get_irg_pinned(irg);
820 }
821
822 irg_outs_state
823 (get_irg_outs_state)(const ir_graph *irg) {
824         return _get_irg_outs_state(irg);
825 }
826
827 void
828 (set_irg_outs_inconsistent)(ir_graph *irg) {
829         _set_irg_outs_inconsistent(irg);
830 }
831
832 irg_extblk_state
833 (get_irg_extblk_state)(const ir_graph *irg) {
834         return _get_irg_extblk_state(irg);
835 }
836
837 void
838 (set_irg_extblk_inconsistent)(ir_graph *irg) {
839         _set_irg_extblk_inconsistent(irg);
840 }
841
842 irg_dom_state
843 (get_irg_dom_state)(const ir_graph *irg) {
844         return _get_irg_dom_state(irg);
845 }
846
847 irg_dom_state
848 (get_irg_postdom_state)(const ir_graph *irg) {
849         return _get_irg_postdom_state(irg);
850 }
851
852 void
853 (set_irg_doms_inconsistent)(ir_graph *irg) {
854         _set_irg_doms_inconsistent(irg);
855 }
856
857 irg_loopinfo_state
858 (get_irg_loopinfo_state)(const ir_graph *irg) {
859         return _get_irg_loopinfo_state(irg);
860 }
861
862 void
863 (set_irg_loopinfo_state)(ir_graph *irg, irg_loopinfo_state s) {
864         _set_irg_loopinfo_state(irg, s);
865 }
866
867 void
868 (set_irg_loopinfo_inconsistent)(ir_graph *irg) {
869         _set_irg_loopinfo_inconsistent(irg);
870 }
871
872 void set_irp_loopinfo_inconsistent(void) {
873         int i;
874         for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
875                 set_irg_loopinfo_inconsistent(get_irp_irg(i));
876         }
877 }
878
879
880
881 void
882 (set_irg_pinned)(ir_graph *irg, op_pin_state p) {
883         _set_irg_pinned(irg, p);
884 }
885
886 irg_callee_info_state
887 (get_irg_callee_info_state)(const ir_graph *irg) {
888         return _get_irg_callee_info_state(irg);
889 }
890
891 void
892 (set_irg_callee_info_state)(ir_graph *irg, irg_callee_info_state s) {
893         _set_irg_callee_info_state(irg, s);
894 }
895
896 irg_inline_property
897 (get_irg_inline_property)(const ir_graph *irg) {
898         return _get_irg_inline_property(irg);
899 }
900
901 void
902 (set_irg_inline_property)(ir_graph *irg, irg_inline_property s) {
903         _set_irg_inline_property(irg, s);
904 }
905
906 unsigned
907 (get_irg_additional_properties)(const ir_graph *irg) {
908         return _get_irg_additional_properties(irg);
909 }
910
911 void
912 (set_irg_additional_properties)(ir_graph *irg, unsigned property_mask) {
913         _set_irg_additional_properties(irg, property_mask);
914 }
915
916 void
917 (set_irg_additional_property)(ir_graph *irg, mtp_additional_property flag) {
918         _set_irg_additional_property(irg, flag);
919 }
920
921 void
922 (set_irg_link)(ir_graph *irg, void *thing) {
923         _set_irg_link(irg, thing);
924 }
925
926 void *
927 (get_irg_link)(const ir_graph *irg) {
928         return _get_irg_link(irg);
929 }
930
931 ir_visited_t
932 (get_irg_visited)(const ir_graph *irg) {
933         return _get_irg_visited(irg);
934 }
935
936 #ifdef INTERPROCEDURAL_VIEW
937 /** maximum visited flag content of all ir_graph visited fields. */
938 static ir_visited_t max_irg_visited = 0;
939 #endif /* INTERPROCEDURAL_VIEW */
940
941 void
942 set_irg_visited(ir_graph *irg, ir_visited_t visited) {
943         irg->visited = visited;
944 #ifdef INTERPROCEDURAL_VIEW
945         if (irg->visited > max_irg_visited) {
946                 max_irg_visited = irg->visited;
947         }
948 #endif /* INTERPROCEDURAL_VIEW */
949 }
950
951 void
952 inc_irg_visited(ir_graph *irg) {
953 #ifdef INTERPROCEDURAL_VIEW
954         if (++irg->visited > max_irg_visited) {
955                 max_irg_visited = irg->visited;
956         }
957 #else
958         ++irg->visited;
959 #endif /* INTERPROCEDURAL_VIEW */
960 }
961
962 #ifdef INTERPROCEDURAL_VIEW
963 ir_visited_t
964 get_max_irg_visited(void) {
965 #ifndef NDEBUG
966         int i;
967         for(i = 0; i < get_irp_n_irgs(); i++)
968                 assert(max_irg_visited >= get_irg_visited(get_irp_irg(i)));
969 #endif
970         return max_irg_visited;
971 }
972
973 void set_max_irg_visited(int val) {
974         max_irg_visited = val;
975 }
976
977 ir_visited_t
978 inc_max_irg_visited(void) {
979 #ifndef NDEBUG
980         int i;
981         for(i = 0; i < get_irp_n_irgs(); i++)
982                 assert(max_irg_visited >= get_irg_visited(get_irp_irg(i)));
983 #endif
984         return ++max_irg_visited;
985 }
986 #endif /* INTERPROCEDURAL_VIEW */
987
988 ir_visited_t
989 (get_irg_block_visited)(const ir_graph *irg) {
990         return _get_irg_block_visited(irg);
991 }
992
993 void
994 (set_irg_block_visited)(ir_graph *irg, ir_visited_t visited) {
995         _set_irg_block_visited(irg, visited);
996 }
997
998 void
999 (inc_irg_block_visited)(ir_graph *irg) {
1000   _inc_irg_block_visited(irg);
1001 }
1002
1003 /* Return the floating point model of this graph. */
1004 unsigned (get_irg_fp_model)(const ir_graph *irg) {
1005         return _get_irg_fp_model(irg);
1006 }
1007
1008 /* Sets the floating point model for this graph. */
1009 void set_irg_fp_model(ir_graph *irg, unsigned model) {
1010         irg->fp_model = model;
1011 }
1012
1013 /**
1014  * walker Start->End: places Proj nodes into the same block
1015  * as it's predecessors
1016  *
1017  * @param n    the node
1018  * @param env  ignored
1019  */
1020 static void normalize_proj_walker(ir_node *n, void *env) {
1021         (void) env;
1022         if (is_Proj(n)) {
1023                 ir_node *pred  = get_Proj_pred(n);
1024                 ir_node *block = get_nodes_block(pred);
1025
1026                 set_nodes_block(n, block);
1027         }
1028 }
1029
1030 /* move Proj nodes into the same block as its predecessors */
1031 void normalize_proj_nodes(ir_graph *irg) {
1032         irg_walk_graph(irg, NULL, normalize_proj_walker, NULL);
1033         set_irg_outs_inconsistent(irg);
1034 }
1035
1036 /* set a description for local value n */
1037 void set_irg_loc_description(ir_graph *irg, int n, void *description) {
1038         assert(0 <= n && n < irg->n_loc);
1039
1040         if (! irg->loc_descriptions)
1041                 irg->loc_descriptions = XMALLOCNZ(void*, irg->n_loc);
1042
1043         irg->loc_descriptions[n] = description;
1044 }
1045
1046 /* get the description for local value n */
1047 void *get_irg_loc_description(ir_graph *irg, int n) {
1048         assert(0 <= n && n < irg->n_loc);
1049         return irg->loc_descriptions ? irg->loc_descriptions[n] : NULL;
1050 }
1051
1052 #ifndef NDEBUG
1053 void ir_reserve_resources(ir_graph *irg, ir_resources_t resources) {
1054         assert((irg->reserved_resources & resources) == 0);
1055         irg->reserved_resources |= resources;
1056 }
1057
1058 void ir_free_resources(ir_graph *irg, ir_resources_t resources) {
1059         assert((irg->reserved_resources & resources) == resources);
1060         irg->reserved_resources &= ~resources;
1061 }
1062
1063 ir_resources_t ir_resources_reserved(const ir_graph *irg) {
1064         return irg->reserved_resources;
1065 }
1066 #endif /* NDEBUG */
1067
1068 /* Returns a estimated node count of the irg. */
1069 unsigned (get_irg_estimated_node_cnt)(const ir_graph *irg) {
1070         return _get_irg_estimated_node_cnt(irg);
1071 }
1072
1073 /* Returns the last irn index for this graph. */
1074 unsigned get_irg_last_idx(const ir_graph *irg) {
1075         return irg->last_node_idx;
1076 }
1077
1078 /* register additional space in an IR graph */
1079 size_t register_additional_graph_data(size_t size) {
1080         assert(!forbid_new_data && "Too late to register additional node data");
1081
1082         if (forbid_new_data)
1083                 return 0;
1084
1085         return additional_graph_data_size += size;
1086 }