5f4a84865f4aa58d800e6370c4040c0267a9d26f
[libfirm] / ir / be / benode.c
1 /**
2  * @file   benode.c
3  * @date   17.05.2005
4  * @author Sebastian Hack
5  *
6  * Backend node support.
7  *
8  * This file provdies Perm, Copy, Spill and Reload nodes.
9  *
10  * Copyright (C) 2005 Universitaet Karlsruhe
11  * Released under the GPL
12  */
13
14 #ifdef HAVE_CONFIG_H
15 #include "config.h"
16 #endif
17
18 #include <stdlib.h>
19
20 #include "obst.h"
21 #include "set.h"
22 #include "pmap.h"
23 #include "util.h"
24 #include "debug.h"
25 #include "fourcc.h"
26 #include "bitfiddle.h"
27
28 #include "irop_t.h"
29 #include "irmode_t.h"
30 #include "irnode_t.h"
31 #include "ircons_t.h"
32 #include "irprintf.h"
33
34 #include "be_t.h"
35 #include "belive_t.h"
36 #include "besched_t.h"
37 #include "benode_t.h"
38
39 #include "beirgmod.h"
40
41 #define OUT_POS(x) (-((x) + 1))
42
43 /* Sometimes we want to put const nodes into get_irn_generic_attr ... */
44 #define get_irn_attr(irn) get_irn_generic_attr((ir_node *) (irn))
45
46 static unsigned be_node_tag = FOURCC('B', 'E', 'N', 'O');
47
48 #if 0
49 typedef enum _node_kind_t {
50         node_kind_spill,
51         node_kind_reload,
52         node_kind_perm,
53         node_kind_copy,
54         node_kind_kill,
55         node_kind_last
56 } node_kind_t;
57 #endif
58
59 typedef enum {
60         be_req_kind_old_limited,
61         be_req_kind_negate_old_limited,
62         be_req_kind_single_reg
63 } be_req_kind_t;
64
65 typedef struct {
66         arch_register_req_t req;
67         be_req_kind_t       kind;
68         arch_irn_flags_t    flags;
69         union {
70                 struct {
71                         void (*old_limited)(void *ptr, bitset_t *bs);
72                         void *old_limited_env;
73                 } old_limited;
74
75                 const arch_register_t *single_reg;
76         } x;
77 } be_req_t;
78
79 typedef struct {
80         const arch_register_t *reg;
81         be_req_t              req;
82         be_req_t              in_req;
83 } be_reg_data_t;
84
85 typedef struct {
86         int                         max_reg_data;
87         be_reg_data_t               *reg_data;
88 } be_node_attr_t;
89
90 typedef struct {
91         be_node_attr_t node_attr;
92         int offset;           /**< The offset by which the stack shall be increased/decreased. */
93         be_stack_dir_t dir;   /**< The direction in which the stack shall be modified (along or in the other direction). */
94 } be_stack_attr_t;
95
96 typedef struct {
97         be_node_attr_t node_attr;
98         entity *ent;
99         int offset;
100 } be_frame_attr_t;
101
102 typedef struct {
103         be_frame_attr_t frame_attr;
104         ir_node *spill_ctx;  /**< The node in whose context this spill was introduced. */
105 } be_spill_attr_t;
106
107 static ir_op *op_Spill;
108 static ir_op *op_Reload;
109 static ir_op *op_Perm;
110 static ir_op *op_Copy;
111 static ir_op *op_Keep;
112 static ir_op *op_Call;
113 static ir_op *op_Return;
114 static ir_op *op_IncSP;
115 static ir_op *op_AddSP;
116 static ir_op *op_SetSP;
117 static ir_op *op_RegParams;
118 static ir_op *op_StackParam;
119 static ir_op *op_FrameAddr;
120 static ir_op *op_FrameLoad;
121 static ir_op *op_FrameStore;
122
123 static int beo_base = -1;
124
125 static const ir_op_ops be_node_op_ops;
126
127 #define N   irop_flag_none
128 #define L   irop_flag_labeled
129 #define C   irop_flag_commutative
130 #define X   irop_flag_cfopcode
131 #define I   irop_flag_ip_cfopcode
132 #define F   irop_flag_fragile
133 #define Y   irop_flag_forking
134 #define H   irop_flag_highlevel
135 #define c   irop_flag_constlike
136 #define K   irop_flag_keep
137
138 void be_node_init(void) {
139         static int inited = 0;
140
141         if(inited)
142                 return;
143
144         inited = 1;
145
146         /* Acquire all needed opcodes. */
147         beo_base = get_next_ir_opcodes(beo_Last - 1);
148
149         op_Spill      = new_ir_op(beo_base + beo_Spill,      "Spill",      op_pin_state_mem_pinned, N, oparity_unary,    0, sizeof(be_spill_attr_t), &be_node_op_ops);
150         op_Reload     = new_ir_op(beo_base + beo_Reload,     "Reload",     op_pin_state_mem_pinned, N, oparity_zero,     0, sizeof(be_node_attr_t),  &be_node_op_ops);
151         op_Perm       = new_ir_op(beo_base + beo_Perm,       "Perm",       op_pin_state_pinned,     N, oparity_variable, 0, sizeof(be_node_attr_t),  &be_node_op_ops);
152         op_Copy       = new_ir_op(beo_base + beo_Copy,       "Copy",       op_pin_state_floats,     N, oparity_unary,    0, sizeof(be_node_attr_t),  &be_node_op_ops);
153         op_Keep       = new_ir_op(beo_base + beo_Keep,       "Keep",       op_pin_state_pinned,     K, oparity_variable, 0, sizeof(be_node_attr_t),  &be_node_op_ops);
154         op_Call       = new_ir_op(beo_base + beo_Call,       "Call",       op_pin_state_pinned,     N, oparity_variable, 0, sizeof(be_node_attr_t),  &be_node_op_ops);
155         op_Return     = new_ir_op(beo_base + beo_Return,     "Return",     op_pin_state_pinned,     X, oparity_variable, 0, sizeof(be_node_attr_t),  &be_node_op_ops);
156         op_AddSP      = new_ir_op(beo_base + beo_AddSP,      "AddSP",      op_pin_state_pinned,     N, oparity_unary,    0, sizeof(be_stack_attr_t), &be_node_op_ops);
157         op_SetSP      = new_ir_op(beo_base + beo_SetSP,      "SetSP",      op_pin_state_pinned,     N, oparity_binary,   0, sizeof(be_stack_attr_t), &be_node_op_ops);
158         op_IncSP      = new_ir_op(beo_base + beo_IncSP,      "IncSP",      op_pin_state_pinned,     N, oparity_binary,   0, sizeof(be_stack_attr_t), &be_node_op_ops);
159         op_RegParams  = new_ir_op(beo_base + beo_RegParams,  "RegParams",  op_pin_state_pinned,     N, oparity_zero,     0, sizeof(be_node_attr_t),  &be_node_op_ops);
160         op_StackParam = new_ir_op(beo_base + beo_StackParam, "StackParam", op_pin_state_pinned,     N, oparity_unary,    0, sizeof(be_frame_attr_t), &be_node_op_ops);
161         op_FrameAddr  = new_ir_op(beo_base + beo_FrameAddr,  "FrameAddr",  op_pin_state_pinned,     N, oparity_binary,   0, sizeof(be_frame_attr_t), &be_node_op_ops);
162         op_FrameLoad  = new_ir_op(beo_base + beo_FrameLoad,  "FrameLoad",  op_pin_state_pinned,     N, oparity_any,      0, sizeof(be_frame_attr_t), &be_node_op_ops);
163         op_FrameStore = new_ir_op(beo_base + beo_FrameStore, "FrameStore", op_pin_state_pinned,     N, oparity_any,      0, sizeof(be_frame_attr_t), &be_node_op_ops);
164
165         set_op_tag(op_Spill,      &be_node_tag);
166         set_op_tag(op_Reload,     &be_node_tag);
167         set_op_tag(op_Perm,       &be_node_tag);
168         set_op_tag(op_Copy,       &be_node_tag);
169         set_op_tag(op_Keep,       &be_node_tag);
170         set_op_tag(op_Call,       &be_node_tag);
171         set_op_tag(op_Return,     &be_node_tag);
172         set_op_tag(op_AddSP,      &be_node_tag);
173         set_op_tag(op_SetSP,      &be_node_tag);
174         set_op_tag(op_IncSP,      &be_node_tag);
175         set_op_tag(op_RegParams,  &be_node_tag);
176         set_op_tag(op_StackParam, &be_node_tag);
177         set_op_tag(op_FrameLoad,  &be_node_tag);
178         set_op_tag(op_FrameStore, &be_node_tag);
179         set_op_tag(op_FrameAddr,  &be_node_tag);
180 }
181
182 static void *init_node_attr(ir_node* irn, int max_reg_data)
183 {
184         ir_graph *irg     = get_irn_irg(irn);
185         be_node_attr_t *a = get_irn_attr(irn);
186
187         a->max_reg_data = max_reg_data;
188         a->reg_data     = NULL;
189
190         if(max_reg_data > 0) {
191                 int i;
192
193                 a->reg_data = NEW_ARR_D(be_reg_data_t, get_irg_obstack(irg), max_reg_data);
194                 memset(a->reg_data, 0, max_reg_data * sizeof(a->reg_data[0]));
195                 for(i = 0; i < max_reg_data; ++i) {
196                         a->reg_data[i].req.req.cls  = NULL;
197                         a->reg_data[i].req.req.type = arch_register_req_type_none;
198                 }
199         }
200
201         return a;
202 }
203
204 static INLINE int is_be_node(const ir_node *irn)
205 {
206         return get_op_tag(get_irn_op(irn)) == &be_node_tag;
207 }
208
209 be_opcode_t be_get_irn_opcode(const ir_node *irn)
210 {
211         return is_be_node(irn) ? get_irn_opcode(irn) - beo_base : beo_NoBeOp;
212 }
213
214 static int redir_proj(const ir_node **node, int pos)
215 {
216         const ir_node *n = *node;
217
218         if(is_Proj(n)) {
219                 assert(pos == -1 && "Illegal pos for a Proj");
220                 *node = get_Proj_pred(n);
221                 return get_Proj_proj(n);
222         }
223
224         return 0;
225 }
226
227 static void
228 be_node_set_irn_reg(const void *_self, ir_node *irn, const arch_register_t *reg)
229 {
230         int out_pos;
231         be_node_attr_t *a;
232
233         out_pos = redir_proj((const ir_node **) &irn, -1);
234         a       = get_irn_attr(irn);
235
236         assert(is_be_node(irn));
237         assert(out_pos < a->max_reg_data && "position too high");
238         a->reg_data[out_pos].reg = reg;
239 }
240
241
242 ir_node *be_new_Spill(const arch_register_class_t *cls, const arch_register_class_t *cls_frame, ir_graph *irg, ir_node *bl, ir_node *frame, ir_node *to_spill, ir_node *ctx)
243 {
244         be_spill_attr_t *a;
245         ir_node *in[2];
246         ir_node *res;
247
248         in[0] = frame;
249         in[1] = to_spill;
250         res   = new_ir_node(NULL, irg, bl, op_Spill, mode_M, 2, in);
251         a     = init_node_attr(res, 2);
252         a->frame_attr.ent = NULL;
253         a->frame_attr.offset = 0;
254         a->spill_ctx = ctx;
255
256         be_node_set_reg_class(res, 0, cls_frame);
257         be_node_set_reg_class(res, 1, cls);
258         return res;
259 }
260
261 ir_node *be_new_Reload(const arch_register_class_t *cls, const arch_register_class_t *cls_frame, ir_graph *irg, ir_node *bl, ir_node *frame, ir_node *mem, ir_mode *mode)
262 {
263         ir_node *in[2];
264         ir_node *res;
265
266         in[0] = frame;
267         in[1] = mem;
268         res   = new_ir_node(NULL, irg, bl, op_Reload, mode, 2, in);
269         init_node_attr(res, 2);
270         be_node_set_reg_class(res, 0, cls_frame);
271         be_node_set_reg_class(res, -1, cls);
272         return res;
273 }
274
275 ir_node *(be_get_Reload_mem)(const ir_node *irn)
276 {
277         assert(be_is_Reload(irn));
278         return get_irn_n(irn, 1);
279 }
280
281 ir_node *be_new_Perm(const arch_register_class_t *cls, ir_graph *irg, ir_node *bl, int n, ir_node *in[])
282 {
283         int i;
284         ir_node *irn = new_ir_node(NULL, irg, bl, op_Perm, mode_T, n, in);
285         init_node_attr(irn, n);
286         for(i = 0; i < n; ++i) {
287                 be_node_set_reg_class(irn, i, cls);
288                 be_node_set_reg_class(irn, OUT_POS(i), cls);
289         }
290
291         return irn;
292 }
293
294 ir_node *be_new_Copy(const arch_register_class_t *cls, ir_graph *irg, ir_node *bl, ir_node *op)
295 {
296         ir_node *in[1];
297         ir_node *res;
298
299         in[0] = op;
300         res   = new_ir_node(NULL, irg, bl, op_Copy, get_irn_mode(op), 1, in);
301         init_node_attr(res, 1);
302         be_node_set_reg_class(res, 0, cls);
303         be_node_set_reg_class(res, OUT_POS(0), cls);
304         return res;
305 }
306
307 ir_node *be_new_Keep(const arch_register_class_t *cls, ir_graph *irg, ir_node *bl, int n, ir_node *in[])
308 {
309         int i;
310         ir_node *irn;
311
312         irn = new_ir_node(NULL, irg, bl, op_Keep, mode_ANY, n, in);
313         init_node_attr(irn, n);
314         for(i = 0; i < n; ++i) {
315                 be_node_set_reg_class(irn, i, cls);
316         }
317         keep_alive(irn);
318         return irn;
319 }
320
321 ir_node *be_new_Call(ir_graph *irg, ir_node *bl, ir_node *mem, ir_node *sp, ir_node *ptr, int n_outs, int n, ir_node *in[])
322 {
323         int real_n = 3 + n;
324         ir_node *irn;
325         ir_node **real_in;
326
327         real_in = malloc(sizeof(real_in[0]) * (real_n));
328
329         real_in[0] = mem;
330         real_in[1] = sp;
331         real_in[2] = ptr;
332         memcpy(&real_in[3], in, n * sizeof(in[0]));
333
334         irn = new_ir_node(NULL, irg, bl, op_Call, mode_T, real_n, real_in);
335         init_node_attr(irn, (n_outs > real_n ? n_outs : real_n));
336         return irn;
337 }
338
339 ir_node *be_new_Return(ir_graph *irg, ir_node *bl, int n, ir_node *in[])
340 {
341         ir_node *irn = new_ir_node(NULL, irg, bl, op_Return, mode_X, n, in);
342         init_node_attr(irn, n);
343
344         return irn;
345 }
346
347 ir_node *be_new_IncSP(const arch_register_t *sp, ir_graph *irg, ir_node *bl, ir_node *old_sp, ir_node *mem, unsigned offset, be_stack_dir_t dir)
348 {
349         be_stack_attr_t *a;
350         ir_node *irn;
351         ir_node *in[1];
352
353         in[0]     = old_sp;
354         in[1]     = mem;
355         irn       = new_ir_node(NULL, irg, bl, op_IncSP, sp->reg_class->mode, 2, in);
356         a         = init_node_attr(irn, 1);
357         a->dir    = dir;
358         a->offset = offset;
359
360         be_node_set_flags(irn, -1, arch_irn_flags_ignore);
361
362         /* Set output constraint to stack register. */
363         be_node_set_reg_class(irn, 0, sp->reg_class);
364         be_set_constr_single_reg(irn, -1, sp);
365         be_node_set_irn_reg(NULL, irn, sp);
366
367         return irn;
368 }
369
370 ir_node *be_new_AddSP(const arch_register_t *sp, ir_graph *irg, ir_node *bl, ir_node *old_sp, ir_node *op)
371 {
372         be_node_attr_t *a;
373         ir_node *irn;
374         ir_node *in[2];
375
376         in[0]    = old_sp;
377         in[1]    = op;
378         irn      = new_ir_node(NULL, irg, bl, op_AddSP, sp->reg_class->mode, 2, in);
379         a        = init_node_attr(irn, 1);
380
381         be_node_set_flags(irn, OUT_POS(0), arch_irn_flags_ignore);
382
383         /* Set output constraint to stack register. */
384         be_set_constr_single_reg(irn, OUT_POS(0), sp);
385         be_node_set_irn_reg(NULL, irn, sp);
386
387         return irn;
388 }
389
390 ir_node *be_new_SetSP(const arch_register_t *sp, ir_graph *irg, ir_node *bl, ir_node *old_sp, ir_node *op, ir_node *mem)
391 {
392         be_node_attr_t *a;
393         ir_node *irn;
394         ir_node *in[3];
395
396         in[0]    = mem;
397         in[1]    = old_sp;
398         in[2]    = op;
399         irn      = new_ir_node(NULL, irg, bl, op_SetSP, get_irn_mode(old_sp), 3, in);
400         a        = init_node_attr(irn, 3);
401
402         be_node_set_flags(irn, OUT_POS(0), arch_irn_flags_ignore);
403
404         /* Set output constraint to stack register. */
405         be_set_constr_single_reg(irn, OUT_POS(0), sp);
406         be_node_set_reg_class(irn, 1, sp->reg_class);
407         be_node_set_reg_class(irn, 2, sp->reg_class);
408         be_node_set_irn_reg(NULL, irn, sp);
409
410         return irn;
411 }
412
413 ir_node *be_new_StackParam(const arch_register_class_t *cls, const arch_register_class_t *cls_frame, ir_graph *irg, ir_node *bl, ir_mode *mode, ir_node *frame_pointer, entity *ent)
414 {
415         be_frame_attr_t *a;
416         ir_node *irn;
417         ir_node *in[1];
418
419         in[0] = frame_pointer;
420         irn = new_ir_node(NULL, irg, bl, op_StackParam, mode, 1, in);
421         a = init_node_attr(irn, 1);
422         a->ent = ent;
423
424         be_node_set_reg_class(irn, 0, cls_frame);
425         be_node_set_reg_class(irn, OUT_POS(0), cls);
426         return irn;
427 }
428
429 ir_node *be_new_RegParams(ir_graph *irg, ir_node *bl, int n_outs)
430 {
431         ir_node *irn;
432         ir_node *in[1];
433
434         irn = new_ir_node(NULL, irg, bl, op_RegParams, mode_T, 0, in);
435         init_node_attr(irn, n_outs);
436         return irn;
437 }
438
439 ir_node *be_new_FrameLoad(const arch_register_class_t *cls_frame, const arch_register_class_t *cls_data,
440                                                   ir_graph *irg, ir_node *bl, ir_node *mem, ir_node *frame, entity *ent)
441 {
442         be_frame_attr_t *a;
443         ir_node *irn;
444         ir_node *in[2];
445
446         in[0]  = mem;
447         in[1]  = frame;
448         irn    = new_ir_node(NULL, irg, bl, op_FrameLoad, mode_T, 2, in);
449         a      = init_node_attr(irn, 3);
450         a->ent = ent;
451         a->offset = 0;
452         be_node_set_reg_class(irn, 1, cls_frame);
453         be_node_set_reg_class(irn, OUT_POS(pn_Load_res), cls_data);
454         return irn;
455 }
456
457 ir_node *be_new_FrameStore(const arch_register_class_t *cls_frame, const arch_register_class_t *cls_data,
458                                                    ir_graph *irg, ir_node *bl, ir_node *mem, ir_node *frame, ir_node *data, entity *ent)
459 {
460         be_frame_attr_t *a;
461         ir_node *irn;
462         ir_node *in[3];
463
464         in[0]  = mem;
465         in[1]  = frame;
466         in[2]  = data;
467         irn    = new_ir_node(NULL, irg, bl, op_FrameStore, mode_T, 3, in);
468         a      = init_node_attr(irn, 3);
469         a->ent = ent;
470         a->offset = 0;
471         be_node_set_reg_class(irn, 1, cls_frame);
472         be_node_set_reg_class(irn, 2, cls_data);
473         return irn;
474 }
475
476 ir_node *be_new_FrameAddr(const arch_register_class_t *cls_frame, ir_graph *irg, ir_node *bl, ir_node *frame, entity *ent)
477 {
478         be_frame_attr_t *a;
479         ir_node *irn;
480         ir_node *in[1];
481
482         in[0]  = frame;
483         irn    = new_ir_node(NULL, irg, bl, op_FrameAddr, get_irn_mode(frame), 1, in);
484         a      = init_node_attr(irn, 1);
485         a->ent = ent;
486         a->offset = 0;
487         be_node_set_reg_class(irn, 0, cls_frame);
488         be_node_set_reg_class(irn, OUT_POS(0), cls_frame);
489         return irn;
490 }
491
492 int be_is_Spill         (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Spill          ; }
493 int be_is_Reload        (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Reload         ; }
494 int be_is_Copy          (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Copy           ; }
495 int be_is_Perm          (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Perm           ; }
496 int be_is_Keep          (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Keep           ; }
497 int be_is_Call          (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Call           ; }
498 int be_is_Return        (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Return         ; }
499 int be_is_IncSP         (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_IncSP          ; }
500 int be_is_SetSP         (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_SetSP          ; }
501 int be_is_AddSP         (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_AddSP          ; }
502 int be_is_RegParams     (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_RegParams      ; }
503 int be_is_StackParam    (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_StackParam     ; }
504 int be_is_FrameAddr     (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_FrameAddr      ; }
505 int be_is_FrameLoad     (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_FrameLoad      ; }
506 int be_is_FrameStore    (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_FrameStore     ; }
507
508 int be_has_frame_entity(const ir_node *irn)
509 {
510         switch(be_get_irn_opcode(irn)) {
511         case beo_StackParam:
512         case beo_Spill:
513         case beo_FrameStore:
514         case beo_FrameLoad:
515         case beo_FrameAddr:
516                 return 1;
517         }
518
519         return 0;
520 }
521
522 entity *be_get_frame_entity(const ir_node *irn)
523 {
524         if(be_has_frame_entity(irn)) {
525                 be_frame_attr_t *a = get_irn_attr(irn);
526                 return a->ent;
527         }
528
529         else if(be_get_irn_opcode(irn) == beo_Reload)
530                 return be_get_spill_entity(irn);
531
532         return NULL;
533 }
534
535 static void be_limited(void *data, bitset_t *bs)
536 {
537         be_req_t *req = data;
538
539         switch(req->kind) {
540         case be_req_kind_negate_old_limited:
541         case be_req_kind_old_limited:
542                 req->x.old_limited.old_limited(req->x.old_limited.old_limited_env, bs);
543                 if(req->kind == be_req_kind_negate_old_limited)
544                         bitset_flip_all(bs);
545                 break;
546         case be_req_kind_single_reg:
547                 bitset_clear_all(bs);
548                 bitset_set(bs, req->x.single_reg->index);
549                 break;
550         }
551 }
552
553 static INLINE be_req_t *get_req(ir_node *irn, int pos)
554 {
555         int idx           = pos < 0 ? -(pos + 1) : pos;
556         be_node_attr_t *a = get_irn_attr(irn);
557         be_reg_data_t *rd = &a->reg_data[idx];
558         be_req_t       *r = pos < 0 ? &rd->req : &rd->in_req;
559
560         assert(is_be_node(irn));
561         assert(!(pos >= 0) || pos < get_irn_arity(irn));
562         assert(!(pos < 0)  || -(pos + 1) <= a->max_reg_data);
563
564         return r;
565 }
566
567 void be_set_constr_single_reg(ir_node *irn, int pos, const arch_register_t *reg)
568 {
569         be_req_t *r = get_req(irn, pos);
570
571         r->kind            = be_req_kind_single_reg;
572         r->x.single_reg    = reg;
573         r->req.limited     = be_limited;
574         r->req.limited_env = r;
575         r->req.type        = arch_register_req_type_limited;
576         r->req.cls         = reg->reg_class;
577 }
578
579 void be_set_constr_limited(ir_node *irn, int pos, const arch_register_req_t *req)
580 {
581         be_req_t *r = get_req(irn, pos);
582
583         assert(arch_register_req_is(req, limited));
584
585         r->kind            = be_req_kind_old_limited;
586         r->req.limited     = be_limited;
587         r->req.limited_env = r;
588         r->req.type        = arch_register_req_type_limited;
589         r->req.cls         = req->cls;
590
591         r->x.old_limited.old_limited     = req->limited;
592         r->x.old_limited.old_limited_env = req->limited_env;
593 }
594
595 void be_node_set_flags(ir_node *irn, int pos, arch_irn_flags_t flags)
596 {
597         be_req_t *r = get_req(irn, pos);
598         r->flags = flags;
599 }
600
601 void be_node_set_reg_class(ir_node *irn, int pos, const arch_register_class_t *cls)
602 {
603         be_req_t *r = get_req(irn, pos);
604         r->req.cls = cls;
605         if(r->req.type == arch_register_req_type_none)
606                 r->req.type = arch_register_req_type_normal;
607 }
608
609 void be_set_IncSP_offset(ir_node *irn, unsigned offset)
610 {
611         be_stack_attr_t *a = get_irn_attr(irn);
612         assert(be_is_IncSP(irn));
613         a->offset = offset;
614 }
615
616 unsigned be_get_IncSP_offset(ir_node *irn)
617 {
618         be_stack_attr_t *a = get_irn_attr(irn);
619         assert(be_is_IncSP(irn));
620         return a->offset;
621 }
622
623 void be_set_IncSP_direction(ir_node *irn, be_stack_dir_t dir)
624 {
625         be_stack_attr_t *a = get_irn_attr(irn);
626         assert(be_is_IncSP(irn));
627         a->dir = dir;
628 }
629
630 be_stack_dir_t be_get_IncSP_direction(ir_node *irn)
631 {
632         be_stack_attr_t *a = get_irn_attr(irn);
633         assert(be_is_IncSP(irn));
634         return a->dir;
635 }
636
637 void be_set_Spill_entity(ir_node *irn, entity *ent)
638 {
639         be_spill_attr_t *a = get_irn_attr(irn);
640         assert(be_is_Spill(irn));
641         a->frame_attr.ent = ent;
642 }
643
644 static ir_node *find_a_spill_walker(ir_node *irn, unsigned visited_nr)
645 {
646         if(get_irn_visited(irn) < visited_nr) {
647                 set_irn_visited(irn, visited_nr);
648
649                 if(is_Phi(irn)) {
650                         int i, n;
651                         for(i = 0, n = get_irn_arity(irn); i < n; ++i) {
652                                 ir_node *n = find_a_spill_walker(get_irn_n(irn, i), visited_nr);
653                                 if(n != NULL)
654                                         return n;
655                         }
656                 }
657
658                 else if(be_get_irn_opcode(irn) == beo_Spill)
659                         return irn;
660         }
661
662         return NULL;
663 }
664
665 ir_node *be_get_Spill_context(const ir_node *irn) {
666         const be_spill_attr_t *a = get_irn_attr(irn);
667         assert(be_is_Spill(irn));
668         return a->spill_ctx;
669 }
670
671 /**
672  * Finds a spill for a reload.
673  * If the reload is directly using the spill, this is simple,
674  * else we perform DFS from the reload (over all PhiMs) and return
675  * the first spill node we find.
676  */
677 static INLINE ir_node *find_a_spill(const ir_node *irn)
678 {
679         ir_graph *irg       = get_irn_irg(irn);
680         unsigned visited_nr = get_irg_visited(irg) + 1;
681
682         assert(be_is_Reload(irn));
683         set_irg_visited(irg, visited_nr);
684         return find_a_spill_walker(be_get_Reload_mem(irn), visited_nr);
685 }
686
687 entity *be_get_spill_entity(const ir_node *irn)
688 {
689         int opc           = get_irn_opcode(irn);
690
691         switch(be_get_irn_opcode(irn)) {
692         case beo_Reload:
693                 return be_get_spill_entity(find_a_spill(irn));
694         case beo_Spill:
695                 {
696                         be_spill_attr_t *a = get_irn_attr(irn);
697                         return a->frame_attr.ent;
698                 }
699         default:
700                 assert(0 && "Must give spill/reload node");
701         }
702
703         return NULL;
704 }
705
706 ir_node *be_spill(const arch_env_t *arch_env, ir_node *irn, ir_node *ctx)
707 {
708         ir_node *bl    = get_nodes_block(irn);
709         ir_graph *irg  = get_irn_irg(bl);
710         ir_node *frame = get_irg_frame(irg);
711         ir_node *spill;
712         ir_node *insert;
713
714         const arch_register_class_t *cls       = arch_get_irn_reg_class(arch_env, irn, -1);
715         const arch_register_class_t *cls_frame = arch_get_irn_reg_class(arch_env, frame, -1);
716
717         spill = be_new_Spill(cls, cls_frame, irg, bl, frame, irn, ctx);
718
719         /*
720          * search the right insertion point. a spill of a phi cannot be put
721          * directly after the phi, if there are some phis behind the one which
722          * is spilled. Also, a spill of a Proj must be after all Projs of the
723          * same tuple node.
724          */
725         insert = sched_next(irn);
726         while((is_Phi(insert) || is_Proj(insert)) && !sched_is_end(insert))
727                 insert = sched_next(insert);
728
729         /*
730          * Here's one special case:
731          * If the spill is in the start block, the spill must be after the frame
732          * pointer is set up. This is checked here and fixed.
733          */
734         if(bl == get_irg_start_block(irg))
735                 insert = sched_next(frame);
736
737         sched_add_before(insert, spill);
738         return spill;
739 }
740
741 ir_node *be_reload(const arch_env_t *arch_env, const arch_register_class_t *cls, ir_node *reloader, ir_mode *mode, ir_node *spill)
742 {
743         ir_node *reload;
744
745         ir_node *bl    = get_nodes_block(reloader);
746         ir_graph *irg  = get_irn_irg(bl);
747         ir_node *frame = get_irg_frame(irg);
748         const arch_register_class_t *cls_frame = arch_get_irn_reg_class(arch_env, frame, -1);
749
750         assert(be_is_Spill(spill) || (is_Phi(spill) && get_irn_mode(spill) == mode_M));
751
752         reload = be_new_Reload(cls, cls_frame, irg, bl, frame, spill, mode);
753
754         sched_add_before(reloader, reload);
755         return reload;
756 }
757
758 static void *put_out_reg_req(arch_register_req_t *req, const ir_node *irn, int out_pos)
759 {
760         const be_node_attr_t *a = get_irn_attr(irn);
761
762         if(out_pos < a->max_reg_data)
763                 memcpy(req, &a->reg_data[out_pos].req, sizeof(req[0]));
764         else {
765                 req->type = arch_register_req_type_none;
766                 req->cls  = NULL;
767         }
768
769         return req;
770 }
771
772 static void *put_in_reg_req(arch_register_req_t *req, const ir_node *irn, int pos)
773 {
774         const be_node_attr_t *a = get_irn_attr(irn);
775         int n                   = get_irn_arity(irn);
776
777         if(pos < get_irn_arity(irn) && pos < a->max_reg_data)
778                 memcpy(req, &a->reg_data[pos].in_req, sizeof(req[0]));
779         else {
780                 req->type = arch_register_req_type_none;
781                 req->cls  = NULL;
782         }
783
784         return req;
785 }
786
787 static const arch_register_req_t *
788 be_node_get_irn_reg_req(const void *self, arch_register_req_t *req, const ir_node *irn, int pos)
789 {
790         int out_pos = pos;
791
792         if(pos < 0) {
793                 if(get_irn_mode(irn) == mode_T)
794                         return NULL;
795
796                 out_pos = redir_proj((const ir_node **) &irn, pos);
797                 assert(is_be_node(irn));
798                 return put_out_reg_req(req, irn, out_pos);
799         }
800
801         else {
802                 return is_be_node(irn) ? put_in_reg_req(req, irn, pos) : NULL;
803         }
804
805         return req;
806 }
807
808 const arch_register_t *
809 be_node_get_irn_reg(const void *_self, const ir_node *irn)
810 {
811         int out_pos;
812         be_node_attr_t *a;
813
814         out_pos = redir_proj((const ir_node **) &irn, -1);
815         a       = get_irn_attr(irn);
816
817         assert(is_be_node(irn));
818         assert(out_pos < a->max_reg_data && "position too high");
819
820         return a->reg_data[out_pos].reg;
821 }
822
823 static arch_irn_class_t be_node_classify(const void *_self, const ir_node *irn)
824 {
825         redir_proj((const ir_node **) &irn, -1);
826
827         switch(be_get_irn_opcode(irn)) {
828 #define XXX(a,b) case beo_ ## a: return arch_irn_class_ ## b;
829                 XXX(Spill, spill)
830                 XXX(Reload, reload)
831                 XXX(Perm, perm)
832                 XXX(Copy, copy)
833 #undef XXX
834                 default:
835                 return 0;
836         }
837
838         return 0;
839 }
840
841 static arch_irn_flags_t be_node_get_flags(const void *_self, const ir_node *irn)
842 {
843         int out_pos;
844         be_node_attr_t *a;
845
846         out_pos = redir_proj((const ir_node **) &irn, -1);
847         a       = get_irn_attr(irn);
848
849         assert(is_be_node(irn));
850         assert(out_pos < a->max_reg_data && "position too high");
851
852         return a->reg_data[out_pos].req.flags;
853 }
854
855 static entity *be_node_get_frame_entity(const void *self, const ir_node *irn)
856 {
857         return be_get_frame_entity(irn);
858 }
859
860 static void be_node_set_frame_offset(const void *self, ir_node *irn, int offset)
861 {
862         if(be_has_frame_entity(irn)) {
863                 be_frame_attr_t *a = get_irn_attr(irn);
864                 a->offset = offset;
865         }
866 }
867
868
869 static const arch_irn_ops_if_t be_node_irn_ops_if = {
870         be_node_get_irn_reg_req,
871         be_node_set_irn_reg,
872         be_node_get_irn_reg,
873         be_node_classify,
874         be_node_get_flags,
875         be_node_get_frame_entity,
876         be_node_set_frame_offset
877 };
878
879 static const arch_irn_ops_t be_node_irn_ops = {
880         &be_node_irn_ops_if
881 };
882
883 const void *be_node_get_arch_ops(const arch_irn_handler_t *self, const ir_node *irn)
884 {
885         redir_proj((const ir_node **) &irn, -1);
886         return is_be_node(irn) ? &be_node_irn_ops : NULL;
887 }
888
889 const arch_irn_handler_t be_node_irn_handler = {
890         be_node_get_arch_ops
891 };
892
893
894 static void dump_node_req(FILE *f, be_req_t *req)
895 {
896         unsigned i;
897         int did_something = 0;
898         const char *suffix = "";
899
900         if(req->flags != arch_irn_flags_none) {
901                 fprintf(f, "flags: ");
902                 for(i = arch_irn_flags_none; i <= log2_ceil(arch_irn_flags_last); ++i) {
903                         if(req->flags & (1 << i)) {
904                                 fprintf(f, "%s%s", suffix, arch_irn_flag_str(1 << i));
905                                 suffix = "|";
906                         }
907                 }
908                 suffix = ", ";
909                 did_something = 1;
910         }
911
912         if(req->req.cls != 0) {
913                 char tmp[256];
914                 fprintf(f, suffix);
915                 arch_register_req_format(tmp, sizeof(tmp), &req->req);
916                 fprintf(f, "%s", tmp);
917                 did_something = 1;
918         }
919
920         if(did_something)
921                 fprintf(f, "\n");
922 }
923
924 static void dump_node_reqs(FILE *f, ir_node *irn)
925 {
926         int i;
927         be_node_attr_t *a = get_irn_attr(irn);
928
929         fprintf(f, "registers: \n");
930         for(i = 0; i < a->max_reg_data; ++i) {
931                 be_reg_data_t *rd = &a->reg_data[i];
932                 if(rd->reg)
933                         fprintf(f, "#%d: %s\n", i, rd->reg->name);
934         }
935
936         fprintf(f, "in requirements\n");
937         for(i = 0; i < a->max_reg_data; ++i) {
938                 dump_node_req(f, &a->reg_data[i].in_req);
939         }
940
941         fprintf(f, "\nout requirements\n");
942         for(i = 0; i < a->max_reg_data; ++i) {
943                 dump_node_req(f, &a->reg_data[i].req);
944         }
945 }
946
947 static int dump_node(ir_node *irn, FILE *f, dump_reason_t reason)
948 {
949         be_node_attr_t *at = get_irn_attr(irn);
950
951         assert(is_be_node(irn));
952
953         switch(reason) {
954                 case dump_node_opcode_txt:
955                         fprintf(f, get_op_name(get_irn_op(irn)));
956                         break;
957                 case dump_node_mode_txt:
958                         fprintf(f, get_mode_name(get_irn_mode(irn)));
959                         break;
960                 case dump_node_nodeattr_txt:
961                         break;
962                 case dump_node_info_txt:
963                         dump_node_reqs(f, irn);
964
965                         if(be_has_frame_entity(irn)) {
966                                 be_frame_attr_t *a = (be_frame_attr_t *) at;
967                                 if (a->ent)
968                                         ir_fprintf(f, "frame entity: %+F offset %x (%d)\n", a->ent, a->offset, a->offset);
969
970                         }
971
972                         switch(be_get_irn_opcode(irn)) {
973                         case beo_Spill:
974                                 {
975                                         be_spill_attr_t *a = (be_spill_attr_t *) at;
976                                         ir_fprintf(f, "spill context: %+F\n", a->spill_ctx);
977                                 }
978                                 break;
979
980                         case beo_IncSP:
981                                 {
982                                         be_stack_attr_t *a = (be_stack_attr_t *) at;
983                                         fprintf(f, "offset: %u\n", a->offset);
984                                         fprintf(f, "direction: %s\n", a->dir == be_stack_dir_along ? "along" : "against");
985                                 }
986                                 break;
987                         }
988
989         }
990
991         return 0;
992 }
993
994 /**
995  * Copies the backend specific attributes from old node to new node.
996  */
997 static void copy_attr(const ir_node *old_node, ir_node *new_node)
998 {
999         be_node_attr_t *old_attr = get_irn_attr(old_node);
1000         be_node_attr_t *new_attr = get_irn_attr(new_node);
1001         int i;
1002
1003         assert(is_be_node(old_node));
1004         assert(is_be_node(new_node));
1005
1006         memcpy(new_attr, old_attr, get_op_attr_size(get_irn_op(old_node)));
1007         new_attr->reg_data = NULL;
1008
1009         if(new_attr->max_reg_data > 0) {
1010                 new_attr->reg_data = NEW_ARR_D(be_reg_data_t, get_irg_obstack(get_irn_irg(new_node)), new_attr->max_reg_data);
1011                 memcpy(new_attr->reg_data, old_attr->reg_data, new_attr->max_reg_data * sizeof(be_reg_data_t));
1012
1013                 for(i = 0; i < old_attr->max_reg_data; ++i) {
1014                         be_req_t *r;
1015
1016                         r = &new_attr->reg_data[i].req;
1017                         r->req.limited_env = r;
1018
1019                         r = &new_attr->reg_data[i].in_req;
1020                         r->req.limited_env = r;
1021                 }
1022         }
1023 }
1024
1025 static const ir_op_ops be_node_op_ops = {
1026         NULL,
1027         NULL,
1028         NULL,
1029         NULL,
1030         NULL,
1031         copy_attr,
1032         NULL,
1033         NULL,
1034         NULL,
1035         NULL,
1036         NULL,
1037         dump_node,
1038         NULL
1039 };
1040
1041 pset *nodes_live_at(const arch_env_t *arch_env, const arch_register_class_t *cls, const ir_node *pos, pset *live)
1042 {
1043         firm_dbg_module_t *dbg = firm_dbg_register("firm.be.node");
1044         const ir_node *bl      = is_Block(pos) ? pos : get_nodes_block(pos);
1045         ir_node *irn;
1046         irn_live_t *li;
1047
1048         live_foreach(bl, li) {
1049                 ir_node *irn = (ir_node *) li->irn;
1050                 if(live_is_end(li) && arch_irn_consider_in_reg_alloc(arch_env, cls, irn))
1051                         pset_insert_ptr(live, irn);
1052         }
1053
1054         sched_foreach_reverse(bl, irn) {
1055                 int i, n;
1056                 ir_node *x;
1057
1058                 /*
1059                  * If we encounter the node we want to insert the Perm after,
1060                 * exit immediately, so that this node is still live
1061                 */
1062                 if(irn == pos)
1063                         return live;
1064
1065                 DBG((dbg, LEVEL_1, "%+F\n", irn));
1066                 for(x = pset_first(live); x; x = pset_next(live))
1067                         DBG((dbg, LEVEL_1, "\tlive: %+F\n", x));
1068
1069                 if(arch_irn_consider_in_reg_alloc(arch_env, cls, irn))
1070                         pset_remove_ptr(live, irn);
1071
1072                 for(i = 0, n = get_irn_arity(irn); i < n; ++i) {
1073                         ir_node *op = get_irn_n(irn, i);
1074
1075                         if(arch_irn_consider_in_reg_alloc(arch_env, cls, op))
1076                                 pset_insert_ptr(live, op);
1077                 }
1078         }
1079
1080         return live;
1081 }
1082
1083 ir_node *insert_Perm_after(const arch_env_t *arch_env,
1084                                                    const arch_register_class_t *cls,
1085                                                    dom_front_info_t *dom_front,
1086                                                    ir_node *pos)
1087 {
1088         ir_node *bl                 = is_Block(pos) ? pos : get_nodes_block(pos);
1089         ir_graph *irg               = get_irn_irg(bl);
1090         pset *live                  = pset_new_ptr_default();
1091         firm_dbg_module_t *dbg      = firm_dbg_register("be.node");
1092
1093         ir_node *curr, *irn, *perm, **nodes;
1094         int i, n;
1095
1096         DBG((dbg, LEVEL_1, "Insert Perm after: %+F\n", pos));
1097
1098         if(!nodes_live_at(arch_env, cls, pos, live));
1099
1100         n = pset_count(live);
1101
1102         if(n == 0)
1103                 return NULL;
1104
1105         nodes = malloc(n * sizeof(nodes[0]));
1106
1107         DBG((dbg, LEVEL_1, "live:\n"));
1108         for(irn = pset_first(live), i = 0; irn; irn = pset_next(live), i++) {
1109                 DBG((dbg, LEVEL_1, "\t%+F\n", irn));
1110                 nodes[i] = irn;
1111         }
1112
1113         perm = be_new_Perm(cls, irg, bl, n, nodes);
1114         sched_add_after(pos, perm);
1115         free(nodes);
1116
1117         curr = perm;
1118         for(i = 0; i < n; ++i) {
1119                 ir_node *copies[2];
1120                 ir_node *perm_op = get_irn_n(perm, i);
1121                 const arch_register_t *reg = arch_get_irn_register(arch_env, perm_op);
1122
1123                 ir_mode *mode = get_irn_mode(perm_op);
1124                 ir_node *proj = new_r_Proj(irg, bl, perm, mode, i);
1125                 arch_set_irn_register(arch_env, proj, reg);
1126
1127                 sched_add_after(curr, proj);
1128                 curr = proj;
1129
1130                 copies[0] = perm_op;
1131                 copies[1] = proj;
1132                 be_ssa_constr(dom_front, 2, copies);
1133         }
1134         return perm;
1135 }