62a82fa8421e01ce2716e7e674077d804d1f5ae6
[libfirm] / ir / be / beabi.c
1 /**
2  * ABI lowering.
3  *
4  *
5  *
6  */
7
8 #include "firm_config.h"
9 #include "obst.h"
10
11 #include "type.h"
12
13 #include "irgraph_t.h"
14 #include "irnode_t.h"
15 #include "ircons_t.h"
16 #include "iredges_t.h"
17 #include "irgmod.h"
18 #include "irgwalk.h"
19
20 #include "be.h"
21 #include "beabi.h"
22 #include "bearch.h"
23 #include "benode_t.h"
24 #include "besched_t.h"
25
26 #define MAX(x, y) ((x) > (y) ? (x) : (y))
27 #define MIN(x, y) ((x) < (y) ? (x) : (y))
28
29 typedef struct _be_abi_call_arg_t {
30         unsigned is_res : 1;
31         unsigned in_reg : 1;
32
33         int pos;
34         const arch_register_t *reg;
35 } be_abi_call_arg_t;
36
37 struct _be_abi_call_t {
38         be_abi_call_flags_t flags;
39         unsigned arg_gap;
40         set *params;
41 };
42
43 struct _be_abi_irg_t {
44         struct obstack      obst;
45         be_irg_t            *birg;
46         be_abi_call_t       *call;
47         type                *method_type;
48
49         ir_node             *init_sp;      /**< The node representing the stack pointer
50                                                                              at the start of the function. */
51
52         ir_node             *reg_params;
53
54         pset                *stack_ops;    /**< Contains all nodes modifying the stack pointer. */
55         pmap                *regs;
56
57         int start_block_bias;
58
59         unsigned omit_fp : 1;
60         unsigned dedicated_fp : 1;
61         unsigned left_to_right : 1;
62
63         firm_dbg_module_t *dbg;            /**< The debugging module. */
64 };
65
66 static int cmp_call_arg(const void *a, const void *b, size_t n)
67 {
68         const be_abi_call_arg_t *p = a, *q = b;
69         return !(p->is_res == q->is_res && p->pos == q->pos);
70 }
71
72 static be_abi_call_arg_t *get_or_set_call_arg(be_abi_call_t *call, int is_res, int pos, int do_insert)
73 {
74         be_abi_call_arg_t arg;
75         unsigned hash;
76
77         arg.is_res = is_res;
78         arg.pos    = pos;
79
80         hash = is_res * 100 + pos;
81
82         return do_insert
83                 ? set_insert(call->params, &arg, sizeof(arg), hash)
84                 : set_find(call->params, &arg, sizeof(arg), hash);
85 }
86
87 static INLINE be_abi_call_arg_t *get_call_arg(be_abi_call_t *call, int is_res, int pos)
88 {
89         return get_or_set_call_arg(call, is_res, pos, 0);
90 }
91
92 void be_abi_call_set_flags(be_abi_call_t *call, be_abi_call_flags_t flags, unsigned arg_gap)
93 {
94         call->flags   = flags;
95         call->arg_gap = arg_gap;
96 }
97
98 void be_abi_call_param_stack(be_abi_call_t *call, int arg_pos)
99 {
100         be_abi_call_arg_t *arg = get_or_set_call_arg(call, 0, arg_pos, 1);
101 }
102
103 void be_abi_call_param_reg(be_abi_call_t *call, int arg_pos, const arch_register_t *reg)
104 {
105         be_abi_call_arg_t *arg = get_or_set_call_arg(call, 0, arg_pos, 1);
106         arg->reg = reg;
107 }
108
109 void be_abi_call_res_reg(be_abi_call_t *call, int arg_pos, const arch_register_t *reg)
110 {
111         be_abi_call_arg_t *arg = get_or_set_call_arg(call, 1, arg_pos, 1);
112         arg->reg = reg;
113 }
114
115 be_abi_call_t *be_abi_call_new(void)
116 {
117         be_abi_call_t *call = malloc(sizeof(call[0]));
118         call->flags  = BE_ABI_NONE;
119         call->params = new_set(cmp_call_arg, 16);
120         return call;
121 }
122
123 void be_abi_call_free(be_abi_call_t *call)
124 {
125         del_set(call->params);
126         free(call);
127 }
128
129 static INLINE int is_on_stack(be_abi_call_t *call, int pos)
130 {
131         be_abi_call_arg_t *arg = get_call_arg(call, 0, pos);
132         return arg && !arg->in_reg;
133 }
134
135 static void adjust_call(be_abi_irg_t *env, ir_node *irn)
136 {
137         ir_graph *irg             = env->birg->irg;
138         const arch_isa_t *isa     = env->birg->main_env->arch_env->isa;
139         be_abi_call_t *call       = be_abi_call_new();
140         ir_type *mt               = get_Call_type(irn);
141         int n_params              = get_method_n_params(mt);
142         ir_node *curr_sp          = get_irg_frame(irg);
143         ir_node *curr_mem         = get_Call_mem(irn);
144         ir_node *bl               = get_nodes_block(irn);
145         pset *results             = pset_new_ptr(8);
146         pset *caller_save         = pset_new_ptr(8);
147         int stack_size            = 0;
148         int stack_dir             = arch_isa_stack_dir(isa);
149         const arch_register_t *sp = arch_isa_sp(isa);
150         ir_mode *mach_mode        = sp->reg_class->mode;
151         struct obstack *obst      = &env->obst;
152         ir_node *no_mem           = get_irg_no_mem(irg);
153
154         ir_node *res_proj = NULL;
155         int curr_res_proj = -1;
156         int n_low_args    = 0;
157         int n_pos         = 0;
158
159         ir_node *low_call;
160         ir_node **in;
161         ir_node *sp_proj;
162         const ir_edge_t *edge;
163         int *low_args;
164         int *pos;
165         int i, n;
166
167         /* Let the isa fill out the abi description for that call node. */
168         arch_isa_get_call_abi(isa, mt, call);
169
170         /* Insert code to put the stack arguments on the stack. */
171         for(i = get_irn_arity(irn); i >= 0; --i) {
172                 if(is_on_stack(call, i)) {
173                         stack_size += get_type_size_bytes(get_method_param_type(mt, i));
174                         obstack_int_grow(obst, i);
175                         n_pos++;
176                 }
177         }
178         pos = obstack_finish(obst);
179
180         /* Collect all arguments which are passed in registers. */
181         for(i = 0, n = get_irn_arity(irn); i < n; ++i) {
182                 be_abi_call_arg_t *arg = get_call_arg(call, 0, i);
183                 if(arg && arg->in_reg) {
184                         obstack_int_grow(obst, i);
185                         n_low_args++;
186                 }
187         }
188         low_args = obstack_finish(obst);
189
190         /* If there are some parameters which shall be passed on the stack. */
191         if(n_pos > 0) {
192                 int curr_ofs      = 0;
193                 int do_seq        = (call->flags & BE_ABI_USE_PUSH);
194
195                 /* Reverse list of stack parameters if call arguments are from left to right */
196                 if(call->flags & BE_ABI_LEFT_TO_RIGHT) {
197                         for(i = 0; i < n_pos / 2; ++i) {
198                                 int other  = n_pos - i - 1;
199                                 int tmp    = pos[i];
200                                 pos[i]     = pos[other];
201                                 pos[other] = tmp;
202                         }
203                 }
204
205                 /*
206                  * If the stack is decreasing and we do not want to store sequentially,
207                  * we allocate as much space on the stack all parameters need, by
208                  * moving the stack pointer along the stack's direction.
209                  */
210                 if(stack_dir < 0 && !do_seq) {
211                         curr_sp = be_new_IncSP(sp, irg, bl, curr_sp, no_mem, stack_size, be_stack_dir_along);
212                         pset_insert_ptr(env->stack_ops, curr_sp);
213                 }
214
215                 assert(mode_is_reference(mach_mode) && "machine mode must be pointer");
216                 for(i = 0; i < n_pos; ++i) {
217                         int p            = pos[i];
218                         ir_node *param   = get_irn_n(irn, p);
219                         ir_node *addr    = curr_sp;
220                         ir_node *mem     = NULL;
221                         type *param_type = get_method_param_type(mt, p);
222                         int param_size   = get_type_size_bytes(param_type);
223
224                         /* Make the expression to compute the argument's offset. */
225                         if(curr_ofs > 0) {
226                                 addr = new_r_Const_long(irg, bl, mode_Is, curr_ofs);
227                                 addr = new_r_Add(irg, bl, curr_sp, addr, mach_mode);
228                         }
229
230                         /* Insert a store for primitive arguments. */
231                         if(is_atomic_type(param_type)) {
232                                 mem = new_r_Store(irg, bl, curr_mem, addr, param);
233                                 mem = new_r_Proj(irg, bl, mem, mode_M, pn_Store_M);
234                         }
235
236                         /* Make a memcopy for compound arguments. */
237                         else {
238                                 assert(mode_is_reference(get_irn_mode(param)));
239                                 mem = new_r_CopyB(irg, bl, curr_mem, addr, param, param_type);
240                                 mem = new_r_Proj(irg, bl, mem, mode_M, pn_CopyB_M_regular);
241                         }
242
243                         obstack_ptr_grow(obst, mem);
244
245                         curr_ofs += param_size;
246
247                         /*
248                         * If we wanted to build the arguments sequentially,
249                         * the stack pointer for the next must be incremented,
250                         * and the memory value propagated.
251                         */
252                         if(do_seq) {
253                                 curr_ofs = 0;
254                                 curr_sp  = be_new_IncSP(sp, irg, bl, curr_sp, no_mem, param_size, be_stack_dir_along);
255                                 curr_mem = mem;
256
257                                 /*
258                                  * only put the first IncSP to the stack fixup set since the other
259                                  * ones are correctly connected to other nodes and do not need
260                                  * to be fixed.
261                                  */
262                                 if(i == 0)
263                                         pset_insert_ptr(env->stack_ops, curr_sp);
264                         }
265                 }
266
267                 in = (ir_node **) obstack_finish(obst);
268
269                 /* We need the sync only, if we didn't build the stores sequentially. */
270                 if(!do_seq)
271                         curr_mem = new_r_Sync(irg, bl, n_pos, in);
272                 obstack_free(obst, in);
273         }
274
275         /* Collect caller save registers */
276         for(i = 0; env->birg->main_env->caller_save[i]; ++i)
277                 pset_insert_ptr(caller_save, env->birg->main_env->caller_save[i]);
278
279         /* search the greatest result proj number */
280         foreach_out_edge(irn, edge) {
281                 const ir_edge_t *res_edge;
282                 ir_node *irn = get_edge_src_irn(edge);
283
284                 if(is_Proj(irn) && get_irn_mode(irn) == mode_T) {
285                         res_proj = irn;
286                         foreach_out_edge(irn, res_edge) {
287                                 int proj;
288                                 be_abi_call_arg_t *arg;
289                                 ir_node *res = get_edge_src_irn(res_edge);
290
291                                 assert(is_Proj(res));
292                                 proj = get_Proj_proj(res);
293                                 arg = get_call_arg(call, 1, proj);
294                                 if(proj > curr_res_proj)
295                                         curr_res_proj = proj;
296                                 if(arg->in_reg)
297                                         pset_remove_ptr(caller_save, arg->reg);
298                         }
299                 }
300         }
301         curr_res_proj++;
302
303         /* Make additional projs for the caller save registers
304            and the Keep node which keeps them alive. */
305         if(pset_count(caller_save) > 0) {
306                 const arch_register_t *reg;
307                 ir_node **in;
308
309                 if(!res_proj)
310                         res_proj = new_r_Proj(irg, bl, irn, mode_T, pn_Call_T_result);
311
312                 for(reg = pset_first(caller_save); reg; reg = pset_next(caller_save))
313                         obstack_ptr_grow(obst, new_r_Proj(irg, bl, res_proj, reg->reg_class->mode, curr_res_proj++));
314
315                 in = (ir_node **) obstack_finish(obst);
316                 be_new_Keep(NULL, irg, bl, pset_count(caller_save), in);
317                 obstack_free(obst, in);
318         }
319
320         /* Clean up the stack. */
321         if(stack_size > 0) {
322                 ir_node *last_inc_sp;
323
324                 /* Get the result ProjT */
325                 if(!res_proj)
326                         res_proj = new_r_Proj(irg, bl, irn, mode_T, pn_Call_T_result);
327
328                 /* Make a Proj for the stack pointer. */
329                 sp_proj     = new_r_Proj(irg, bl, res_proj, sp->reg_class->mode, curr_res_proj++);
330                 last_inc_sp = be_new_IncSP(sp, irg, bl, sp_proj, no_mem, stack_size, be_stack_dir_against);
331                 pset_insert_ptr(env->stack_ops, last_inc_sp);
332         }
333
334         /* at last make the backend call node and set its register requirements. */
335         for(i = 0; i < n_low_args; ++i)
336                 obstack_ptr_grow(obst, get_irn_n(irn, low_args[i]));
337         in = obstack_finish(obst);
338         low_call = be_new_Call(irg, bl, curr_mem, curr_sp, get_Call_ptr(irn), curr_res_proj, n_low_args, in);
339         obstack_free(obst, in);
340
341         exchange(irn, low_call);
342
343         be_abi_call_free(call);
344         obstack_free(obst, pos);
345         del_pset(results);
346         del_pset(caller_save);
347 }
348
349 static void adjust_call_walker(ir_node *irn, void *data)
350 {
351         if(get_irn_opcode(irn) == iro_Call)
352                 adjust_call(data, irn);
353 }
354
355 /**
356  * Walker to implement alloca-style allocations.
357  * They are implemented using an add to the stack pointer
358  * and a copy instruction.
359  */
360 static void implement_stack_alloc(be_abi_irg_t *env, ir_node *irn)
361 {
362         const arch_isa_t *isa = env->birg->main_env->arch_env->isa;
363         ir_node *bl           = get_nodes_block(irn);
364         ir_node *res          = env->init_sp;
365         ir_node *size;
366
367         assert(get_irn_opcode(irn) == iro_Alloc && get_Alloc_where(irn) == stack_alloc);
368
369         size = get_Alloc_size(irn);
370         if(isa->stack_dir > 0)
371                 res = be_new_Copy(isa->sp->reg_class, env->birg->irg, bl, res);
372
373         res = be_new_AddSP(isa->sp, env->birg->irg, bl, res, size);
374         pset_insert_ptr(env->stack_ops, res);
375
376         if(isa->stack_dir < 0)
377                 res = be_new_Copy(isa->sp->reg_class, env->birg->irg, bl, res);
378
379 }
380
381 static void collect_return_walker(ir_node *irn, void *data)
382 {
383         if(get_irn_opcode(irn) == iro_Return) {
384                 struct obstack *obst = data;
385                 obstack_ptr_grow(obst, irn);
386         }
387 }
388
389 static ir_node *setup_frame(be_abi_irg_t *env)
390 {
391         const arch_isa_t *isa = env->birg->main_env->arch_env->isa;
392         const arch_register_t *sp = isa->sp;
393         const arch_register_t *bp = isa->bp;
394         ir_graph *irg      = env->birg->irg;
395         ir_node *bl        = get_irg_start_block(irg);
396         ir_node *no_mem    = get_irg_no_mem(irg);
397         ir_node *old_frame = get_irg_frame(irg);
398         int store_old_fp   = 1;
399         int omit_fp        = env->omit_fp;
400         ir_node *stack     = pmap_get(env->regs, (void *) sp);
401         ir_node *frame     = pmap_get(env->regs, (void *) bp);
402
403         int stack_nr       = get_Proj_proj(stack);
404
405         if(omit_fp) {
406                 stack = be_new_IncSP(sp, irg, bl, stack, no_mem, BE_STACK_FRAME_SIZE, be_stack_dir_along);
407                 frame = stack;
408         }
409
410         else {
411                 if(store_old_fp) {
412                         ir_node *irn;
413
414                         irn   = new_r_Store(irg, bl, get_irg_initial_mem(irg), stack, frame);
415                         irn   = new_r_Proj(irg, bl, irn, mode_M, pn_Store_M);
416                         stack = be_new_IncSP(sp, irg, bl, stack, irn, get_mode_size_bytes(bp->reg_class->mode), be_stack_dir_along);
417                 }
418
419                 frame = be_new_Copy(bp->reg_class, irg, bl, stack);
420
421                 if(env->dedicated_fp) {
422                         be_set_constr_single_reg(frame, -1, bp);
423                         be_node_set_flags(frame, -1, arch_irn_flags_ignore);
424                 }
425
426                 stack = be_new_IncSP(sp, irg, bl, stack, no_mem, BE_STACK_FRAME_SIZE, be_stack_dir_along);
427         }
428
429         be_node_set_flags(env->reg_params, -(stack_nr + 1), arch_irn_flags_ignore);
430         env->init_sp = stack;
431         set_irg_frame(irg, frame);
432         edges_reroute(old_frame, frame, irg);
433
434         return frame;
435 }
436
437 static ir_node *clearup_frame(be_abi_irg_t *env, ir_node *stack, ir_node *frame)
438 {
439
440 }
441
442 /**
443  * Modify the irg itself and the frame type.
444  */
445 static void modify_irg(be_abi_irg_t *env)
446 {
447         firm_dbg_module_t *dbg    = env->dbg;
448         be_abi_call_t *call       = be_abi_call_new();
449         const arch_isa_t *isa     = env->birg->main_env->arch_env->isa;
450         const arch_register_t *sp = arch_isa_sp(isa);
451         ir_graph *irg             = env->birg->irg;
452         ir_node *bl               = get_irg_start_block(irg);
453         ir_node *end              = get_irg_end_block(irg);
454         ir_node *arg_tuple        = get_irg_args(irg);
455         ir_node *no_mem           = get_irg_no_mem(irg);
456         type *method_type         = get_entity_type(get_irg_entity(irg));
457         int n_params              = get_method_n_params(method_type);
458
459         int max_arg               = 0;
460         int reg_params_nr         = 0;
461         int arg_offset            = 0;
462
463         int i, j, n;
464
465         ir_node *frame_pointer;
466         ir_node *reg_params, *reg_params_bl;
467         ir_node **args, **args_repl;
468         const ir_edge_t *edge;
469
470         pmap_entry *ent;
471
472         env->regs = pmap_create();
473
474         DBG((dbg, LEVEL_1, "introducing abi on %+F\n", irg));
475
476         /* Find the maximum proj number of the argument tuple proj */
477         foreach_out_edge(arg_tuple, edge)  {
478                 ir_node *irn = get_edge_src_irn(edge);
479                 int nr       = get_Proj_proj(irn);
480                 max_arg      = MAX(max_arg, nr);
481         }
482         max_arg += 1;
483         args      = obstack_alloc(&env->obst, max_arg * sizeof(args[0]));
484         args_repl = obstack_alloc(&env->obst, max_arg * sizeof(args[0]));
485         memset(args, 0, max_arg * sizeof(args[0]));
486         memset(args_repl, 0, max_arg * sizeof(args[0]));
487
488         /* Fill the argument vector */
489         foreach_out_edge(arg_tuple, edge) {
490                 ir_node *irn = get_edge_src_irn(edge);
491                 int nr       = get_Proj_proj(irn);
492                 args[nr]     = irn;
493                 DBG((dbg, LEVEL_2, "\treading arg: %d -> %+F\n", nr, irn));
494         }
495
496         /* Get the ABI constraints from the ISA */
497         arch_isa_get_call_abi(isa, method_type, call);
498
499         /* Count the register params and add them to the number of Projs for the RegParams node */
500         for(i = 0; i < n_params; ++i) {
501                 be_abi_call_arg_t *arg = get_call_arg(call, 0, i);
502                 if(arg->in_reg) {
503                         assert(arg->reg != sp && "cannot use stack pointer as parameter register");
504                         pmap_insert(env->regs, (void *) arg->reg, NULL);
505                         DBG((dbg, LEVEL_2, "\targ #%d -> reg %s\n", i, arg->reg->name));
506                 }
507         }
508
509         /* Collect all callee-save registers */
510         for(i = 0, n = arch_isa_get_n_reg_class(isa); i < n; ++i) {
511                 const arch_register_class_t *cls = arch_isa_get_reg_class(isa, i);
512                 for(j = 0; j < cls->n_regs; ++j) {
513                         const arch_register_t *reg = &cls->regs[j];
514                         if(arch_register_type_is(reg, callee_save))
515                                 pmap_insert(env->regs, (void *) reg, NULL);
516                 }
517         }
518
519         pmap_insert(env->regs, (void *) sp, NULL);
520         pmap_insert(env->regs, (void *) isa->bp, NULL);
521         reg_params_bl = get_irg_start_block(irg);
522         env->reg_params = reg_params = be_new_RegParams(irg, reg_params_bl, pmap_count(env->regs));
523         reg_params_nr = 0;
524
525         /*
526          * make proj nodes for the callee save registers.
527          * memorize them, since Return nodes get those as inputs.
528          */
529         for(ent = pmap_first(env->regs); ent; ent = pmap_next(env->regs)) {
530                 arch_register_t *reg = ent->key;
531                 int pos = -(reg_params_nr + 1);
532                 ent->value = new_r_Proj(irg, reg_params_bl, reg_params, reg->reg_class->mode, reg_params_nr);
533                 be_set_constr_single_reg(reg_params, pos, reg);
534
535                 /*
536                  * If the register is an ignore register,
537                  * The Proj for that register shall also be ignored during register allocation.
538                  */
539                 if(arch_register_type_is(reg, ignore))
540                         be_node_set_flags(reg_params, pos, arch_irn_flags_ignore);
541
542                 reg_params_nr++;
543
544                 DBG((dbg, LEVEL_2, "\tregister save proj #%d -> reg %s\n", reg_params_nr - 1, reg->name));
545         }
546
547         /* Insert the code to set up the stack frame */
548         frame_pointer = setup_frame(env);
549
550 #if 0
551         proj_sp = pmap_get(regs, (void *) sp);
552         proj_bp = pmap_get(regs, (void *) bp);
553         assert(proj_sp != NULL && "There must be a Proj for the stack pointer");
554         assert(proj_sp != NULL && "There must be a Proj for the base pointer");
555
556         /* Set the Proj for the stack pointer to ignore. */
557         be_node_set_flags(reg_params, -(get_Proj_proj(proj_sp) + 1), arch_irn_flags_ignore);
558
559         /*
560          * If a frame pointer is needed and the frame pointer is in a dedicated register,
561          * also exclude that from register allocation by setting the corresponding
562          * Proj to ignore.
563          */
564         if(!env->omit_fp && env->dedicated_fp)
565                 be_node_set_flags(reg_params, -(get_Proj_proj(proj_bp) + 1), arch_irn_flags_ignore);
566
567
568         if(env->omit_fp) {
569                 /* This is the stack pointer add/sub which allocates the frame. remind it for later fix up. */
570                 env->init_sp  = be_new_IncSP(sp, irg, reg_params_bl, proj_sp, no_mem, 0, be_stack_dir_along);
571                 frame_pointer = env->init_sp;
572         }
573
574         else {
575                 env->init_sp  = proj_sp;
576                 frame_pointer = be_new_Copy(sp->reg_class, irg, reg_params_bl, proj_sp);
577         }
578
579         /* Set the new frame pointer. */
580         exchange(get_irg_frame(irg), frame_pointer);
581         set_irg_frame(irg, frame_pointer);
582 #endif
583
584         /* compute the start offset for the stack parameters. */
585         {
586                 int arg_offset = 0;
587                 int arg_size   = 0;
588                 int inc_dir    = isa->stack_dir * (env->left_to_right ? 1 : -1);
589
590                 for(i = 0; i < n_params; ++i) {
591                         be_abi_call_arg_t *arg = get_call_arg(call, 0, i);
592                         if(!arg->in_reg)
593                                 arg_size += get_type_size_bytes(get_method_param_type(method_type, i));
594                 }
595
596                 arg_offset = -isa->stack_dir * call->arg_gap + env->left_to_right * arg_size;
597
598                 /* Now, introduce stack param nodes for all parameters passed on the stack */
599                 for(i = 0; i < max_arg; ++i) {
600                         ir_node *arg_proj = args[i];
601                         if(arg_proj != NULL) {
602                                 be_abi_call_arg_t *arg;
603                                 ir_type *param_type;
604                                 int nr = get_Proj_proj(arg_proj);
605
606                                 nr         = MIN(nr, n_params);
607                                 arg        = get_call_arg(call, 0, nr);
608                                 param_type = get_method_param_type(method_type, nr);
609
610                                 if(arg->in_reg) {
611                                         args_repl[i] = new_r_Proj(irg, reg_params_bl, reg_params, get_irn_mode(arg_proj), reg_params_nr);
612                                         be_set_constr_single_reg(reg_params, -(reg_params_nr + 1), arg->reg);
613                                         reg_params_nr++;
614                                 }
615
616                                 /* when the (stack) parameter is primitive, we insert a StackParam
617                                 node representing the load of that parameter */
618                                 else {
619                                         int size = get_type_size_bytes(param_type) * isa->stack_dir;
620
621                                         if(inc_dir < 0)
622                                                 arg_offset -= size;
623
624                                         if(is_atomic_type(param_type)) {
625                                                 ir_mode *mode                    = get_type_mode(param_type);
626                                                 const arch_register_class_t *cls = arch_isa_get_reg_class_for_mode(isa, mode);
627                                                 args_repl[i] = be_new_StackParam(cls, irg, reg_params_bl, mode, frame_pointer, arg_offset);
628                                         }
629
630                                         /* The stack parameter is not primitive (it is a struct or array),
631                                         we thus will create a node representing the parameter's address
632                                         on the stack. */
633                                         else {
634                                                 assert(0 && "struct parameters are not supported");
635                                         }
636
637                                         if(inc_dir > 0)
638                                                 arg_offset += size;
639                                 }
640                         }
641                 }
642         }
643
644         /* reroute the edges from the original argument projs to the RegParam ones. */
645         for(i = 0; i < max_arg; ++i) {
646                 if(args[i] != NULL) {
647                         assert(args_repl[i] != NULL);
648                         edges_reroute(args[i], args_repl[i], irg);
649                 }
650         }
651
652         /* All Return nodes hang on the End node, so look for them there. */
653         for(i = 0, n = get_irn_arity(end); i < n; ++i) {
654                 ir_node *irn = get_irn_n(end, i);
655
656                 if(get_irn_opcode(irn) == iro_Return) {
657                         ir_node *bl = get_nodes_block(irn);
658                         ir_node *ret;
659                         int i, n;
660                         ir_node **in;
661
662                         /* collect all arguments of the return */
663                         for(i = 0, n = get_irn_arity(irn); i < n; ++i)
664                                 obstack_ptr_grow(&env->obst, get_irn_n(irn, i));
665
666                         /* Add the Proj nodes representing the caller save registers. */
667                         for(ent = pmap_first(env->regs); ent; ent = pmap_next(env->regs), ++n) {
668                                 const arch_register_t *reg = ent->key;
669                                 ir_node *irn               = ent->value;
670
671                                 /*
672                                  * If the register is the stack pointer,
673                                  * add the fix up code. Either add the size of the stack
674                                  * frame if we omitted the frame pointer or move the
675                                  * frame pointer back to the stack register.
676                                  */
677                                 if(reg == sp) {
678                                         irn = be_new_IncSP(sp, irg, bl, frame_pointer, no_mem, env->omit_fp ? BE_STACK_FRAME_SIZE : 0, be_stack_dir_against);
679                                 }
680                                 obstack_ptr_grow(&env->obst, irn);
681                         }
682
683                         /* The in array for the new back end return is now ready. */
684                         in  = obstack_finish(&env->obst);
685                         ret = be_new_Return(irg, bl, n, in);
686                         edges_reroute(irn, ret, irg);
687                         obstack_free(&env->obst, in);
688                 }
689         }
690
691         obstack_free(&env->obst, args);
692         be_abi_call_free(call);
693 }
694
695 static void collect_alloca_walker(ir_node *irn, void *data)
696 {
697         be_abi_irg_t *env = data;
698         if(get_irn_opcode(irn) == iro_Alloc && get_Alloc_where(irn) == stack_alloc)
699                 obstack_ptr_grow(&env->obst, irn);
700 }
701
702 be_abi_irg_t *be_abi_introduce(be_irg_t *birg)
703 {
704         be_abi_irg_t *env = malloc(sizeof(env[0]));
705
706         int i;
707         ir_node **stack_allocs;
708
709         env->method_type   = get_entity_type(get_irg_entity(birg->irg));
710         env->call          = be_abi_call_new();
711         arch_isa_get_call_abi(birg->main_env->arch_env->isa, env->method_type, env->call);
712
713         env->omit_fp       = (env->call->flags & BE_ABI_TRY_OMIT_FRAME_POINTER) != 0;
714         env->dedicated_fp  = (env->call->flags & BE_ABI_FRAME_POINTER_DEDICATED) != 0;
715         env->left_to_right = (env->call->flags & BE_ABI_LEFT_TO_RIGHT) != 0;
716         env->birg          = birg;
717         env->stack_ops     = pset_new_ptr(32);
718         env->dbg           = firm_dbg_register("firm.be.abi");
719         obstack_init(&env->obst);
720
721         /* search for stack allocation nodes and record them */
722         irg_walk_graph(env->birg->irg, collect_alloca_walker, NULL, env);
723         obstack_ptr_grow(&env->obst, NULL);
724         stack_allocs = obstack_finish(&env->obst);
725
726         /* If there are stack allocations in the irg, we need a frame pointer */
727         if(stack_allocs[0] != NULL)
728                 env->omit_fp = 0;
729
730         modify_irg(env);
731
732         for(i = 0; stack_allocs[i] != NULL; ++i)
733                 implement_stack_alloc(env, stack_allocs[i]);
734
735         irg_walk_graph(env->birg->irg, NULL, adjust_call_walker, env);
736         return env;
737 }
738
739 static void collect_stack_nodes(ir_node *irn, void *data)
740 {
741         pset *s = data;
742
743         switch(be_get_irn_opcode(irn)) {
744         case beo_IncSP:
745         case beo_AddSP:
746                 pset_insert_ptr(s, irn);
747         }
748 }
749
750 void be_abi_fix_stack_nodes(be_abi_irg_t *env)
751 {
752         dom_front_info_t *df;
753         pset *stack_ops;
754
755         /* We need dominance frontiers for fix up */
756         df = be_compute_dominance_frontiers(env->birg->irg);
757
758         stack_ops = pset_new_ptr_default();
759         pset_insert_ptr(env->stack_ops, env->init_sp);
760         irg_walk_graph(env->birg->irg, collect_stack_nodes, NULL, stack_ops);
761         be_ssa_constr_set(df, stack_ops);
762         del_pset(stack_ops);
763
764         /* free these dominance frontiers */
765         be_free_dominance_frontiers(df);
766 }
767
768 static int get_dir(ir_node *irn)
769 {
770         return 1 - 2 * (be_get_IncSP_direction(irn) == be_stack_dir_against);
771 }
772
773 static int process_stack_bias(be_abi_irg_t *env, ir_node *bl, int bias)
774 {
775         const arch_env_t *aenv = env->birg->main_env->arch_env;
776         ir_node *irn;
777         int start_bias = bias;
778
779         sched_foreach(bl, irn) {
780                 if(be_is_IncSP(irn)) {
781                         int ofs = be_get_IncSP_offset(irn);
782                         int dir = get_dir(irn);
783
784                         if(ofs == BE_STACK_FRAME_SIZE) {
785                                 ofs = get_type_size_bytes(get_irg_frame_type(env->birg->irg));
786                                 be_set_IncSP_offset(irn, ofs);
787                         }
788
789                         bias += dir * ofs;
790                 }
791
792                 else
793                         arch_set_stack_bias(aenv, irn, bias);
794         }
795
796         return bias;
797 }
798
799 static void stack_bias_walker(ir_node *bl, void *data)
800 {
801         if(bl != get_irg_start_block(get_irn_irg(bl))) {
802                 be_abi_irg_t *env = data;
803                 process_stack_bias(env, bl, env->start_block_bias);
804         }
805 }
806
807 void be_abi_fix_stack_bias(be_abi_irg_t *env)
808 {
809         ir_graph *irg  = env->birg->irg;
810
811         /* Determine the stack bias at the and of the start block. */
812         env->start_block_bias = process_stack_bias(env, get_irg_start_block(irg), 0);
813
814         /* fix the bias is all other blocks */
815         irg_block_walk_graph(irg, stack_bias_walker, NULL, env);
816 }
817
818 void be_abi_free(be_abi_irg_t *env)
819 {
820         del_pset(env->stack_ops);
821         obstack_free(&env->obst, NULL);
822         free(env);
823 }
824
825 ir_node *be_abi_get_callee_save_node(be_abi_irg_t *abi, const arch_register_t *reg)
826 {
827         assert(arch_register_type_is(reg, callee_save));
828         assert(pmap_contains(abi->regs, (void *) reg));
829         return pmap_get(abi->regs, (void *) reg);
830 }