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