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