avoid unnecessary macros in public headers
[libfirm] / ir / ir / ircgcons.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   Construction and removal of interprocedural representation
23  *          (explicit interprocedural dependencies).
24  * @author  Hubert Schmid
25  * @date    09.06.2002
26  * @version $Id$
27  */
28 #include "config.h"
29
30 #ifdef INTERPROCEDURAL_VIEW
31
32 #include <string.h>
33 #include <stdbool.h>
34 #include "ircgcons.h"
35
36 #include "array.h"
37 #include "irprog.h"
38 #include "irnode_t.h"
39 #include "irprog_t.h"
40 #include "ircons_t.h"
41 #include "irgmod.h"
42 #include "irgwalk.h"
43 #include "irflag_t.h"
44 #include "irtools.h"
45
46 /* Return the current state of the interprocedural view. */
47 ip_view_state get_irp_ip_view_state(void)
48 {
49   return irp->ip_view;
50 }
51
52 /* Set the current state of the interprocedural view. */
53 static void set_irp_ip_view(ip_view_state state)
54 {
55   irp->ip_view = state;
56 }
57
58 /* Set the state of the interprocedural view to invalid. */
59 void set_irp_ip_view_invalid(void)
60 {
61   set_irp_ip_view(ip_view_invalid);
62 }
63
64
65 /* Data for each method */
66 typedef struct {
67   int count;                      /* Number of calleers. */
68   bool open;                      /* Open method: called by an unknown caller */
69   ir_node * reg, * mem, ** res;   /* EndReg, Mem and Method return values */
70   ir_node * except, * except_mem; /* EndExcept and Mem for exception return */
71 } irg_data_t;
72
73 static irg_data_t * irg_data_create(void)
74 {
75   return XMALLOCZ(irg_data_t);
76 }
77
78 /** Count the number of callers of each method and mark open methods.
79  *
80  *  Fills the irg_data data structure.
81  *  Open methods are methods with an unknown caller, I.e., methods that
82  *   - are external visible
83  *   - are dereferenced somewhere within the program (i.e., the address of the
84  *     method is stored somewhere). */
85 static void caller_init(int arr_length, ir_entity ** free_methods)
86 {
87   int i, j;
88   for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
89     set_entity_link(get_irg_entity(get_irp_irg(i)), irg_data_create());
90   }
91   for (i = arr_length - 1; i >= 0; --i) {
92     irg_data_t * data = get_entity_link(free_methods[i]);
93     data->open = true;
94   }
95   for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
96     ir_graph * irg = get_irp_irg(i);
97     ir_node * call;
98     /* We collected all call nodes in a link list at the end node. */
99     for (call = get_irn_link(get_irg_end(irg)); call; call = get_irn_link(call)) {
100       if (!is_Call(call)) continue;
101       for (j = get_Call_n_callees(call) - 1; j >= 0; --j) {
102         ir_entity * ent = get_Call_callee(call, j);
103         if (get_entity_irg(ent)) {
104           irg_data_t * data = get_entity_link(ent);
105 # ifndef CATE_jni
106           assert(get_entity_irg(ent) && data);
107           ++data->count;
108 # endif /* ndef CATE_jni */
109         } else {
110           set_entity_link(ent, NULL);
111         }
112       }
113     }
114   }
115 }
116
117 /*
118 static inline ir_node * tail(ir_node * node)
119 {
120   ir_node * link;
121   for (; (link = get_irn_link(node)); node = link) ;
122   return node;
123 }
124 */
125
126 /* Call-Operationen an die "link"-Liste von "call_tail" anhängen (und
127  * "call_tail" aktualisieren), Proj-Operationen in die Liste ihrer Definition
128  * (auch bei Proj->Call Operationen) und Phi-Operationen in die Liste ihres
129  * Grundblocks einfügen. */
130 static void collect_phicallproj_walker(ir_node * node, ir_node ** call_tail)
131 {
132   if (is_Call(node)) {
133     /* Die Liste von Call an call_tail anhängen. */
134     ir_node * link;
135     assert(get_irn_link(*call_tail) == NULL);
136     set_irn_link(*call_tail, node);
137     /* call_tail aktualisieren: */
138     for (link = get_irn_link(*call_tail); link; *call_tail = link, link = get_irn_link(link)) ;
139   } else if (get_irn_op(node) == op_Proj) {
140     ir_node * head = skip_Proj(get_Proj_pred(node));
141     set_irn_link(node, get_irn_link(head));
142     set_irn_link(head, node);
143     /* call_tail gegebenenfalls aktualisieren: */
144     if (head == *call_tail) {
145       *call_tail = node;
146     }
147   } else if (get_irn_op(node) == op_Phi) {
148     ir_node * block = get_nodes_block(node);
149     set_irn_link(node, get_irn_link(block));
150     set_irn_link(block, node);
151   }
152 }
153
154
155 static void link(ir_node * head, ir_node * node)
156 {
157   if (node) {
158     set_irn_link(node, get_irn_link(head));
159     set_irn_link(head, node);
160   }
161 }
162
163
164 /* Die Call-Operationen aller Graphen an den End-Operationen
165  * verlinken, die Proj-Operationen an ihren Definitionen und die
166  * Phi-Operationen an ihren Grundblöcken. Die Liste der Calls sieht
167  * dann so aus: End -> Call -> Proj -> ... -> Proj -> Call -> Proj ->
168  * ... -> Proj -> NULL. */
169 static void collect_phicallproj(void)
170 {
171   int i;
172
173   for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
174     ir_graph * irg = get_irp_irg(i);
175     ir_node * start = get_irg_start(irg);
176     ir_node * end = get_irg_end(irg);
177     current_ir_graph = irg;
178     assert(irg && start);
179
180         set_using_irn_link(irg);
181
182     /* Die speziellen Parameter der Start-Operation extra verlinken,
183      * auch wenn sie nicht im intraprozeduralen Graphen erreichbar
184      * sind. */
185     link(start, get_irg_frame(irg));
186     /* walk */
187     irg_walk_graph(irg, firm_clear_link, (irg_walk_func *) collect_phicallproj_walker, &end);
188
189         clear_using_irn_link(irg);
190   }
191 }
192
193
194 /* Proj-Operation durch Filter-Operation im aktuellen Block ersetzen. */
195 static ir_node * exchange_proj(ir_node * proj)
196 {
197   ir_node * filter;
198   assert(get_irn_op(proj) == op_Proj);
199   filter = new_Filter(get_Proj_pred(proj), get_irn_mode(proj), get_Proj_proj(proj));
200   /* Die Proj- (Id-) Operation sollte im gleichen Grundblock stehen, wie die
201    * Filter-Operation. */
202   set_nodes_block(proj, get_nodes_block(filter));
203   exchange(proj, filter);
204   return filter;
205 }
206
207
208 /* Echt neue Block-Operation erzeugen. CSE abschalten! */
209 static ir_node * create_Block(int n, ir_node ** in)
210 {
211   /* Turn off optimizations so that blocks are not merged again. */
212   int rem_opt = get_opt_optimize();
213   ir_node * block;
214   set_optimize(0);
215   block = new_Block(n, in);
216   set_cur_block(block);
217   set_optimize(rem_opt);
218   return block;
219 }
220
221
222 static void prepare_irg_end(ir_graph * irg, irg_data_t * data);
223 static void prepare_irg_end_except(ir_graph * irg, irg_data_t * data);
224
225
226 /* If we use new_Unknown we get the Unknown of a graph.  This can
227  * cause cycles we don't want to see, as Unknwon is in the Start Block
228  * of the procedure. Use unknown of outermost irg where the start
229  * block has no predecessors. */
230 static inline ir_node *get_cg_Unknown(ir_mode *m)
231 {
232   assert((get_Block_n_cfgpreds(get_irg_start_block(get_irp_main_irg())) == 1) &&
233          (get_nodes_block(get_Block_cfgpred(get_irg_start_block(get_irp_main_irg()), 0)) ==
234           get_irg_start_block(get_irp_main_irg())));
235   return new_r_Unknown(get_irp_main_irg(), m);
236 }
237
238
239 /* IRG vorbereiten. Proj-Operationen der Start-Operation in Filter-Operationen
240  * umwandeln. Die künstlichen Steuerzusammenflüsse EndReg und EndExcept
241  * einfügen. An der Start-Operation hängt nach dem Aufruf eine Liste der
242  * entsprechenden Filter-Knoten. */
243 static void prepare_irg(ir_graph * irg, irg_data_t * data)
244 {
245   ir_node * start_block = get_irg_start_block(irg);
246   ir_node * link, * proj;
247   int n_callers = data->count + (data->open ? 1 : 0);
248   ir_node ** in = NEW_ARR_F(ir_node *, n_callers);
249
250   current_ir_graph = irg;
251   set_irg_current_block(irg, start_block);
252
253   /* Grundblock interprozedural machen. */
254   /* "in" ist nicht initialisiert. Das passiert erst in "construct_start". */
255   set_Block_cg_cfgpred_arr(start_block, n_callers, in);
256   /* Proj-Operationen durch Filter-Operationen ersetzen und (sonst) in
257    * den Start-Block verschieben. */
258   for (proj = get_irn_link(get_irg_start(irg)); proj; proj = get_irn_link(proj)) {
259     if (get_Proj_pred(proj) != get_irg_start(irg)
260     || (get_Proj_proj(proj) != pn_Start_X_initial_exec && get_Proj_proj(proj) != pn_Start_T_args)) {
261       ir_node * filter = exchange_proj(proj);
262       set_Filter_cg_pred_arr(filter, n_callers, in);
263     } else {
264       set_nodes_block(proj, start_block);
265     }
266   }
267
268   DEL_ARR_F(in);
269
270   /* Liste der Filter-Operationen herstellen. Dabei muss man beachten,
271    * dass oben für "verschiedene" Proj-Operationen wegen CSE nur eine
272    * Filter-Operation erzeugt worden sein kann. */
273   for (link = get_irg_start(irg), proj = get_irn_link(link); proj; proj = get_irn_link(proj)) {
274     if (is_Id(proj)) { /* replaced with filter */
275       ir_node * filter = get_Id_pred(proj);
276       assert(is_Filter(filter));
277       if (filter != link && get_irn_link(filter) == NULL) {
278     set_irn_link(link, filter);
279     link = filter;
280       }
281     }
282   }
283   /* Globle Einträge für ersetzte Operationen korrigieren. */
284   set_irg_initial_exec(irg, skip_Id(get_irg_initial_exec(irg)));
285   set_irg_frame       (irg, skip_Id(get_irg_frame(irg)));
286   set_irg_initial_mem (irg, skip_Id(get_irg_initial_mem(irg)));
287
288   /* Unbekannten Aufrufer sofort eintragen. */
289   if (data->open) {
290     set_Block_cg_cfgpred(start_block, 0, get_cg_Unknown(mode_X));
291     for (proj = get_irn_link(get_irg_start(irg)); proj; proj = get_irn_link(proj)) {
292       if (is_Filter(proj)) {
293     set_Filter_cg_pred(proj, 0, get_cg_Unknown(get_irn_mode(proj)));
294       }
295     }
296     data->count = 1;
297   } else {
298     data->count = 0;
299   }
300
301   prepare_irg_end(irg, data);
302   prepare_irg_end_except(irg, data);
303 }
304
305
306 /* Künstlicher Steuerzusammenfluss EndReg einfügen. */
307 static void prepare_irg_end(ir_graph * irg, irg_data_t * data)
308 {
309   ir_node * end_block   = get_irg_end_block(irg);
310   ir_node * end         = get_irg_end(irg);
311   ir_node **ret_arr     = NULL;
312   ir_node **cfgpred_arr = get_Block_cfgpred_arr(end_block);
313   int i, j;
314   int n_ret = 0;
315
316   for (i = get_Block_n_cfgpreds(end_block) - 1; i >= 0; --i) {
317     if (is_Return(cfgpred_arr[i])) {
318       if (ret_arr) {
319         ARR_APP1(ir_node *, ret_arr, cfgpred_arr[i]);
320       } else {
321         ret_arr = NEW_ARR_F(ir_node *, 1);
322         ret_arr[0] = cfgpred_arr[i];
323       }
324       ++n_ret;
325     }
326   }
327
328   if (n_ret > 0) {
329     int n_res = get_method_n_ress(get_entity_type(get_irg_entity(irg)));
330     ir_node ** in = NEW_ARR_F(ir_node *, n_ret);
331
332     /* block */
333     for (i = n_ret - 1; i >= 0; --i) {
334       set_irg_current_block(irg, get_nodes_block(ret_arr[i]));
335       in[i] = new_Jmp();
336     }
337     create_Block(n_ret, in);
338
339     /* end */
340     data->reg = new_EndReg();
341
342     /* mem */
343     for (i = n_ret - 1; i >= 0; --i) {
344       in[i] = get_Return_mem(ret_arr[i]);
345     }
346     data->mem = new_Phi(n_ret, in, mode_M);
347     /* This Phi is a merge, therefore needs not be kept alive.
348        It might be optimized away, though.  */
349     if (get_End_keepalive(end, get_End_n_keepalives(end)-1 ) == data->mem)
350       set_End_keepalive(end, get_End_n_keepalives(end)-1, new_Bad());
351
352     /* res */
353     data->res = NEW_ARR_F(ir_node *, n_res);
354     for (j = n_res - 1; j >= 0; --j) {
355       ir_mode *mode = NULL;
356       /* In[0] could be a Bad node with wrong mode. */
357       for (i = n_ret - 1; i >= 0; --i) {
358         in[i] = get_Return_res(ret_arr[i], j);
359         if (!mode && get_irn_mode(in[i]) != mode_T)
360           mode = get_irn_mode(in[i]);
361       }
362       if (mode)
363         data->res[j] = new_Phi(n_ret, in, mode);
364       else  /* All preds are Bad */
365         data->res[j] = new_Bad();
366     }
367
368     DEL_ARR_F(in);
369   }
370
371   if (ret_arr) DEL_ARR_F(ret_arr);
372 }
373
374
375 /* Künstlicher Steuerzusammenfluss EndExcept einfügen. */
376 static void prepare_irg_end_except(ir_graph * irg, irg_data_t * data)
377 {
378   ir_node * end_block = get_irg_end_block(irg);
379   ir_node * end = get_irg_end(irg);
380   ir_node ** except_arr = NULL;
381   int i;
382   int n_except = 0;
383   ir_node ** cfgpred_arr = get_Block_cfgpred_arr(end_block);
384   for (i = get_Block_n_cfgpreds(end_block) - 1; i >= 0; --i) {
385     if (! is_Return(cfgpred_arr[i])) {
386       if (except_arr) {
387         ARR_APP1(ir_node *, except_arr, cfgpred_arr[i]);
388       } else {
389         except_arr = NEW_ARR_F(ir_node *, 1);
390         except_arr[0] = cfgpred_arr[i];
391       }
392       ++n_except;
393     }
394   }
395   if (n_except > 0) {
396     ir_node ** in = NEW_ARR_F(ir_node *, n_except);
397     /* block */
398     create_Block(n_except, except_arr);
399     /* end_except */
400     data->except = new_EndExcept();
401     /* mem */
402     for (i = n_except - 1; i >= 0; --i) {
403       ir_node *node = skip_Proj(skip_Tuple(except_arr[i]));
404       ir_op *op = get_irn_op(node);
405       if (op == op_Call) {
406         in[i] = new_r_Proj(irg, get_nodes_block(node), node, mode_M, pn_Call_M_except);
407       } else if (op == op_Raise) {
408         in[i] = new_r_Proj(irg, get_nodes_block(node), node, mode_M, pn_Raise_M);
409       } else if (op == op_CopyB) {
410         in[i] = new_r_Proj(irg, get_nodes_block(node), node, mode_M, pn_CopyB_M_except);
411       } else {
412         assert(is_fragile_op(node));
413         /* We rely that all cfops have the memory output at the same position. */
414         in[i] = new_r_Proj(irg, get_nodes_block(node), node, mode_M, 0);
415       }
416     }
417     data->except_mem = new_Phi(n_except, in, mode_M);
418     /* This Phi is a merge, therefor needs not be kept alive.
419        It might be optimized away, though.  */
420     if (get_End_keepalive(end, get_End_n_keepalives(end)-1 )
421     == data->except_mem)
422       set_End_keepalive(end, get_End_n_keepalives(end)-1, new_Bad());
423     DEL_ARR_F(in);
424   }
425   if (except_arr) DEL_ARR_F(except_arr);
426 }
427
428
429 /* Zwischengespeicherte Daten wieder freigeben. */
430 static void cleanup_irg(ir_graph * irg)
431 {
432   ir_entity * ent = get_irg_entity(irg);
433   irg_data_t * data = get_entity_link(ent);
434   assert(data);
435   if (data->res) DEL_ARR_F(data->res);
436   set_entity_link(ent, NULL);
437   free(data);
438 }
439
440
441 /* Alle Phi-Operationen aus "from_block" nach "to_block"
442  * verschieben. Die Phi-Operationen müssen am zugehörigen Grundblock
443  * verlinkt sein. Danach sind sie am neuen Grundblock verlinkt. */
444 static void move_phis(ir_node * from_block, ir_node * to_block)
445 {
446   ir_node * phi;
447   for (phi = get_irn_link(from_block); phi != NULL; phi = get_irn_link(phi)) {
448     set_nodes_block(phi, to_block);
449   }
450   assert(get_irn_link(to_block) == NULL);
451   set_irn_link(to_block, get_irn_link(from_block));
452   set_irn_link(from_block, NULL);
453 }
454
455
456 /* Rekursiv die Operation "node" und alle ihre Vorgänger aus dem Block
457  * "from_block" nach "to_block" verschieben.
458  * Verschiebe ebenfalls die Projs aus diesen Operationen. */
459 static void move_nodes(ir_node * from_block, ir_node * to_block, ir_node * node)
460 {
461   int i,  arity = get_irn_arity(node);
462   ir_node *proj;
463
464   for (i = arity - 1; i >= 0; --i) {
465     ir_node * pred = get_irn_n(node, i);
466     if (get_nodes_block(pred) == from_block) {
467       move_nodes(from_block, to_block, pred);
468     }
469   }
470   set_nodes_block(node, to_block);
471
472   /* Move projs of this node. */
473   proj = get_irn_link(node);
474   for (; proj; proj = skip_Id(get_irn_link(proj))) {
475     if (get_irn_op(proj) != op_Proj && !is_Filter(proj)) continue;
476     if ((get_nodes_block(proj) == from_block) && (skip_Proj(get_irn_n(proj, 0)) == node))
477       set_nodes_block(proj, to_block);
478   }
479 }
480
481
482 /* Abhängigkeiten vom Start-Block und den Filter-Operationen im
483  * Start-Block auf den Aufrufer hinzufügen. */
484 static void construct_start(ir_entity * caller, ir_entity * callee,
485                             ir_node * call, ir_node * exec)
486 {
487   irg_data_t *data  = get_entity_link(callee);
488   ir_graph   *irg   = get_entity_irg(callee);
489   ir_node    *start = get_irg_start(irg);
490   ir_node    *filter;
491   (void) caller;
492
493   assert(irg);
494   assert(get_entity_peculiarity(callee) == peculiarity_existent); /* Else data is not initalized. */
495   assert((0 <= data->count) &&
496          (data->count < get_Block_cg_n_cfgpreds(get_nodes_block(start))));
497
498   set_Block_cg_cfgpred(get_nodes_block(start), data->count, exec);
499   for (filter = get_irn_link(start); filter; filter = get_irn_link(filter)) {
500     if (!is_Filter(filter)) continue;
501     if (get_Proj_pred(filter) == start) {
502       switch ((int) get_Proj_proj(filter)) {
503       case pn_Start_M:
504     set_Filter_cg_pred(filter, data->count, get_Call_mem(call));
505     break;
506       case  pn_Start_P_frame_base:
507     /* "frame_base" wird nur durch Unknown dargestellt. Man kann ihn aber
508      * auch explizit darstellen, wenn sich daraus Vorteile für die
509      * Datenflussanalyse ergeben. */
510     set_Filter_cg_pred(filter, data->count, get_cg_Unknown(get_irn_mode(filter)));
511     break;
512       case pn_Start_P_globals:
513     /* "globals" wird nur durch Unknown dargestellt. Man kann ihn aber auch
514      * explizit darstellen, wenn sich daraus Vorteile für die
515      * Datenflussanalyse ergeben. */
516     set_Filter_cg_pred(filter, data->count, get_cg_Unknown(get_irn_mode(filter)));
517     break;
518       default:
519     /* not reached */
520     assert(0 && "not reached");
521     break;
522       }
523     } else {
524       set_Filter_cg_pred(filter, data->count, get_Call_param(call, get_Proj_proj(filter)));
525     }
526   }
527   ++data->count;
528 }
529
530
531 /* Abhängigkeiten für den Speicherzustand über alle aufgerufenen
532  * Methoden bestimmen. */
533 static void fill_mem(int length, irg_data_t * data[], ir_node * in[])
534 {
535   int i;
536   for (i = 0; i < length; ++i) {
537     if (data[i]) { /* explicit */
538       if (data[i]->reg) {
539         in[i] = data[i]->mem;
540       } else {
541         in[i] = new_Bad();
542       }
543     } else { /* unknown */
544       in[i] = get_cg_Unknown(mode_M);
545     }
546   }
547 }
548
549
550 /* Abhängigkeiten für den Ausnahme-Speicherzustand über alle
551  * aufgerufenen Methoden bestimmen. */
552 static void fill_except_mem(int length, irg_data_t * data[], ir_node * in[])
553 {
554   int i;
555   for (i = 0; i < length; ++i) {
556     if (data[i]) { /* explicit */
557       if (data[i]->except) {
558         in[i] = data[i]->except_mem;
559       } else {
560         in[i] = new_Bad();
561       }
562     } else { /* unknown */
563       in[i] = get_cg_Unknown(mode_M);
564     }
565   }
566 }
567
568
569 /* Abhängigkeiten für ein Ergebnis über alle aufgerufenen Methoden
570  * bestimmen. */
571 static void fill_result(int pos, int length, irg_data_t * data[], ir_node * in[], ir_mode *m)
572 {
573   int i;
574   for (i = 0; i < length; ++i) {
575     if (data[i]) { /* explicit */
576       if (data[i]->reg) {
577         in[i] = data[i]->res[pos];
578       } else {
579         in[i] = new_Bad();
580       }
581     } else { /* unknown */
582       in[i] = get_cg_Unknown(m);
583     }
584   }
585 }
586
587
588 /* Proj auf Except-X einer Call-Operation (aus der Link-Liste) bestimmen. */
589 static ir_node * get_except(ir_node * call)
590 {
591   /* Mit CSE könnte man das effizienter machen! Die Methode wird aber für jede
592    * Aufrufstelle nur ein einziges Mal aufgerufen. */
593   ir_node * proj;
594   for (proj = get_irn_link(call); proj && get_irn_op(proj) == op_Proj; proj = get_irn_link(proj)) {
595     if (get_Proj_proj(proj) == 1 && is_Call(get_Proj_pred(proj))) {
596       return proj;
597     }
598   }
599   return NULL;
600 }
601
602 /* Returns true if control flow operation exc is predecessor of end
603    block in irg.  Works also for Return nodes, not only exceptions. */
604 static bool exc_branches_to_end(ir_graph *irg, ir_node *exc)
605 {
606   int i;
607   ir_node *end = get_irg_end_block(irg);
608   for (i = get_Block_n_cfgpreds(end) -1; i >= 0; --i)
609     if (get_Block_cfgpred(end, i) == exc) return true;
610   return false;
611 }
612
613 /* Returns true if only caller of irg is "Unknown". */
614 static bool is_outermost_graph(ir_graph *irg)
615 {
616   irg_data_t * data = get_entity_link(get_irg_entity(irg));
617   if (data->count) {
618     return false;
619   } else if (data->open) {
620     /* Die Methode wird nur von "der" unbekannten Aufrufstelle
621      * aufgerufen. Darstellung wird für diese Methode nicht
622      * geändert. */
623   } else {
624     /* Methode kann nicht aufgerufen werden. Die Darstellung wird
625      * für diese Methode nicht geändert. Das kann nicht vorkommen,
626      * wenn zuvor "gc_irgs()" aufgerufen wurde. */
627   }
628   return true;
629 }
630
631 #ifdef INTERPROCEDURAL_VIEW
632 /* Grundblock der Call-Operation aufteilen. CallBegin- und Filter-Operationen
633  * einfügen. Die Steuer- und Datenflussabhängigkeiten von den aufgerufenen
634  * Methoden auf die CallBegin-Operation, und von der Aufrufstelle auf die
635  * aufgerufenen Methoden eintragen. */
636 static void construct_call(ir_node * call)
637 {
638   int i, n_callees;
639   ir_node *post_block, *pre_block, *except_block, * proj, *jmp, *call_begin;
640   ir_node ** in;
641   ir_entity * caller;
642   ir_entity ** callees;
643   ir_graph ** irgs;
644   irg_data_t ** data;
645
646   n_callees  = get_Call_n_callees(call);
647   post_block = get_nodes_block(call); /* block nach dem Aufruf */
648   pre_block  = create_Block(get_Block_n_cfgpreds(post_block),
649                       get_Block_cfgpred_arr(post_block)); /* block vor dem Aufruf (mit CallBegin) */
650   except_block = NULL;
651   jmp = new_Break(); /* Sprung für intraprozedurale Darstellung (in     * pre_block) */
652   call_begin = new_CallBegin(get_Call_ptr(call), call); /* (in pre_block) */
653   /* CallBegin might be entry to endless recursion. */
654   add_End_keepalive(get_irg_end(get_irn_irg(pre_block)), pre_block);
655
656   in = NEW_ARR_F(ir_node *, n_callees);
657   caller = get_irg_entity(current_ir_graph); /* entity des aktuellen ir_graph */
658   callees = NEW_ARR_F(ir_entity *, n_callees); /* aufgerufene Methoden: entity */
659   irgs = NEW_ARR_F(ir_graph *, n_callees); /* aufgerufene Methoden: ir_graph */
660   data = NEW_ARR_F(irg_data_t *, n_callees); /* aufgerufene Methoden: irg_data_t */
661
662   /* post_block kann bereits interprozedurale Steuerflussvorgänger
663    * besitzen. Diese müssen dann auch noch für den pre_block gesetzt werden. */
664   if (get_Block_cg_cfgpred_arr(post_block)) {
665     set_Block_cg_cfgpred_arr(pre_block, get_Block_cg_n_cfgpreds(post_block),
666                  get_Block_cg_cfgpred_arr(post_block));
667     remove_Block_cg_cfgpred_arr(post_block);
668   }
669
670   /* Operationen verschieben */
671   move_phis(post_block, pre_block);
672   move_nodes(post_block, pre_block, call);
673   set_irn_in(post_block, 1, &jmp);
674
675   /* Wiederverwendete Daten initialisieren. */
676   for (i = 0; i < n_callees; ++i) {
677     callees[i] = get_Call_callee(call, i);
678     irgs[i] = get_entity_irg(callees[i]);
679     data[i] = get_entity_link(callees[i]);
680     /* Only entities that have an irg got a irg_data data structure.
681        In others there is some arbitrary garbage in the link field. */
682     if (!irgs[i]) { assert(!data[i]); data[i] = NULL; }
683   }
684
685   /*
686    * Set flag to suppress verifying placement on proper irg:
687    * optimization can return block on other irg.
688    */
689   set_interprocedural_view(1);
690
691   /* Die interprozeduralen Steuerflussvorgänger des post_block
692    * bestimmen. */
693   for (i = 0; i < n_callees; ++i) {
694     if (data[i]) { /* explicit */
695       if (data[i]->reg) {
696             in[i] = new_r_Proj(irgs[i], get_nodes_block(data[i]->reg),
697                                data[i]->reg, mode_X, data[i]->count);
698       } else {
699             in[i] = new_Bad();
700       }
701     } else { /* unknown */
702       in[i] = get_cg_Unknown(mode_X);
703     }
704   }
705   set_interprocedural_view(0);
706
707   set_Block_cg_cfgpred_arr(post_block, n_callees, in);
708
709   /* Die interprozeduralen Steuerflussvorgänger des except_block
710    * bestimmen. */
711   if ((proj = get_except(call)) != NULL) {
712     int preds = 0;
713     bool exc_to_end = false;
714     if (exc_branches_to_end(current_ir_graph, proj)) {
715       /* The Call aborts the procedure if it returns with an exception.
716          If this is an outermost procedure, the normal handling of exceptions
717          will generate a Break that goes to the end block.  This is illegal
718          Frim. So directly branch to the end block with all exceptions. */
719       exc_to_end = true;
720       if (is_outermost_graph(current_ir_graph)) {
721             except_block = get_irg_end_block(current_ir_graph);
722       } else {
723             irg_data_t * tmp_data = get_entity_link(get_irg_entity(current_ir_graph));
724             except_block = get_nodes_block(tmp_data->except);
725       }
726     } else {
727       except_block = create_Block(1, &proj);
728       set_nodes_block(proj, except_block);
729       exchange(proj, new_Break());
730       set_irg_current_block(current_ir_graph, pre_block);
731       set_irn_n(except_block, 0, new_Proj(call, mode_X, pn_Call_X_except));
732       set_irg_current_block(current_ir_graph, post_block);
733     }
734
735     /*
736      * Set flag to suppress verifying placement on proper irg:
737      * optimization can return block on other irg.
738      */
739     set_interprocedural_view(1);
740
741     for (i = 0; i < n_callees; ++i) {
742       ir_entity * callee = get_Call_callee(call, i);
743       if (data[i]) { /* explicit */
744             if (data[i]->except) {
745               in[i] = new_r_Proj(get_entity_irg(callee), get_nodes_block(data[i]->except),
746                                  data[i]->except, mode_X, data[i]->count);
747             } else {
748               in[i] = new_Bad();
749             }
750       } else { /* unknown */
751             in[i] = get_cg_Unknown(mode_X);
752       }
753     }
754
755     preds = n_callees;
756     if (exc_to_end) {
757       /* append all existing preds of the end block to new in array.
758        * Normal access routine guarantees that with first visit we
759        * get the normal preds, and from then on the _cg_ preds.
760        * (interprocedural view is set!)
761        * Do not add the exc pred of end we are replacing! */
762       for (i = get_Block_n_cfgpreds(except_block)-1; i >= 0; --i) {
763             ir_node *pred = get_Block_cfgpred(except_block, i);
764             if (pred != proj) {
765               ARR_APP1(ir_node *, in, pred);
766               preds++;
767             }
768       }
769     }
770     set_Block_cg_cfgpred_arr(except_block, preds, in);
771   }
772   set_interprocedural_view(0);
773
774   /* Diesen Vorgänger in den Start-Blöcken der aufgerufenen Methoden
775    * eintragen. */
776   set_irg_current_block(current_ir_graph, pre_block);
777   for (i = 0; i < n_callees; ++i) {
778     if (irgs[i]) /* Else there is not graph to call */
779       construct_start(caller, callees[i], call, new_Proj(call_begin, mode_X, i));
780   }
781
782   /* Proj-Operationen in Filter-Operationen umwandeln und
783    * interprozedurale Vorgänger einfügen. */
784   set_irg_current_block(current_ir_graph, post_block);
785   for (proj = get_irn_link(call); proj; proj = get_irn_link(proj)) {
786     if (get_irn_op(proj) != op_Proj) continue;
787     if (skip_Proj(get_Proj_pred(proj)) != call) continue;
788     if (get_Proj_pred(proj) == call) {
789       if (get_Proj_proj(proj) == pn_Call_M_regular) { /* memory */
790             ir_node * filter;
791
792             set_nodes_block(proj, post_block);
793             filter = exchange_proj(proj);
794             /* filter in die Liste der Phis aufnehmen */
795             if (get_irn_link(filter) == NULL) { /* note CSE */
796               set_irn_link(filter, get_irn_link(post_block));
797               set_irn_link(post_block, filter);
798             }
799             fill_mem(n_callees, data, in);
800             set_Filter_cg_pred_arr(filter, n_callees, in);
801       } else if (get_Proj_proj(proj) == pn_Call_X_except) { /* except */
802         /* nothing: siehe oben */
803       } else if (get_Proj_proj(proj) == pn_Call_T_result) { /* results */
804             /* nothing */
805       } else if (get_Proj_proj(proj) == pn_Call_M_except) { /* except_mem */
806         ir_node * filter;
807
808             set_nodes_block(proj, post_block);
809             assert(except_block);
810             set_irg_current_block(current_ir_graph, except_block);
811             filter = exchange_proj(proj);
812             /* filter in die Liste der Phis aufnehmen */
813             if (get_irn_link(filter) == NULL) { /* note CSE */
814               set_irn_link(filter, get_irn_link(except_block));
815               set_irn_link(except_block, filter);
816             }
817             set_irg_current_block(current_ir_graph, post_block);
818             fill_except_mem(n_callees, data, in);
819             set_Filter_cg_pred_arr(filter, n_callees, in);
820       } else {
821         assert(0 && "not reached");
822       }
823     } else { /* result */
824       ir_node * filter;
825
826       assert(is_Proj(get_Proj_pred(proj)) && get_Proj_pred(get_Proj_pred(proj)) == call);
827       set_nodes_block(proj, post_block);
828       filter = exchange_proj(proj);
829       /* filter in die Liste der Phis aufnehmen */
830       if (get_irn_link(filter) == NULL) { /* not CSE */
831             set_irn_link(filter, get_irn_link(post_block));
832             set_irn_link(post_block, filter);
833       }
834       fill_result(get_Proj_proj(filter), n_callees, data, in, get_irn_mode(filter));
835       set_Filter_cg_pred_arr(filter, n_callees, in);
836     }
837   }
838   DEL_ARR_F(in);
839   DEL_ARR_F(callees);
840   DEL_ARR_F(irgs);
841   DEL_ARR_F(data);
842 }
843 #endif
844
845
846 void cg_construct(int arr_len, ir_entity ** free_methods_arr)
847 {
848   int i;
849
850   if (get_irp_ip_view_state() == ip_view_valid) return;
851   if (get_irp_ip_view_state() == ip_view_invalid) cg_destruct();
852   set_irp_ip_view(ip_view_valid);
853
854   collect_phicallproj();
855
856   /* count callers */
857   caller_init(arr_len, free_methods_arr);
858
859   /* prepare irgs */
860   for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
861     ir_graph * irg = get_irp_irg(i);
862     ir_entity * ent = get_irg_entity(irg);
863     irg_data_t * data = get_entity_link(ent);
864     if (data->count) {
865       prepare_irg(irg, data);
866     } else if (data->open) {
867       /* Die Methode wird nur von "der" unbekannten Aufrufstelle
868        * aufgerufen. Darstellung wird für diese Methode nicht
869        * geändert. */
870     } else {
871       /* Methode kann nicht aufgerufen werden. Die Darstellung wird
872        * für diese Methode nicht geändert. Das kann nicht vorkommen,
873        * wenn zuvor "gc_irgs()" aufgerufen wurde. */
874     }
875   }
876
877   /* construct calls */
878   for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
879     ir_node * node;
880
881     current_ir_graph = get_irp_irg(i);
882     for (node = get_irn_link(get_irg_end(current_ir_graph)); node; node = get_irn_link(node)) {
883       if (is_Call(node)) {
884         int j, n_callees = get_Call_n_callees(node);
885         for (j = 0; j < n_callees; ++j)
886           if (get_entity_irg(get_Call_callee(node, j)))
887             break;
888           if (j < n_callees)  /* There is an entity with a graph */
889             construct_call(node);
890       }
891     }
892   }
893
894   /* cleanup irgs: Abschlussarbeiten: Die Vorgänger der Methoden noch
895    * explizit setzen und die zwischengespeicherten Daten wieder
896    * freigeben. */
897   for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
898     cleanup_irg(get_irp_irg(i));
899   }
900 }
901
902
903
904 static void destruct_walker(ir_node * node, void * env)
905 {
906   (void) env;
907   if (is_Block(node)) {
908     remove_Block_cg_cfgpred_arr(node);
909     /* Do not turn Break into Jmp.  Better: merge blocks right away.
910        Well, but there are Breaks left.
911        See exc1 from ajacs-rts/Exceptions.java.  */
912     if (get_Block_n_cfgpreds(node) == 1) {
913       ir_node *pred = get_Block_cfgpred(node, 0);
914       if (get_irn_op(pred) == op_Break)
915         exchange(node, get_nodes_block(pred));
916     }
917   } else if (is_Filter(node)) {
918     set_irg_current_block(current_ir_graph, get_nodes_block(node));
919     exchange(node, new_Proj(get_Filter_pred(node), get_irn_mode(node), get_Filter_proj(node)));
920   } else if (get_irn_op(node) == op_Break) {
921     set_irg_current_block(current_ir_graph, get_nodes_block(node));
922     exchange(node, new_Jmp());
923   } else if (is_Call(node)) {
924     remove_Call_callee_arr(node);
925   } else if (get_irn_op(node) == op_Proj) {
926     /*  some ProjX end up in strange blocks. */
927     set_nodes_block(node, get_nodes_block(get_Proj_pred(node)));
928   }
929 }
930
931
932 void cg_destruct(void)
933 {
934   int i;
935   if (get_irp_ip_view_state() != ip_view_no) {
936     for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
937       ir_graph * irg = get_irp_irg(i);
938       irg_walk_graph(irg, destruct_walker, firm_clear_link, NULL);
939
940           set_irg_initial_exec(irg, skip_Id(get_irg_initial_exec(irg)));
941       set_irg_frame       (irg, skip_Id(get_irg_frame(irg)));
942       set_irg_initial_mem (irg, skip_Id(get_irg_initial_mem(irg)));
943       set_irg_end_reg     (irg, get_irg_end(irg));
944       set_irg_end_except  (irg, get_irg_end(irg));
945
946       set_irg_callee_info_state(irg, irg_callee_info_none);
947     }
948
949     set_irp_ip_view(ip_view_no);
950   }
951 }
952
953 #endif