Fixes (goetz) f"ur PRECISE_EXC_CONTEXT --flo
[libfirm] / ir / ir / irgraph.c
1 /* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
2 ** All rights reserved.
3 **
4 ** Authors: Martin Trapp, Christian Schaefer
5 **
6 **
7 */
8
9 /* $Id$ */
10
11 #ifdef HAVE_CONFIG_H
12 # include <config.h>
13 #endif
14
15 # include "ircons.h"
16 # include "irgraph_t.h"
17 # include "irprog.h"
18 # include "iropt_t.h"
19 # include "array.h"
20 # include "irgmod.h"
21 # include "mangle.h"
22
23 ir_graph *current_ir_graph;
24
25 #if USE_EXPICIT_PHI_IN_STACK
26 /* really defined in ircons.c */
27 typedef struct Phi_in_stack Phi_in_stack;
28 Phi_in_stack *new_Phi_in_stack();
29 void free_Phi_in_stack(Phi_in_stack *s);
30 #endif
31
32 /* Allocates a list of nodes:
33     - The start block containing a start node and Proj nodes for it's four
34       results (X, M, P, Tuple).
35     - The end block containing an end node. This block is not matured after
36       new_ir_graph as predecessors need to be added to it.
37     - The current block, which is empty and also not matured.
38    Further it allocates several datastructures needed for graph construction
39    and optimization.
40 */
41 ir_graph *
42 new_ir_graph (entity *ent, int n_loc)
43 {
44   ir_graph *res;
45   ir_node *first_block;
46   ir_node *projX;
47
48   res = (ir_graph *) malloc (sizeof (ir_graph));
49   current_ir_graph = res;
50   add_irp_irg(res);          /* remember this graph global. */
51
52   /** Internal information for graph construction either held in the graph or
53   *** initialized for each graph. **/
54 #if PRECISE_EXC_CONTEXT
55   res->n_loc = n_loc + 1 + 1; /* number of local variables that are never
56                                  dereferenced in this graph plus one for
57                                  the store plus one for links to fragile
58                                  operations.  n_loc is not the number of
59                                  parameters to the procedure!  */
60 #else
61   res->n_loc = n_loc + 1;  /* number of local variables that are never
62                               dereferenced in this graph plus one for
63                               the store. This is not the number of parameters
64                               to the procedure!  */
65 #endif
66
67   res->visited = 0;     /* visited flag, for the ir walker */
68   res->block_visited=0; /* visited flag, for the 'block'-walker */
69
70 #if USE_EXPICIT_PHI_IN_STACK
71   res->Phi_in_stack = new_Phi_in_stack();  /* A stack needed for automatic Phi
72                                 generation */
73 #endif
74   res->obst      = (struct obstack *) xmalloc (sizeof (struct obstack));
75   obstack_init (res->obst);
76   res->value_table = new_identities (); /* value table for global value
77                                            numbering for optimizing use in
78                                            iropt.c */
79   res->outs = NULL;
80
81   res->phase_state = phase_building;
82   res->pinned = pinned;
83   res->outs_state = no_outs;
84
85   /** Type inforamtion for the procedure of the graph **/
86   res->ent = ent;
87   set_entity_irg(ent, res);
88
89   /** A type that represents the stack frame.  A class type so that it can
90       contain "inner" methods as in Pascal. **/
91   res->frame_type = new_type_class(mangle(get_entity_ident(ent), id_from_str("frame_tp", 8)));
92
93   /** Nodes needed in every graph **/
94   res->end_block = new_immBlock ();
95   res->end       = new_End ();
96
97   res->start_block = new_immBlock ();
98   res->start   = new_Start ();
99   res->bad     = new_ir_node (res, res->start_block, op_Bad, mode_T, 0, NULL);
100
101   /* Proj results of start node */
102   projX        = new_Proj (res->start, mode_X, pns_initial_exec);
103   set_store (new_Proj (res->start, mode_M, pns_global_store));
104   res->frame   = new_Proj (res->start, mode_p, pns_frame_base);
105   res->globals = new_Proj (res->start, mode_p, pns_globals);
106   res->args    = new_Proj (res->start, mode_T, pns_args);
107
108   add_in_edge(res->start_block, projX);
109   /*
110    * The code generation needs it. leave it in now.
111    * Use of this edge is matter of discussion, unresolved. Also possible:
112    * add_in_edge(res->start_block, res->start_block), but invalid typed.
113    */
114   mature_block (res->current_block);
115
116   /** Make a block to start with **/
117   first_block = new_immBlock ();
118   add_in_edge (first_block, projX);
119
120   return res;
121 }
122
123
124 /* Make a rudimentary ir graph for the constant code.
125    Must look like a correct irg, spare everything else. */
126 ir_graph *new_const_code_irg() {
127   ir_graph *res;
128   ir_node *projX;
129
130   res = (ir_graph *) malloc (sizeof (ir_graph));
131   current_ir_graph = res;
132   res->n_loc = 1;      /* Only the memory. */
133   res->visited = 0;     /* visited flag, for the ir walker */
134   res->block_visited=0; /* visited flag, for the 'block'-walker */
135 #if USE_EXPICIT_PHI_IN_STACK
136   res->Phi_in_stack = NULL;
137 #endif
138   res->obst      = (struct obstack *) xmalloc (sizeof (struct obstack));
139   obstack_init (res->obst);
140   res->pinned = pinned;
141   res->value_table = new_identities (); /* value table for global value
142                                            numbering for optimizing use in
143                                            iropt.c */
144   res->ent = NULL;
145   res->frame_type = NULL;
146   res->start_block = new_immBlock ();
147   res->end_block = new_immBlock ();
148   res->end       = new_End ();
149   mature_block(get_cur_block());
150   res->bad = new_ir_node (res, res->start_block, op_Bad, mode_T, 0, NULL);
151   res->start   = new_Start ();
152   /* Proj results of start node */
153   projX        = new_Proj (res->start, mode_X, pns_initial_exec);
154   set_store (new_Proj (res->start, mode_M, pns_global_store));
155   add_in_edge(res->start_block, projX);
156   mature_block (res->current_block);
157   add_in_edge (new_immBlock (), projX);
158   mature_block(get_cur_block());
159   /* Set the visited flag high enough that the block will never be visited. */
160   set_irn_visited(get_cur_block(), -1);
161   set_Block_block_visited(get_cur_block(), -1);
162   set_Block_block_visited(res->start_block, -1);
163   return res;
164 }
165
166 /* Frees the passed irgraph.
167    Deallocates all nodes in this graph and the ir_graph structure.
168    Sets the field irgraph in the corresponding entity to NULL.
169    Does not remove the irgraph from the list in irprog (requires
170    inefficient search, call remove_irp_irg by hand).
171    Does not free types, entities or modes that are used only by this
172    graph, nor the entity standing for this graph. */
173 void free_ir_graph (ir_graph *irg) {
174   set_entity_irg(irg->ent, NULL);
175   free(irg->obst);
176 #if USE_EXPICIT_PHI_IN_STACK
177   free_Phi_in_stack(irg->Phi_in_stack);
178 #endif
179   free(irg);
180 }
181
182 /* access routines for all ir_graph attributes:
183    templates:
184    {attr type} get_irg_{attribute name} (ir_graph *irg);
185    void set_irg_{attr name} (ir_graph *irg, {attr type} {attr}); */
186
187 ir_node *
188 get_irg_start_block (ir_graph *irg)
189 {
190   return irg->start_block;
191 }
192
193 void
194 set_irg_start_block (ir_graph *irg, ir_node *node)
195 {
196   irg->start_block = node;
197 }
198
199 ir_node *
200 get_irg_start (ir_graph *irg)
201 {
202   return irg->start;
203 }
204
205 void
206 set_irg_start(ir_graph *irg, ir_node *node)
207 {
208   irg->start = node;
209 }
210
211 ir_node *
212 get_irg_end_block (ir_graph *irg)
213 {
214   return irg->end_block;
215 }
216
217 void
218 set_irg_end_block (ir_graph *irg, ir_node *node)
219 {
220   irg->end_block = node;
221 }
222
223 ir_node *
224 get_irg_end (ir_graph *irg)
225 {
226   return irg->end;
227 }
228
229 void
230 set_irg_end (ir_graph *irg, ir_node *node)
231 {
232   irg->end = node;
233 }
234
235 ir_node *
236 get_irg_cstore (ir_graph *irg)
237 {
238   return irg->cstore;
239 }
240
241 void
242 set_irg_cstore (ir_graph *irg, ir_node *node)
243 {
244   irg->cstore = node;
245 }
246
247 ir_node *
248 get_irg_frame (ir_graph *irg)
249 {
250   return irg->frame;
251 }
252
253 void
254 set_irg_frame (ir_graph *irg, ir_node *node)
255 {
256   irg->frame = node;
257 }
258
259 ir_node *
260 get_irg_globals (ir_graph *irg)
261 {
262   return irg->globals;
263 }
264
265 void
266 set_irg_globals (ir_graph *irg, ir_node *node)
267 {
268   irg->globals = node;
269 }
270
271 ir_node *
272 get_irg_args (ir_graph *irg)
273 {
274   return irg->args;
275 }
276
277 void
278 set_irg_args (ir_graph *irg, ir_node *node)
279 {
280   irg->args = node;
281 }
282
283 ir_node *
284 get_irg_bad (ir_graph *irg)
285 {
286   return irg->bad;
287 }
288
289 void
290 set_irg_bad (ir_graph *irg, ir_node *node)
291 {
292   irg->bad = node;
293 }
294
295 ir_node *
296 get_irg_current_block (ir_graph *irg)
297 {
298   return irg->current_block;
299 }
300
301 void
302 set_irg_current_block (ir_graph *irg, ir_node *node)
303 {
304   irg->current_block = node;
305 }
306
307 entity *
308 get_irg_ent (ir_graph *irg)
309 {
310   assert(irg && irg->ent);
311   return irg->ent;
312 }
313
314 void
315 set_irg_ent (ir_graph *irg, entity *ent)
316 {
317   irg->ent = ent;
318 }
319
320 type *
321 get_irg_frame_type (ir_graph *irg)
322 {
323   assert(irg && irg->frame_type);
324   return irg->frame_type;
325 }
326
327 void
328 set_irg_frame_type (ir_graph *irg, type *ftp)
329 {
330   irg->frame_type = ftp;
331 }
332
333 int
334 get_irg_n_loc (ir_graph *irg)
335 {
336 #if PRECISE_EXC_CONTEXT
337   return irg->n_loc - 1 - 1;
338 #else
339   return irg->n_loc - 1;
340 #endif
341 }
342
343 void
344 set_irg_n_loc (ir_graph *irg, int n_loc)
345 {
346   irg->n_loc = n_loc;
347 }
348
349 irg_phase_state get_irg_phase_state (ir_graph *irg) {
350   return irg->phase_state;
351 }
352
353 void set_irg_phase_low(ir_graph *irg) {
354   irg->phase_state = phase_low;
355 }
356
357 op_pinned
358 get_irg_pinned (ir_graph *irg) {
359   return irg->pinned;
360 }
361
362 irg_outs_state get_irg_outs_state(ir_graph *irg) {
363   return irg->outs_state;
364 }
365
366 void set_irg_outs_inconsistent(ir_graph *irg) {
367   irg->outs_state = outs_inconsistent;
368 }
369
370 inline void
371 set_irg_pinned (ir_graph *irg, op_pinned p)
372 {
373   irg->pinned = p;
374 }
375
376 unsigned long
377 get_irg_visited (ir_graph *irg)
378 {
379   return irg->visited;
380 }
381
382 void
383 set_irg_visited (ir_graph *irg, unsigned long visited)
384 {
385   irg->visited = visited;
386 }
387
388 void
389 inc_irg_visited (ir_graph *irg)
390 {
391   irg->visited = irg->visited++;
392 }
393
394 unsigned long
395 get_irg_block_visited (ir_graph *irg)
396 {
397   return irg->block_visited;
398 }
399
400 void
401 set_irg_block_visited (ir_graph *irg, unsigned long visited)
402 {
403   irg->block_visited = visited;
404 }
405
406 void
407 inc_irg_block_visited (ir_graph *irg)
408 {
409   irg->block_visited = irg->block_visited++;
410 }