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