Move includes for alloca() to xmalloc.h, so not everyone and his dog has to use the...
[libfirm] / ir / lower / lower_calls.c
1 /*
2  * Project:     libFIRM
3  * File name:   ir/lower/lower_calls.c
4  * Purpose:     lowering of Calls with compound parameters
5  * Author:      Michael Beck
6  * Created:
7  * CVS-ID:      $Id$
8  * Copyright:   (c) 1998-2005 Universität Karlsruhe
9  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
10  */
11
12 #ifdef HAVE_CONFIG_H
13 #include "config.h"
14 #endif
15
16 #include "irprog_t.h"
17 #include "irnode_t.h"
18 #include "type_t.h"
19 #include "irmode_t.h"
20 #include "ircons.h"
21 #include "irgmod.h"
22 #include "irgwalk.h"
23 #include "typewalk.h"
24 #include "lower_calls.h"
25 #include "return.h"
26 #include "irtools.h"
27 #include "array.h"
28 #include "pmap.h"
29 #include "xmalloc.h"
30
31 /** A type map for def_find_pointer_type. */
32 static pmap *type_map;
33
34 /**
35  * Default implementation for finding a pointer type for a given element type.
36  * Simple create a new one.
37  */
38 static ir_type *def_find_pointer_type(ir_type *e_type, ir_mode *mode, int alignment)
39 {
40   ir_type *res;
41   pmap_entry *e;
42
43   /* Mode and alignment are always identical in all calls to def_find_pointer_type(), so
44      we simply can use a map from the element type to the pointer type. */
45   e = pmap_find(type_map, e_type);
46   if (e)
47     res = e->value;
48   else {
49     res = new_type_pointer(mangle_u(get_type_ident(e_type), new_id_from_chars("Ptr", 3)), e_type, mode);
50     set_type_alignment_bytes(res, alignment);
51     pmap_insert(type_map, e_type, res);
52   }
53   return res;
54 }
55
56 /**
57  * Creates a new lowered type for a method type with compound
58  * arguments. The new type is associated to the old one and returned.
59  *
60  * @param lp   parameter struct
61  * @param mtp  the method type to lower
62  *
63  * The current implementation expects that a lowered type already
64  * includes the necessary changes ...
65  */
66 static ir_type *create_modified_mtd_type(const lower_params_t *lp, ir_type *mtp)
67 {
68   ir_type *lowered, *ptr_tp;
69   ir_type **params, **results, *res_tp;
70   ir_mode *modes[MAX_REGISTER_RET_VAL];
71   int n_ress, n_params, nn_ress, nn_params, i, first_variadic;
72   ident *id;
73   add_hidden hidden_params;
74   variadicity var;
75
76   if (is_lowered_type(mtp)) {
77     /* the type is already lowered. Not handled yet. */
78     assert(0 && "lowered types NYI");
79   }
80
81   lowered = get_associated_type(mtp);
82   if (lowered)
83     return lowered;
84
85   n_ress   = get_method_n_ress(mtp);
86   NEW_ARR_A(ir_type *, results, n_ress);
87
88   n_params = get_method_n_params(mtp);
89   NEW_ARR_A(ir_type *, params, n_params + n_ress);
90
91   first_variadic = get_method_first_variadic_param_index(mtp);
92
93   hidden_params = lp->hidden_params;
94   if (hidden_params == ADD_HIDDEN_SMART &&
95     get_method_variadicity(mtp) == variadicity_variadic)
96         hidden_params = ADD_HIDDEN_ALWAYS_IN_FRONT;
97
98   if (hidden_params == ADD_HIDDEN_ALWAYS_IN_FRONT) {
99     /* add hidden in front */
100     for (nn_ress = nn_params = i = 0; i < n_ress; ++i) {
101       res_tp = get_method_res_type(mtp, i);
102
103       if (is_compound_type(res_tp)) {
104         int n_regs = 0;
105
106         if (lp->flags & LF_SMALL_CMP_IN_REGS)
107           n_regs = lp->ret_compound_in_regs(res_tp, modes);
108
109         if (n_regs > 0) {
110           /* this compound will be returned solely in registers */
111           assert(0);
112         }
113         else {
114           /* this compound will be allocated on callers stack and its
115              address will be transmitted as a hidden parameter. */
116           ptr_tp = lp->find_pointer_type(res_tp, get_modeP_data(), lp->def_ptr_alignment);
117           params[nn_params++] = ptr_tp;
118           if (lp->flags & LF_RETURN_HIDDEN)
119             results[nn_ress++] = ptr_tp;
120         }
121       }
122       else
123         results[nn_ress++] = res_tp;
124     }
125
126     /* move the index of the first variadic parameter */
127     first_variadic += nn_params;
128
129     for (i = 0; i < n_params; ++i)
130       params[nn_params++] = get_method_param_type(mtp, i);
131   }
132   else {
133     /* add hidden parameters last */
134     assert(get_method_variadicity(mtp) == variadicity_non_variadic &&
135       "Cannot add hidden parameters at end of variadic function");
136
137     for (nn_params = 0; nn_params < n_params; ++nn_params)
138       params[nn_params] = get_method_param_type(mtp, nn_params);
139
140     for (nn_ress = i = 0; i < n_ress; ++i) {
141       res_tp = get_method_res_type(mtp, i);
142
143       if (is_compound_type(res_tp))
144         params[nn_params++] = lp->find_pointer_type(res_tp, get_modeP_data(), lp->def_ptr_alignment);
145       else
146         results[nn_ress++] = res_tp;
147     }
148   }
149
150   /* create the new type */
151   id = mangle_u(new_id_from_chars("L", 1), get_type_ident(mtp));
152   lowered = new_d_type_method(id, nn_params, nn_ress, get_type_dbg_info(mtp));
153
154   /* fill it */
155   for (i = 0; i < nn_params; ++i)
156     set_method_param_type(lowered, i, params[i]);
157   for (i = 0; i < nn_ress; ++i)
158     set_method_res_type(lowered, i, results[i]);
159
160   var = get_method_variadicity(mtp);
161   set_method_variadicity(lowered, var);
162   if (var == variadicity_variadic)
163     set_method_first_variadic_param_index(lowered, first_variadic);
164
165   /* associate the lowered type with the original one for easier access */
166   set_lowered_type(mtp, lowered);
167
168   return lowered;
169 }
170
171 /**
172  * A call list entry.
173  */
174 typedef struct cl_entry cl_entry;
175 struct cl_entry {
176   cl_entry *next;   /**< Pointer to the next entry. */
177   ir_node  *call;   /**< Pointer to the Call node. */
178   ir_node  *copyb;  /**< List of all CopyB nodes. */
179 };
180
181 /**
182  * Walker environment for fix_args_and_collect_calls().
183  */
184 typedef struct _wlk_env_t {
185   int                  arg_shift;     /**< The Argument index shift for parameters. */
186   int                  first_hidden;  /**< The index of the first hidden argument. */
187   struct obstack       obst;          /**< An obstack to allocate the data on. */
188   cl_entry             *cl_list;      /**< The call list. */
189   pmap                 *dummy_map;    /**< A map for finding the dummy arguments. */
190   unsigned             dnr;           /**< The dummy index number. */
191   const lower_params_t *params;       /**< lowering parameters */
192 } wlk_env;
193
194 /**
195  * Return the call list entry of a call node.
196  * If no entry exists yet, allocate one and enter the node into
197  * the call list of the environment.
198  *
199  * @param call   A Call node.
200  * @param env    The environment.
201  */
202 static cl_entry *get_Call_entry(ir_node *call, wlk_env *env) {
203   cl_entry *res = get_irn_link(call);
204   if (res == NULL) {
205     cl_entry *res = obstack_alloc(&env->obst, sizeof(*res));
206     res->next  = env->cl_list;
207     res->call  = call;
208     res->copyb = NULL;
209     set_irn_link(call, res);
210     env->cl_list = res;
211   }
212   return res;
213 }
214
215 /**
216  * Post walker: shift all parameter indeces
217  * and collect Calls with compound returns in the call list.
218  */
219 static void fix_args_and_collect_calls(ir_node *n, void *ctx) {
220   wlk_env *env = ctx;
221   int i;
222   ir_type *ctp;
223   ir_op *op = get_irn_op(n);
224
225   if (env->arg_shift > 0 && op == op_Proj) {
226     ir_node *pred = get_Proj_pred(n);
227
228     /* Fix the argument numbers */
229     if (pred == get_irg_args(current_ir_graph)) {
230       long pnr = get_Proj_proj(n);
231       set_Proj_proj(n, pnr + env->arg_shift);
232     }
233   }
234   else if (op == op_Call) {
235     ctp = get_Call_type(n);
236     if (env->params->flags & LF_COMPOUND_RETURN) {
237       /* check for compound returns */
238       for (i = get_method_n_ress(ctp) -1; i >= 0; --i) {
239         if (is_compound_type(get_method_res_type(ctp, i))) {
240           /*
241            * This is a call with a compound return. As the result
242            * might be ignored, we must put it in the list.
243            */
244           (void)get_Call_entry(n, env);
245           break;
246         }
247       }
248     }
249   }
250   else if (op == op_CopyB && env->params->flags & LF_COMPOUND_RETURN) {
251     /* check for compound returns */
252     ir_node *src = get_CopyB_src(n);
253     /* older scheme using value_res_ent */
254     if (is_Sel(src)) {
255       ir_node *proj = get_Sel_ptr(src);
256       if (is_Proj(proj) && get_Proj_proj(proj) == pn_Call_P_value_res_base) {
257         ir_node *call = get_Proj_pred(proj);
258         if (is_Call(call)) {
259           /* found a CopyB from compound Call result */
260           cl_entry *e = get_Call_entry(call, env);
261           set_irn_link(n, e->copyb);
262           e->copyb = n;
263         }
264       }
265     } else
266     /* new scheme: compound results are determined by the call type only */
267     if (is_Proj(src)) {
268       ir_node *proj = get_Proj_pred(src);
269       if (is_Proj(proj) && get_Proj_proj(proj) == pn_Call_T_result) {
270         ir_node *call = get_Proj_pred(proj);
271         if (is_Call(call)) {
272           ctp = get_Call_type(call);
273           if (is_compound_type(get_method_res_type(ctp, get_Proj_proj(src)))) {
274             /* found a CopyB from compound Call result */
275             cl_entry *e = get_Call_entry(call, env);
276             set_irn_link(n, e->copyb);
277             e->copyb = n;
278           }
279         }
280       }
281     }
282   }
283 }
284
285 /**
286  * Returns non-zero if a node is a compound address
287  * of a frame-type entity.
288  *
289  * @param ft   the frame type
290  * @param adr  the node
291  */
292 static int is_compound_address(ir_type *ft, ir_node *adr)
293 {
294   ir_entity *ent;
295
296   if (! is_Sel(adr))
297     return 0;
298   if (get_Sel_n_indexs(adr) != 0)
299     return 0;
300   ent = get_Sel_entity(adr);
301   return get_entity_owner(ent) == ft;
302 }
303
304 /** A pair for the copy-return-optimization. */
305 typedef struct cr_pair {
306   ir_entity *ent; /**< the entity than can be removed from the frame */
307   ir_node *arg;   /**< the argument that replaces the entities address */
308 } cr_pair;
309
310 /**
311  * Post walker: fixes all entities addresses for the copy-return
312  * optimization.
313  *
314  * Note: We expect the length of the cr_pair array (ie number of compound
315  * return values) to be 1 (C, C++) in almost all cases, so ignore the
316  * linear search complexity here.
317  */
318 static void do_copy_return_opt(ir_node *n, void *ctx) {
319   cr_pair *arr = ctx;
320   int i;
321
322   if (is_Sel(n)) {
323     ir_entity *ent = get_Sel_entity(n);
324
325     for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
326       if (ent == arr[i].ent) {
327         exchange(n, arr[i].arg);
328         break;
329       }
330     }
331   }
332 }
333
334 /**
335  * Return a Sel node that selects a dummy argument of type tp.
336  * Dummy arguments are only needed once and we use a map
337  * to store them.
338  * We could even assign all dummy arguments the same offset
339  * in the frame type ...
340  *
341  * @param irg    the graph
342  * @param block  the block where a newly create Sel should be placed
343  * @param tp     the type of the dummy entity that should be create
344  * @param env    the environment
345  */
346 static ir_node *get_dummy_sel(ir_graph *irg, ir_node *block, ir_type *tp, wlk_env *env)
347 {
348   ir_entity *ent;
349   pmap_entry *e;
350
351   /* use a map the check if we already create such an entity */
352   e = pmap_find(env->dummy_map, tp);
353   if (e)
354     ent = e->value;
355   else {
356     ir_type *ft = get_irg_frame_type(irg);
357     char buf[16];
358
359     snprintf(buf, sizeof(buf), "dummy.%u", env->dnr++);
360     ent = new_entity(ft, new_id_from_str(buf), tp);
361     pmap_insert(env->dummy_map, tp, ent);
362
363     if (get_type_state(ft) == layout_fixed) {
364       /* Fix the layout again */
365       assert(0 && "Fixed layout not implemented");
366     }
367   }
368   return new_r_simpleSel(
369     irg,
370     block,
371     get_irg_no_mem(irg),
372     get_irg_frame(irg),
373     ent);
374 }
375
376 /**
377  * Add the hidden parameter from the CopyB node to the Call node.
378  *
379  * @param irg    the graph
380  * @param n_com  number of compound results (will be number of hidden parameters)
381  * @param ins    in array to store the hidden parameters into
382  * @param entry  the call list
383  * @param env    the environment
384  */
385 static void add_hidden_param(ir_graph *irg, int n_com, ir_node **ins, cl_entry *entry, wlk_env *env)
386 {
387   ir_node *p, *n, *src, *mem;
388   ir_entity *ent;
389   ir_type *owner;
390   int idx, n_args;
391
392   n_args = 0;
393   for (p = entry->copyb; p; p = n) {
394     n   = get_irn_link(p);
395     src = get_CopyB_src(p);
396
397     /* old scheme using value_res_ent */
398     if (is_Sel(src)) {
399       ent = get_Sel_entity(src);
400       owner = get_entity_owner(ent);
401
402       /* find the hidden parameter index */
403       for (idx = 0; idx < get_struct_n_members(owner); ++idx)
404         if (get_struct_member(owner, idx) == ent)
405           break;
406       assert(idx < get_struct_n_members(owner));
407     }
408     else
409
410     /* new scheme: compound returns are determined by the call type and are Proj's */
411     idx = get_Proj_proj(src);
412
413     ins[idx] = get_CopyB_dst(p);
414     mem      = get_CopyB_mem(p);
415
416     /* get rid of the CopyB */
417     turn_into_tuple(p, pn_CopyB_max);
418     set_Tuple_pred(p, pn_CopyB_M_regular, mem);
419     set_Tuple_pred(p, pn_CopyB_M_except, get_irg_bad(irg));
420     set_Tuple_pred(p, pn_CopyB_X_except, get_irg_bad(irg));
421     ++n_args;
422   }
423
424   /* now create dummy entities for function with ignored return value */
425   if (n_args < n_com) {
426     ir_type *ctp = get_Call_type(entry->call);
427     int i, j;
428
429     if (is_lowered_type(ctp))
430       ctp = get_associated_type(ctp);
431
432     for (j = i = 0; i < get_method_n_ress(ctp); ++i) {
433       ir_type *rtp = get_method_res_type(ctp, i);
434       if (is_compound_type(rtp)) {
435         if (ins[j] == NULL)
436           ins[j] = get_dummy_sel(irg, get_nodes_block(entry->call), rtp, env);
437         ++j;
438       }
439     }
440   }
441 }
442
443 /**
444  * Fix all calls on a call list by adding hidden parameters.
445  *
446  * @param irg  the graph
447  * @param env  the environment
448  */
449 static void fix_call_list(ir_graph *irg, wlk_env *env) {
450   const lower_params_t *lp = env->params;
451   cl_entry *p;
452   ir_node *call, **new_in;
453   ir_type *ctp, *lowered_mtp;
454   add_hidden hidden_params;
455   int i, n_params, n_com, pos;
456
457   new_in = NEW_ARR_F(ir_node *, 0);
458   for (p = env->cl_list; p; p = p->next) {
459     call = p->call;
460     ctp = get_Call_type(call);
461     lowered_mtp = create_modified_mtd_type(lp, ctp);
462     set_Call_type(call, lowered_mtp);
463
464     hidden_params = lp->hidden_params;
465     if (hidden_params == ADD_HIDDEN_SMART &&
466       get_method_variadicity(ctp) == variadicity_variadic)
467       hidden_params = ADD_HIDDEN_ALWAYS_IN_FRONT;
468
469     n_params = get_Call_n_params(call);
470
471     n_com = 0;
472     for (i = get_method_n_ress(ctp) - 1; i >= 0; --i) {
473       if (is_compound_type(get_method_res_type(ctp, i)))
474         ++n_com;
475     }
476     pos = 2;
477     ARR_RESIZE(ir_node *, new_in, n_params + n_com + pos);
478     memset(new_in, 0, sizeof(*new_in) * (n_params + n_com + pos));
479     if (hidden_params == ADD_HIDDEN_ALWAYS_IN_FRONT) {
480       add_hidden_param(irg, n_com, &new_in[pos], p, env);
481       pos += n_com;
482     }
483     /* copy all other parameters */
484     for (i = 0; i < n_params; ++i)
485       new_in[pos++] = get_Call_param(call, i);
486     if (hidden_params == ADD_HIDDEN_ALWAYS_LAST) {
487       add_hidden_param(irg, n_com, &new_in[pos], p, env);
488       pos += n_com;
489     }
490     new_in[0] = get_Call_mem(call);
491     new_in[1] = get_Call_ptr(call);
492
493     set_irn_in(call, n_params + n_com + 2, new_in);
494   }
495 }
496
497 /**
498  * Transform a graph. If it has compound parameter returns,
499  * remove them and use the hidden parameter instead.
500  * If it calls methods with compound parameter returns, add hidden
501  * parameters.
502  *
503  * @param lp   parameter struct
504  * @param irg  the graph to transform
505  */
506 static void transform_irg(const lower_params_t *lp, ir_graph *irg)
507 {
508   ir_entity *ent = get_irg_entity(irg);
509   ir_type *mtp, *lowered_mtp, *tp, *ft;
510   int i, j, k, n_ress = 0, n_ret_com = 0, n_cr_opt;
511   ir_node **new_in, *ret, *endbl, *bl, *mem, *copy;
512   cr_pair *cr_opt;
513   wlk_env env;
514   add_hidden hidden_params;
515
516   assert(ent && "Cannot tranform graph without an entity");
517   assert(get_irg_phase_state(irg) == phase_high && "call lowering must be done in phase high");
518
519   mtp = get_entity_type(ent);
520
521   if (lp->flags & LF_COMPOUND_RETURN) {
522     /* calculate the number of compound returns */
523     n_ress = get_method_n_ress(mtp);
524     for (n_ret_com = i = 0; i < n_ress; ++i) {
525       tp = get_method_res_type(mtp, i);
526
527       if (is_compound_type(tp))
528         ++n_ret_com;
529     }
530   }
531
532   if (n_ret_com) {
533     /* much easier if we have only one return */
534     normalize_one_return(irg);
535
536     /* This graph has a compound argument. Create a new type */
537     lowered_mtp = create_modified_mtd_type(lp, mtp);
538     set_entity_type(ent, lowered_mtp);
539
540     hidden_params = lp->hidden_params;
541     if (hidden_params == ADD_HIDDEN_SMART &&
542       get_method_variadicity(mtp) == variadicity_variadic)
543       hidden_params = ADD_HIDDEN_ALWAYS_IN_FRONT;
544
545     if (hidden_params == ADD_HIDDEN_ALWAYS_IN_FRONT) {
546       /* hidden arguments are added first */
547       env.arg_shift    = n_ret_com;
548       env.first_hidden = 0;
549     }
550     else {
551       /* hidden arguments are added last */
552       env.arg_shift    = 0;
553       env.first_hidden = get_method_n_params(mtp);
554     }
555   }
556   else {
557     /* we must only search for calls */
558     env.arg_shift = 0;
559   }
560   obstack_init(&env.obst);
561   env.cl_list   = NULL;
562   env.dummy_map = pmap_create_ex(8);
563   env.dnr       = 0;
564   env.params    = lp;
565
566   /* scan the code, fix argument numbers and collect calls. */
567   irg_walk_graph(irg, firm_clear_link, fix_args_and_collect_calls, &env);
568
569   /* fix all calls */
570   if (env.cl_list)
571     fix_call_list(irg, &env);
572
573   if (n_ret_com) {
574     /*
575      * Now fix the Return node of the current graph.
576      */
577
578     /* STEP 1: find the return. This is simple, we have normalized the graph. */
579     endbl = get_irg_end_block(irg);
580     ret = NULL;
581     for (i = get_Block_n_cfgpreds(endbl) - 1; i >= 0; --i) {
582       ir_node *pred = get_Block_cfgpred(endbl, i);
583
584       if (is_Return(pred)) {
585         ret = pred;
586         break;
587       }
588     }
589     /* there should always be a return */
590     assert(ret);
591
592     /*
593      * STEP 2: fix it. For all compound return values add a CopyB,
594      * all others are copied.
595      */
596     NEW_ARR_A(ir_node *, new_in, n_ress + 1);
597
598     bl  = get_nodes_block(ret);
599     mem = get_Return_mem(ret);
600
601     ft = get_irg_frame_type(irg);
602     NEW_ARR_A(cr_pair, cr_opt, n_ret_com);
603     n_cr_opt = 0;
604     for (j = 1, i = k = 0; i < n_ress; ++i) {
605       ir_node *pred = get_Return_res(ret, i);
606       tp = get_method_res_type(mtp, i);
607
608       if (is_compound_type(tp)) {
609         ir_node *arg = get_irg_args(irg);
610         arg = new_r_Proj(irg, get_nodes_block(arg), arg, mode_P_data, env.first_hidden + k);
611         ++k;
612
613         if (is_compound_address(ft, pred)) {
614           /* we can do the copy-return optimization here */
615           cr_opt[n_cr_opt].ent = get_Sel_entity(pred);
616           cr_opt[n_cr_opt].arg = arg;
617           ++n_cr_opt;
618         }
619         else { /* copy-return optimization is impossible, do the copy. */
620           copy = new_r_CopyB(
621                   irg, bl,
622                   mem,
623                   arg,
624                   pred,
625                   tp
626                  );
627           mem = new_r_Proj(irg, bl, copy, mode_M, pn_CopyB_M_regular);
628         }
629         if (lp->flags & LF_RETURN_HIDDEN) {
630           new_in[j] = arg;
631           ++j;
632         }
633       }
634       else { /* scalar return value */
635         new_in[j] = pred;
636         ++j;
637       }
638     }
639     /* replace the in of the Return */
640     new_in[0] = mem;
641     set_irn_in(ret, j, new_in);
642
643     if (n_cr_opt > 0) {
644       irg_walk_graph(irg, NULL, do_copy_return_opt, cr_opt);
645
646       for (i = ARR_LEN(cr_opt) - 1; i >= 0; --i) {
647         remove_class_member(ft, cr_opt[i].ent);
648       }
649     }
650   } /* if (n_ret_com) */
651
652   pmap_destroy(env.dummy_map);
653   obstack_free(&env.obst, NULL);
654 }
655
656 /**
657  * Returns non-zero if the given type is a method
658  * type that must be lowered.
659  *
660  * @param lp  lowering parameters
661  * @param tp  The type.
662  */
663 static int must_be_lowered(const lower_params_t *lp, ir_type *tp) {
664   int i, n_ress;
665   ir_type *res_tp;
666
667   if (is_Method_type(tp)) {
668     if (lp->flags & LF_COMPOUND_RETURN) {
669       /* check for compound returns */
670       n_ress = get_method_n_ress(tp);
671       for (i = 0; i < n_ress; ++i) {
672         res_tp = get_method_res_type(tp, i);
673
674         if (is_compound_type(res_tp))
675           return 1;
676       }
677     }
678   }
679   return 0;
680 }
681
682 /**
683  * type-walker: lower all method types of entities
684  * and points-to types.
685  */
686 static void lower_method_types(type_or_ent *tore, void *env)
687 {
688   const lower_params_t *lp = env;
689   ir_type *tp;
690
691   /* fix method entities */
692   if (is_entity(tore)) {
693     ir_entity *ent = (ir_entity *)tore;
694     tp = get_entity_type(ent);
695
696     if (must_be_lowered(lp, tp)) {
697       tp = create_modified_mtd_type(lp, tp);
698       set_entity_type(ent, tp);
699     }
700   }
701   else {
702     tp = (ir_type *)tore;
703
704     /* fix pointer to methods */
705     if (is_Pointer_type(tp)) {
706       ir_type *etp = get_pointer_points_to_type(tp);
707       if (must_be_lowered(lp, etp)) {
708         etp = create_modified_mtd_type(lp, etp);
709         set_pointer_points_to_type(tp, etp);
710       }
711     }
712   }
713 }
714
715 /*
716  * Lower calls with compound parameters and return types.
717  * This function does the following transformations:
718  *
719  * - Adds a new (hidden) pointer parameter for
720  *   any return compound type.
721  *
722  * - Use of the hidden parameters in the function code.
723  *
724  * - Change all calls to functions with compound return
725  *   by providing space for the hidden parameter on the callers
726  *   stack.
727  *
728  * - Replace a possible block copy after the function call.
729  */
730 void lower_calls_with_compounds(const lower_params_t *params)
731 {
732   int i;
733   ir_graph *irg;
734   lower_params_t param = *params;
735
736   if (param.find_pointer_type == NULL) {
737     param.find_pointer_type = def_find_pointer_type;
738     type_map = pmap_create_ex(8);
739   }
740   else
741     type_map = NULL;
742
743   /* first step: Transform all graphs */
744   for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
745     irg = get_irp_irg(i);
746
747     if (irg == get_const_code_irg())
748       continue;
749
750     transform_irg(&param, irg);
751   }
752
753   /* second step: Lower all method types of visible entities */
754   type_walk(NULL, lower_method_types, &param);
755
756   if (type_map)
757     pmap_destroy(type_map);
758 }