Asserts in irvrfy that verify the mode of Proj nodes. For Start,
[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
80   /** Type inforamtion for the procedure of the graph **/
81   res->ent = ent;
82   set_entity_irg(ent, res);
83
84   /** A type that represents the stack frame.  A class type so that it can
85       contain "inner" methods as in Pascal. **/
86   res->frame_type = new_type_class(mangle(get_entity_ident(ent), id_from_str("frame_tp", 8)));
87
88   /** Nodes needed in every graph **/
89   res->end_block = new_immBlock ();
90   res->end       = new_End ();
91
92   res->start_block = new_immBlock ();
93   res->start   = new_Start ();
94   res->bad     = new_ir_node (res, res->start_block, op_Bad, mode_T, 0, NULL);
95
96   /* Proj results of start node */
97   projX        = new_Proj (res->start, mode_X, pns_initial_exec);
98   set_store (new_Proj (res->start, mode_M, pns_global_store));
99   res->frame   = new_Proj (res->start, mode_p, pns_frame_base);
100   res->globals = new_Proj (res->start, mode_p, pns_globals);
101   res->args    = new_Proj (res->start, mode_T, pns_args);
102
103   add_in_edge(res->start_block, projX);
104   /*
105    * The code generation needs it. leave it in now.
106    * Use of this edge is matter of discussion, unresolved. Also possible:
107    * add_in_edge(res->start_block, res->start_block), but invalid typed.
108    */
109   mature_block (res->current_block);
110
111   /** Make a block to start with **/
112   first_block = new_immBlock ();
113   add_in_edge (first_block, projX);
114
115   return res;
116 }
117
118
119 /* Make a rudimentary ir graph for the constant code.
120    Must look like a correct irg, spare everything else. */
121 ir_graph *new_const_code_irg() {
122   ir_graph *res;
123   ir_node *projX;
124
125   res = (ir_graph *) malloc (sizeof (ir_graph));
126   current_ir_graph = res;
127   res->n_loc = 1;      /* Only the memory. */
128   res->visited = 0;     /* visited flag, for the ir walker */
129   res->block_visited=0; /* visited flag, for the 'block'-walker */
130 #if USE_EXPICIT_PHI_IN_STACK
131   res->Phi_in_stack = NULL;
132 #endif
133   res->obst      = (struct obstack *) xmalloc (sizeof (struct obstack));
134   obstack_init (res->obst);
135   res->value_table = new_identities (); /* value table for global value
136                                            numbering for optimizing use in
137                                            iropt.c */
138   res->ent = NULL;
139   res->frame_type = NULL;
140   res->start_block = new_immBlock ();
141   res->end_block = new_immBlock ();
142   res->end       = new_End ();
143   mature_block(get_cur_block());
144   res->bad = new_ir_node (res, res->start_block, op_Bad, mode_T, 0, NULL);
145   res->start   = new_Start ();
146   /* Proj results of start node */
147   projX        = new_Proj (res->start, mode_X, pns_initial_exec);
148   set_store (new_Proj (res->start, mode_M, pns_global_store));
149   add_in_edge(res->start_block, projX);
150   mature_block (res->current_block);
151   add_in_edge (new_immBlock (), projX);
152   mature_block(get_cur_block());
153   /* Set the visited flag high enough that the block will never be visited. */
154   set_irn_visited(get_cur_block(), -1);
155   set_Block_block_visited(get_cur_block(), -1);
156   set_Block_block_visited(res->start_block, -1);
157   return res;
158 }
159
160
161
162 /* Frees the passed irgraph.
163    Deallocates all nodes in this graph and the ir_graph structure.
164    Sets the field irgraph in the corresponding entity to NULL.
165    Does not remove the irgraph from the list in irprog (requires
166    inefficient search, call remove_irp_irg by hand).
167    Does not free types, entities or modes that are used only by this
168    graph, nor the entity standing for this graph. */
169 void free_ir_graph (ir_graph *irg) {
170   set_entity_irg(irg->ent, NULL);
171   free(irg->obst);
172 #if USE_EXPICIT_PHI_IN_STACK
173   free_Phi_in_stack(irg->Phi_in_stack);
174 #endif
175   free(irg);
176 }
177
178 /* access routines for all ir_graph attributes:
179    templates:
180    {attr type} get_irg_{attribute name} (ir_graph *irg);
181    void set_irg_{attr name} (ir_graph *irg, {attr type} {attr}); */
182
183 ir_node *
184 get_irg_start_block (ir_graph *irg)
185 {
186   return irg->start_block;
187 }
188
189 void
190 set_irg_start_block (ir_graph *irg, ir_node *node)
191 {
192   irg->start_block = node;
193 }
194
195 ir_node *
196 get_irg_start (ir_graph *irg)
197 {
198   return irg->start;
199 }
200
201 void
202 set_irg_start(ir_graph *irg, ir_node *node)
203 {
204   irg->start = node;
205 }
206
207 ir_node *
208 get_irg_end_block (ir_graph *irg)
209 {
210   return irg->end_block;
211 }
212
213 void
214 set_irg_end_block (ir_graph *irg, ir_node *node)
215 {
216   irg->end_block = node;
217 }
218
219 ir_node *
220 get_irg_end (ir_graph *irg)
221 {
222   return irg->end;
223 }
224
225 void
226 set_irg_end (ir_graph *irg, ir_node *node)
227 {
228   irg->end = node;
229 }
230
231 ir_node *
232 get_irg_cstore (ir_graph *irg)
233 {
234   return irg->cstore;
235 }
236
237 void
238 set_irg_cstore (ir_graph *irg, ir_node *node)
239 {
240   irg->cstore = node;
241 }
242
243 ir_node *
244 get_irg_frame (ir_graph *irg)
245 {
246   return irg->frame;
247 }
248
249 void
250 set_irg_frame (ir_graph *irg, ir_node *node)
251 {
252   irg->frame = node;
253 }
254
255 ir_node *
256 get_irg_globals (ir_graph *irg)
257 {
258   return irg->globals;
259 }
260
261 void
262 set_irg_globals (ir_graph *irg, ir_node *node)
263 {
264   irg->globals = node;
265 }
266
267 ir_node *
268 get_irg_args (ir_graph *irg)
269 {
270   return irg->args;
271 }
272
273 void
274 set_irg_args (ir_graph *irg, ir_node *node)
275 {
276   irg->args = node;
277 }
278
279 ir_node *
280 get_irg_bad (ir_graph *irg)
281 {
282   return irg->bad;
283 }
284
285 void
286 set_irg_bad (ir_graph *irg, ir_node *node)
287 {
288   irg->bad = node;
289 }
290
291 ir_node *
292 get_irg_current_block (ir_graph *irg)
293 {
294   return irg->current_block;
295 }
296
297 void
298 set_irg_current_block (ir_graph *irg, ir_node *node)
299 {
300   irg->current_block = node;
301 }
302
303 entity *
304 get_irg_ent (ir_graph *irg)
305 {
306   assert(irg && irg->ent);
307   return irg->ent;
308 }
309
310 void
311 set_irg_ent (ir_graph *irg, entity *ent)
312 {
313   irg->ent = ent;
314 }
315
316 type *
317 get_irg_frame_type (ir_graph *irg)
318 {
319   assert(irg && irg->frame_type);
320   return irg->frame_type;
321 }
322
323 void
324 set_irg_frame_type (ir_graph *irg, type *ftp)
325 {
326   irg->frame_type = ftp;
327 }
328
329 int
330 get_irg_n_loc (ir_graph *irg)
331 {
332   return irg->n_loc;
333 }
334
335 void
336 set_irg_n_loc (ir_graph *irg, int n_loc)
337 {
338   irg->n_loc = n_loc;
339 }
340
341 unsigned long
342 get_irg_visited (ir_graph *irg)
343 {
344   return irg->visited;
345 }
346
347 void
348 set_irg_visited (ir_graph *irg, unsigned long visited)
349 {
350   irg->visited = visited;
351 }
352
353 void
354 inc_irg_visited (ir_graph *irg)
355 {
356   irg->visited = irg->visited++;
357 }
358
359 unsigned long
360 get_irg_block_visited (ir_graph *irg)
361 {
362   return irg->block_visited;
363 }
364
365 void
366 set_irg_block_visited (ir_graph *irg, unsigned long visited)
367 {
368   irg->block_visited = visited;
369 }
370
371 void
372 inc_irg_block_visited (ir_graph *irg)
373 {
374   irg->block_visited = irg->block_visited++;
375 }