Updated for new architecture
[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 provides Perm, Copy, Spill and Reload nodes.
9  *
10  * Copyright (C) 2005-2006 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 "offset.h"
27 #include "bitfiddle.h"
28
29 #include "irop_t.h"
30 #include "irmode_t.h"
31 #include "irnode_t.h"
32 #include "ircons_t.h"
33 #include "irprintf.h"
34 #include "irgwalk.h"
35 #include "iropt_t.h"
36
37 #include "be_t.h"
38 #include "belive_t.h"
39 #include "besched_t.h"
40 #include "benode_t.h"
41
42 #include "beirgmod.h"
43
44 #define OUT_POS(x) (-((x) + 1))
45
46 /* Sometimes we want to put const nodes into get_irn_generic_attr ... */
47 #define get_irn_attr(irn) get_irn_generic_attr((ir_node *) (irn))
48
49 static unsigned be_node_tag = FOURCC('B', 'E', 'N', 'O');
50
51 typedef enum {
52         be_req_kind_old_limited,
53         be_req_kind_negate_old_limited,
54         be_req_kind_single_reg
55 } be_req_kind_t;
56
57 typedef struct {
58         arch_register_req_t req;
59         be_req_kind_t       kind;
60         arch_irn_flags_t    flags;
61         union {
62                 struct {
63                         void (*old_limited)(void *ptr, bitset_t *bs);
64                         void *old_limited_env;
65                 } old_limited;
66
67                 const arch_register_t *single_reg;
68         } x;
69 } be_req_t;
70
71 typedef struct {
72         const arch_register_t *reg;
73         be_req_t              req;
74         be_req_t              in_req;
75 } be_reg_data_t;
76
77 /** The generic be nodes attribute type. */
78 typedef struct {
79         int                   max_reg_data;
80         be_reg_data_t         *reg_data;
81 } be_node_attr_t;
82
83 /** The be_Return nodes attribute type. */
84 typedef struct {
85         be_node_attr_t node_attr;
86         int            num_ret_vals;  /**< number of return values */
87 } be_return_attr_t;
88
89 /** The be_Stack attribute type. */
90 typedef struct {
91         be_node_attr_t node_attr;
92         int offset;           /**< The offset by which the stack shall be expanded/shrinked. */
93 } be_stack_attr_t;
94
95 /** The be_Frame attribute type. */
96 typedef struct {
97         be_node_attr_t node_attr;
98         ir_entity *ent;
99         int offset;
100 } be_frame_attr_t;
101
102 /** The be_Call attribute type. */
103 typedef struct {
104         be_node_attr_t node_attr;
105         ir_entity *ent;      /**< The called entity if this is a static call. */
106         ir_type *call_tp;    /**< The call type, copied from the original Call node. */
107 } be_call_attr_t;
108
109 typedef struct {
110         be_node_attr_t node_attr;
111         ir_entity **in_entities;
112         ir_entity **out_entities;
113 } be_memperm_attr_t;
114
115 ir_op *op_be_Spill;
116 ir_op *op_be_Reload;
117 ir_op *op_be_Perm;
118 ir_op *op_be_MemPerm;
119 ir_op *op_be_Copy;
120 ir_op *op_be_Keep;
121 ir_op *op_be_CopyKeep;
122 ir_op *op_be_Call;
123 ir_op *op_be_Return;
124 ir_op *op_be_IncSP;
125 ir_op *op_be_AddSP;
126 ir_op *op_be_SubSP;
127 ir_op *op_be_SetSP;
128 ir_op *op_be_RegParams;
129 ir_op *op_be_StackParam;
130 ir_op *op_be_FrameAddr;
131 ir_op *op_be_FrameLoad;
132 ir_op *op_be_FrameStore;
133 ir_op *op_be_Barrier;
134
135 static int beo_base = -1;
136
137 static const ir_op_ops be_node_op_ops;
138
139 #define N   irop_flag_none
140 #define L   irop_flag_labeled
141 #define C   irop_flag_commutative
142 #define X   irop_flag_cfopcode
143 #define I   irop_flag_ip_cfopcode
144 #define F   irop_flag_fragile
145 #define Y   irop_flag_forking
146 #define H   irop_flag_highlevel
147 #define c   irop_flag_constlike
148 #define K   irop_flag_keep
149 #define M   irop_flag_machine
150
151
152 /**
153  * Compare two node attributes.
154  *
155  * @return zero if both attributes are identically
156  */
157 static int cmp_node_attr(be_node_attr_t *a, be_node_attr_t *b) {
158         if (a->max_reg_data == b->max_reg_data) {
159                 int i;
160
161                 for (i = 0; i < a->max_reg_data; ++i) {
162                         if (a->reg_data[i].reg    != b->reg_data[i].reg ||
163                             memcmp(&a->reg_data[i].in_req, &b->reg_data[i].in_req, sizeof(b->reg_data[i].in_req)) ||
164                             memcmp(&a->reg_data[i].req,    &b->reg_data[i].req,    sizeof(a->reg_data[i].req)))
165                                 return 1;
166                 }
167                 return 0;
168         }
169         return 1;
170 }
171
172 /**
173  * Compare the attributes of two FrameAddr nodes.
174  *
175  * @return zero if both attributes are identically
176  */
177 static int FrameAddr_cmp_attr(ir_node *a, ir_node *b) {
178         be_frame_attr_t *a_attr = get_irn_attr(a);
179         be_frame_attr_t *b_attr = get_irn_attr(b);
180
181         if (a_attr->ent == b_attr->ent && a_attr->offset == b_attr->offset)
182                 return cmp_node_attr(&a_attr->node_attr, &b_attr->node_attr);
183         return 1;
184 }
185
186 void be_node_init(void) {
187         static int inited = 0;
188
189         if(inited)
190                 return;
191
192         inited = 1;
193
194         /* Acquire all needed opcodes. */
195         beo_base = get_next_ir_opcodes(beo_Last - 1);
196
197         op_be_Spill      = new_ir_op(beo_base + beo_Spill,      "be_Spill",      op_pin_state_mem_pinned, N, oparity_unary,    0, sizeof(be_frame_attr_t),   &be_node_op_ops);
198         op_be_Reload     = new_ir_op(beo_base + beo_Reload,     "be_Reload",     op_pin_state_mem_pinned, N, oparity_zero,     0, sizeof(be_frame_attr_t),   &be_node_op_ops);
199         op_be_Perm       = new_ir_op(beo_base + beo_Perm,       "be_Perm",       op_pin_state_pinned,     N, oparity_variable, 0, sizeof(be_node_attr_t),    &be_node_op_ops);
200         op_be_MemPerm    = new_ir_op(beo_base + beo_MemPerm,    "be_MemPerm",    op_pin_state_mem_pinned, N, oparity_variable, 0, sizeof(be_memperm_attr_t), &be_node_op_ops);
201         op_be_Copy       = new_ir_op(beo_base + beo_Copy,       "be_Copy",       op_pin_state_floats,     N, oparity_unary,    0, sizeof(be_node_attr_t),    &be_node_op_ops);
202         op_be_Keep       = new_ir_op(beo_base + beo_Keep,       "be_Keep",       op_pin_state_pinned,     K, oparity_variable, 0, sizeof(be_node_attr_t),    &be_node_op_ops);
203         op_be_CopyKeep   = new_ir_op(beo_base + beo_CopyKeep,   "be_CopyKeep",   op_pin_state_pinned,     K, oparity_variable, 0, sizeof(be_node_attr_t),    &be_node_op_ops);
204         op_be_Call       = new_ir_op(beo_base + beo_Call,       "be_Call",       op_pin_state_pinned,     F, oparity_variable, 0, sizeof(be_call_attr_t),    &be_node_op_ops);
205         op_be_Return     = new_ir_op(beo_base + beo_Return,     "be_Return",     op_pin_state_pinned,     X, oparity_variable, 0, sizeof(be_return_attr_t),  &be_node_op_ops);
206         op_be_AddSP      = new_ir_op(beo_base + beo_AddSP,      "be_AddSP",      op_pin_state_pinned,     N, oparity_unary,    0, sizeof(be_node_attr_t),    &be_node_op_ops);
207         op_be_SubSP      = new_ir_op(beo_base + beo_SubSP,      "be_SubSP",      op_pin_state_pinned,     N, oparity_unary,    0, sizeof(be_node_attr_t),    &be_node_op_ops);
208         op_be_SetSP      = new_ir_op(beo_base + beo_SetSP,      "be_SetSP",      op_pin_state_pinned,     N, oparity_binary,   0, sizeof(be_stack_attr_t),   &be_node_op_ops);
209         op_be_IncSP      = new_ir_op(beo_base + beo_IncSP,      "be_IncSP",      op_pin_state_pinned,     N, oparity_binary,   0, sizeof(be_stack_attr_t),   &be_node_op_ops);
210         op_be_RegParams  = new_ir_op(beo_base + beo_RegParams,  "be_RegParams",  op_pin_state_pinned,     N, oparity_zero,     0, sizeof(be_node_attr_t),    &be_node_op_ops);
211         op_be_StackParam = new_ir_op(beo_base + beo_StackParam, "be_StackParam", op_pin_state_pinned,     N, oparity_unary,    0, sizeof(be_frame_attr_t),   &be_node_op_ops);
212         op_be_FrameAddr  = new_ir_op(beo_base + beo_FrameAddr,  "be_FrameAddr",  op_pin_state_pinned,     N, oparity_unary,    0, sizeof(be_frame_attr_t),   &be_node_op_ops);
213         op_be_FrameLoad  = new_ir_op(beo_base + beo_FrameLoad,  "be_FrameLoad",  op_pin_state_pinned,     N, oparity_any,      0, sizeof(be_frame_attr_t),   &be_node_op_ops);
214         op_be_FrameStore = new_ir_op(beo_base + beo_FrameStore, "be_FrameStore", op_pin_state_pinned,     N, oparity_any,      0, sizeof(be_frame_attr_t),   &be_node_op_ops);
215         op_be_Barrier    = new_ir_op(beo_base + beo_Barrier,    "be_Barrier",    op_pin_state_pinned,     N, oparity_any,      0, sizeof(be_node_attr_t),    &be_node_op_ops);
216
217         set_op_tag(op_be_Spill,      &be_node_tag);
218         set_op_tag(op_be_Reload,     &be_node_tag);
219         set_op_tag(op_be_Perm,       &be_node_tag);
220         set_op_tag(op_be_MemPerm,    &be_node_tag);
221         set_op_tag(op_be_Copy,       &be_node_tag);
222         set_op_tag(op_be_Keep,       &be_node_tag);
223         set_op_tag(op_be_CopyKeep,   &be_node_tag);
224         set_op_tag(op_be_Call,       &be_node_tag);
225         set_op_tag(op_be_Return,     &be_node_tag);
226         set_op_tag(op_be_AddSP,      &be_node_tag);
227         set_op_tag(op_be_SubSP,      &be_node_tag);
228         set_op_tag(op_be_SetSP,      &be_node_tag);
229         set_op_tag(op_be_IncSP,      &be_node_tag);
230         set_op_tag(op_be_RegParams,  &be_node_tag);
231         set_op_tag(op_be_StackParam, &be_node_tag);
232         set_op_tag(op_be_FrameLoad,  &be_node_tag);
233         set_op_tag(op_be_FrameStore, &be_node_tag);
234         set_op_tag(op_be_FrameAddr,  &be_node_tag);
235         set_op_tag(op_be_Barrier,    &be_node_tag);
236
237         op_be_FrameAddr->ops.node_cmp_attr = FrameAddr_cmp_attr;
238 }
239
240 /**
241  * Initializes the generic attribute of all be nodes and return ir.
242  */
243 static void *init_node_attr(ir_node* irn, int max_reg_data)
244 {
245         ir_graph *irg     = get_irn_irg(irn);
246         be_node_attr_t *a = get_irn_attr(irn);
247
248         memset(a, 0, sizeof(get_op_attr_size(get_irn_op(irn))));
249         a->max_reg_data = max_reg_data;
250         a->reg_data     = NULL;
251
252         if(max_reg_data > 0) {
253                 int i;
254
255                 a->reg_data = NEW_ARR_D(be_reg_data_t, get_irg_obstack(irg), max_reg_data);
256                 memset(a->reg_data, 0, max_reg_data * sizeof(a->reg_data[0]));
257                 for(i = 0; i < max_reg_data; ++i) {
258                         a->reg_data[i].req.req.cls  = NULL;
259                         a->reg_data[i].req.req.type = arch_register_req_type_none;
260                 }
261         }
262
263         return a;
264 }
265
266 int is_be_node(const ir_node *irn)
267 {
268         return get_op_tag(get_irn_op(irn)) == &be_node_tag;
269 }
270
271 be_opcode_t be_get_irn_opcode(const ir_node *irn)
272 {
273         return is_be_node(irn) ? get_irn_opcode(irn) - beo_base : beo_NoBeOp;
274 }
275
276 static int redir_proj(const ir_node **node, int pos)
277 {
278         const ir_node *n = *node;
279
280         if(is_Proj(n)) {
281                 ir_node *irn;
282
283                 *node = irn = get_Proj_pred(n);
284                 if(is_Proj(irn)) {
285                         assert(get_irn_mode(irn) == mode_T);
286                         *node = get_Proj_pred(irn);
287                 }
288                 return get_Proj_proj(n);
289         }
290
291         return 0;
292 }
293
294 static be_node_attr_t *retrieve_irn_attr(const ir_node *irn, int *the_pos)
295 {
296         int dummy;
297         be_node_attr_t *res = NULL;
298         int *pos = the_pos ? the_pos : &dummy;
299
300         *pos = -1;
301         if(is_Proj(irn)) {
302                 ir_node *pred = get_Proj_pred(irn);
303                 int p         = get_Proj_proj(irn);
304
305                 if(is_be_node(pred)) {
306                         assert(get_irn_mode(pred) == mode_T);
307                         *pos = p;
308                         res = get_irn_attr(pred);
309                         assert(p >= 0 && p < res->max_reg_data && "illegal proj number");
310                 }
311         }
312
313         else if(is_be_node(irn) && get_irn_mode(irn) != mode_T) {
314                 be_node_attr_t *a = get_irn_attr(irn);
315                 if(a->max_reg_data > 0) {
316                         res  = a;
317                         *pos = 0;
318                 }
319         }
320
321         return res;
322 }
323
324 static be_reg_data_t *retrieve_reg_data(const ir_node *irn)
325 {
326         int pos;
327         be_node_attr_t *a = retrieve_irn_attr(irn, &pos);
328         return a ? &a->reg_data[pos] : NULL;
329 }
330
331 static void
332 be_node_set_irn_reg(const void *_self, ir_node *irn, const arch_register_t *reg)
333 {
334         be_reg_data_t *r = retrieve_reg_data(irn);
335
336         if(r)
337                 r->reg = reg;
338 }
339
340
341 ir_node *be_new_Spill(const arch_register_class_t *cls, const arch_register_class_t *cls_frame,
342         ir_graph *irg, ir_node *bl, ir_node *frame, ir_node *to_spill)
343 {
344         be_frame_attr_t *a;
345         ir_node         *in[2];
346         ir_node         *res;
347
348         in[0]     = frame;
349         in[1]     = to_spill;
350         res       = new_ir_node(NULL, irg, bl, op_be_Spill, mode_M, 2, in);
351         a         = init_node_attr(res, 2);
352         a->ent    = NULL;
353         a->offset = 0;
354
355         be_node_set_reg_class(res, be_pos_Spill_frame, cls_frame);
356         be_node_set_reg_class(res, be_pos_Spill_val, cls);
357         return res;
358 }
359
360 ir_node *be_new_Reload(const arch_register_class_t *cls, const arch_register_class_t *cls_frame,
361         ir_graph *irg, ir_node *bl, ir_node *frame, ir_node *mem, ir_mode *mode)
362 {
363         ir_node *in[2];
364         ir_node *res;
365
366         in[0] = frame;
367         in[1] = mem;
368         res   = new_ir_node(NULL, irg, bl, op_be_Reload, mode, 2, in);
369
370         init_node_attr(res, 2);
371         be_node_set_reg_class(res, -1, cls);
372         be_node_set_reg_class(res, be_pos_Reload_frame, cls_frame);
373         be_node_set_flags(res, -1, arch_irn_flags_rematerializable);
374         return res;
375 }
376
377 ir_node *be_get_Reload_mem(const ir_node *irn)
378 {
379         assert(be_is_Reload(irn));
380         return get_irn_n(irn, be_pos_Reload_mem);
381 }
382
383 ir_node *be_get_Reload_frame(const ir_node *irn)
384 {
385         assert(be_is_Reload(irn));
386         return get_irn_n(irn, be_pos_Reload_frame);
387 }
388
389 ir_node *be_get_Spill_val(const ir_node *irn)
390 {
391         assert(be_is_Spill(irn));
392         return get_irn_n(irn, be_pos_Spill_val);
393 }
394 ir_node *be_get_Spill_frame(const ir_node *irn)
395 {
396         assert(be_is_Spill(irn));
397         return get_irn_n(irn, be_pos_Spill_frame);
398 }
399
400 ir_node *be_new_Perm(const arch_register_class_t *cls, ir_graph *irg, ir_node *bl, int n, ir_node *in[])
401 {
402         int i;
403         ir_node *irn = new_ir_node(NULL, irg, bl, op_be_Perm, mode_T, n, in);
404         init_node_attr(irn, n);
405         for(i = 0; i < n; ++i) {
406                 be_node_set_reg_class(irn, i, cls);
407                 be_node_set_reg_class(irn, OUT_POS(i), cls);
408         }
409
410         return irn;
411 }
412
413 ir_node *be_new_MemPerm(const arch_env_t *arch_env, ir_graph *irg, ir_node *bl, int n, ir_node *in[])
414 {
415         int i;
416         ir_node *frame = get_irg_frame(irg);
417         const arch_register_class_t *cls_frame = arch_get_irn_reg_class(arch_env, frame, -1);
418         ir_node *irn;
419         const arch_register_t *sp = arch_env->isa->sp;
420         be_memperm_attr_t *attr;
421         ir_node **real_in;
422
423         real_in = alloca((n+1) * sizeof(real_in[0]));
424         real_in[0] = frame;
425         memcpy(&real_in[1], in, n * sizeof(real_in[0]));
426
427         irn =  new_ir_node(NULL, irg, bl, op_be_MemPerm, mode_T, n+1, real_in);
428
429         init_node_attr(irn, n + 1);
430         be_node_set_reg_class(irn, 0, sp->reg_class);
431         for(i = 0; i < n; ++i) {
432                 be_node_set_reg_class(irn, i + 1, cls_frame);
433                 be_node_set_reg_class(irn, OUT_POS(i), cls_frame);
434         }
435
436         attr = get_irn_attr(irn);
437
438         attr->in_entities = obstack_alloc(irg->obst, n * sizeof(attr->in_entities[0]));
439         memset(attr->in_entities, 0, n * sizeof(attr->in_entities[0]));
440         attr->out_entities = obstack_alloc(irg->obst, n*sizeof(attr->out_entities[0]));
441         memset(attr->out_entities, 0, n*sizeof(attr->out_entities[0]));
442
443         return irn;
444 }
445
446
447 ir_node *be_new_Copy(const arch_register_class_t *cls, ir_graph *irg, ir_node *bl, ir_node *op)
448 {
449         ir_node *in[1];
450         ir_node *res;
451
452         in[0] = op;
453         res   = new_ir_node(NULL, irg, bl, op_be_Copy, get_irn_mode(op), 1, in);
454         init_node_attr(res, 1);
455         be_node_set_reg_class(res, 0, cls);
456         be_node_set_reg_class(res, OUT_POS(0), cls);
457         return res;
458 }
459
460 ir_node *be_get_Copy_op(const ir_node *cpy) {
461         return get_irn_n(cpy, be_pos_Copy_op);
462 }
463
464 void be_set_Copy_op(ir_node *cpy, ir_node *op) {
465         set_irn_n(cpy, be_pos_Copy_op, op);
466 }
467
468 ir_node *be_new_Keep(const arch_register_class_t *cls, ir_graph *irg, ir_node *bl, int n, ir_node *in[])
469 {
470         int i;
471         ir_node *irn;
472
473         irn = new_ir_node(NULL, irg, bl, op_be_Keep, mode_ANY, n, in);
474         init_node_attr(irn, n);
475         for(i = 0; i < n; ++i) {
476                 be_node_set_reg_class(irn, i, cls);
477         }
478         keep_alive(irn);
479         return irn;
480 }
481
482 ir_node *be_new_Call(dbg_info *dbg, ir_graph *irg, ir_node *bl, ir_node *mem, ir_node *sp, ir_node *ptr,
483                      int n_outs, int n, ir_node *in[], ir_type *call_tp)
484 {
485         be_call_attr_t *a;
486         int real_n = be_pos_Call_first_arg + n;
487         ir_node *irn;
488         ir_node **real_in;
489
490         NEW_ARR_A(ir_node *, real_in, real_n);
491         real_in[be_pos_Call_mem] = mem;
492         real_in[be_pos_Call_sp]  = sp;
493         real_in[be_pos_Call_ptr] = ptr;
494         memcpy(&real_in[be_pos_Call_first_arg], in, n * sizeof(in[0]));
495
496         irn = new_ir_node(dbg, irg, bl, op_be_Call, mode_T, real_n, real_in);
497         a = init_node_attr(irn, (n_outs > real_n ? n_outs : real_n));
498         a->ent     = NULL;
499         a->call_tp = call_tp;
500         return irn;
501 }
502
503 /* Gets the call entity or NULL if this is no static call. */
504 ir_entity *be_Call_get_entity(const ir_node *call) {
505         be_call_attr_t *a = get_irn_attr(call);
506         assert(be_is_Call(call));
507         return a->ent;
508 }
509
510 /* Sets the call entity. */
511 void be_Call_set_entity(ir_node *call, ir_entity *ent) {
512         be_call_attr_t *a = get_irn_attr(call);
513         assert(be_is_Call(call));
514         a->ent = ent;
515 }
516
517 /* Gets the call type. */
518 ir_type *be_Call_get_type(ir_node *call) {
519         be_call_attr_t *a = get_irn_attr(call);
520         assert(be_is_Call(call));
521         return a->call_tp;
522 }
523
524 /* Sets the call type. */
525 void be_Call_set_type(ir_node *call, ir_type *call_tp) {
526         be_call_attr_t *a = get_irn_attr(call);
527         assert(be_is_Call(call));
528         a->call_tp = call_tp;
529 }
530
531 /* Construct a new be_Return. */
532 ir_node *be_new_Return(dbg_info *dbg, ir_graph *irg, ir_node *bl, int n_res, int n, ir_node *in[])
533 {
534         be_return_attr_t *a;
535         ir_node *irn = new_ir_node(dbg, irg, bl, op_be_Return, mode_X, n, in);
536         init_node_attr(irn, n);
537         a = get_irn_attr(irn);
538         a->num_ret_vals = n_res;
539
540         return irn;
541 }
542
543 /* Returns the number of real returns values */
544 int be_Return_get_n_rets(ir_node *ret)
545 {
546         be_return_attr_t *a = get_irn_attr(ret);
547         return a->num_ret_vals;
548 }
549
550 ir_node *be_new_IncSP(const arch_register_t *sp, ir_graph *irg, ir_node *bl, ir_node *old_sp, int offset)
551 {
552         be_stack_attr_t *a;
553         ir_node *irn;
554         ir_node *in[1];
555
556         in[0]     = old_sp;
557         irn       = new_ir_node(NULL, irg, bl, op_be_IncSP, sp->reg_class->mode, sizeof(in) / sizeof(in[0]), in);
558         a         = init_node_attr(irn, 1);
559         a->offset = offset;
560
561         be_node_set_flags(irn, -1, arch_irn_flags_ignore | arch_irn_flags_modify_sp);
562
563         /* Set output constraint to stack register. */
564         be_node_set_reg_class(irn, 0, sp->reg_class);
565         be_set_constr_single_reg(irn, BE_OUT_POS(0), sp);
566         be_node_set_irn_reg(NULL, irn, sp);
567
568         return irn;
569 }
570
571 ir_node *be_new_AddSP(const arch_register_t *sp, ir_graph *irg, ir_node *bl, ir_node *old_sp, ir_node *sz)
572 {
573         be_node_attr_t *a;
574         ir_node *irn;
575         ir_node *in[be_pos_AddSP_last];
576
577         in[be_pos_AddSP_old_sp] = old_sp;
578         in[be_pos_AddSP_size]   = sz;
579
580         irn = new_ir_node(NULL, irg, bl, op_be_AddSP, mode_T, be_pos_AddSP_last, in);
581         a   = init_node_attr(irn, be_pos_AddSP_last);
582
583         be_node_set_flags(irn, OUT_POS(pn_be_AddSP_res), arch_irn_flags_ignore | arch_irn_flags_modify_sp);
584
585         /* Set output constraint to stack register. */
586         be_set_constr_single_reg(irn, be_pos_AddSP_old_sp, sp);
587         be_node_set_reg_class(irn, be_pos_AddSP_size, arch_register_get_class(sp));
588         be_set_constr_single_reg(irn, OUT_POS(pn_be_AddSP_res), sp);
589         a->reg_data[pn_be_AddSP_res].reg = sp;
590
591         return irn;
592 }
593
594 ir_node *be_new_SubSP(const arch_register_t *sp, ir_graph *irg, ir_node *bl, ir_node *old_sp, ir_node *sz)
595 {
596         be_node_attr_t *a;
597         ir_node *irn;
598         ir_node *in[be_pos_SubSP_last];
599
600         in[be_pos_SubSP_old_sp] = old_sp;
601         in[be_pos_SubSP_size]   = sz;
602
603         irn = new_ir_node(NULL, irg, bl, op_be_SubSP, mode_T, be_pos_SubSP_last, in);
604         a   = init_node_attr(irn, be_pos_SubSP_last);
605
606         be_node_set_flags(irn, OUT_POS(pn_be_SubSP_res), arch_irn_flags_ignore | arch_irn_flags_modify_sp);
607
608         /* Set output constraint to stack register. */
609         be_set_constr_single_reg(irn, be_pos_SubSP_old_sp, sp);
610         be_node_set_reg_class(irn, be_pos_SubSP_size, arch_register_get_class(sp));
611         be_set_constr_single_reg(irn, OUT_POS(pn_be_SubSP_res), sp);
612         a->reg_data[pn_be_SubSP_res].reg = sp;
613
614         return irn;
615 }
616
617 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)
618 {
619         be_node_attr_t *a;
620         ir_node *irn;
621         ir_node *in[3];
622
623         in[0]    = mem;
624         in[1]    = old_sp;
625         in[2]    = op;
626         irn      = new_ir_node(NULL, irg, bl, op_be_SetSP, get_irn_mode(old_sp), 3, in);
627         a        = init_node_attr(irn, 3);
628
629         be_node_set_flags(irn, OUT_POS(0), arch_irn_flags_ignore | arch_irn_flags_modify_sp);
630
631         /* Set output constraint to stack register. */
632         be_set_constr_single_reg(irn, OUT_POS(0), sp);
633         be_node_set_reg_class(irn, be_pos_AddSP_size, sp->reg_class);
634         be_node_set_reg_class(irn, be_pos_AddSP_old_sp, sp->reg_class);
635
636         return irn;
637 }
638
639 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, ir_entity *ent)
640 {
641         be_frame_attr_t *a;
642         ir_node *irn;
643         ir_node *in[1];
644
645         in[0] = frame_pointer;
646         irn = new_ir_node(NULL, irg, bl, op_be_StackParam, mode, 1, in);
647         a = init_node_attr(irn, 1);
648         a->ent = ent;
649
650         be_node_set_reg_class(irn, 0, cls_frame);
651         be_node_set_reg_class(irn, OUT_POS(0), cls);
652         return irn;
653 }
654
655 ir_node *be_new_RegParams(ir_graph *irg, ir_node *bl, int n_outs)
656 {
657         ir_node *irn;
658         ir_node *in[1];
659
660         irn = new_ir_node(NULL, irg, bl, op_be_RegParams, mode_T, 0, in);
661         init_node_attr(irn, n_outs);
662         return irn;
663 }
664
665 ir_node *be_new_FrameLoad(const arch_register_class_t *cls_frame, const arch_register_class_t *cls_data,
666                                                   ir_graph *irg, ir_node *bl, ir_node *mem, ir_node *frame, ir_entity *ent)
667 {
668         be_frame_attr_t *a;
669         ir_node *irn;
670         ir_node *in[2];
671
672         in[0]  = mem;
673         in[1]  = frame;
674         irn    = new_ir_node(NULL, irg, bl, op_be_FrameLoad, mode_T, 2, in);
675         a      = init_node_attr(irn, 3);
676         a->ent = ent;
677         a->offset = 0;
678         be_node_set_reg_class(irn, 1, cls_frame);
679         be_node_set_reg_class(irn, OUT_POS(pn_Load_res), cls_data);
680         return irn;
681 }
682
683 ir_node *be_new_FrameStore(const arch_register_class_t *cls_frame, const arch_register_class_t *cls_data,
684                                                    ir_graph *irg, ir_node *bl, ir_node *mem, ir_node *frame, ir_node *data, ir_entity *ent)
685 {
686         be_frame_attr_t *a;
687         ir_node *irn;
688         ir_node *in[3];
689
690         in[0]  = mem;
691         in[1]  = frame;
692         in[2]  = data;
693         irn    = new_ir_node(NULL, irg, bl, op_be_FrameStore, mode_T, 3, in);
694         a      = init_node_attr(irn, 3);
695         a->ent = ent;
696         a->offset = 0;
697         be_node_set_reg_class(irn, 1, cls_frame);
698         be_node_set_reg_class(irn, 2, cls_data);
699         return irn;
700 }
701
702 ir_node *be_new_FrameAddr(const arch_register_class_t *cls_frame, ir_graph *irg, ir_node *bl, ir_node *frame, ir_entity *ent)
703 {
704         be_frame_attr_t *a;
705         ir_node *irn;
706         ir_node *in[1];
707
708         in[0]  = frame;
709         irn    = new_ir_node(NULL, irg, bl, op_be_FrameAddr, get_irn_mode(frame), 1, in);
710         a      = init_node_attr(irn, 1);
711         a->ent = ent;
712         a->offset = 0;
713         be_node_set_reg_class(irn, 0, cls_frame);
714         be_node_set_reg_class(irn, OUT_POS(0), cls_frame);
715
716         return optimize_node(irn);
717 }
718
719 ir_node *be_new_CopyKeep(const arch_register_class_t *cls, ir_graph *irg, ir_node *bl, ir_node *src, int n, ir_node *in_keep[], ir_mode *mode)
720 {
721         ir_node *irn;
722         ir_node **in = (ir_node **) alloca((n + 1) * sizeof(in[0]));
723
724         in[0] = src;
725         memcpy(&in[1], in_keep, n * sizeof(in[0]));
726         irn   = new_ir_node(NULL, irg, bl, op_be_CopyKeep, mode, n + 1, in);
727         init_node_attr(irn, n + 1);
728         be_node_set_reg_class(irn, OUT_POS(0), cls);
729         be_node_set_reg_class(irn, 0, cls);
730
731         return irn;
732 }
733
734 ir_node *be_new_CopyKeep_single(const arch_register_class_t *cls, ir_graph *irg, ir_node *bl, ir_node *src, ir_node *keep, ir_mode *mode)
735 {
736         ir_node *in[1];
737
738         in[0] = keep;
739         return be_new_CopyKeep(cls, irg, bl, src, 1, in, mode);
740 }
741
742 ir_node *be_get_CopyKeep_op(const ir_node *cpy) {
743         return get_irn_n(cpy, be_pos_CopyKeep_op);
744 }
745
746 void be_set_CopyKeep_op(ir_node *cpy, ir_node *op) {
747         set_irn_n(cpy, be_pos_CopyKeep_op, op);
748 }
749
750 ir_node *be_new_Barrier(ir_graph *irg, ir_node *bl, int n, ir_node *in[])
751 {
752         ir_node *irn;
753
754         irn = new_ir_node(NULL, irg, bl, op_be_Barrier, mode_T, n, in);
755         init_node_attr(irn, n);
756         return irn;
757 }
758
759 int be_is_Spill         (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Spill          ; }
760 int be_is_Reload        (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Reload         ; }
761 int be_is_Copy          (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Copy           ; }
762 int be_is_CopyKeep      (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_CopyKeep       ; }
763 int be_is_Perm          (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Perm           ; }
764 int be_is_MemPerm       (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_MemPerm        ; }
765 int be_is_Keep          (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Keep           ; }
766 int be_is_Call          (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Call           ; }
767 int be_is_Return        (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Return         ; }
768 int be_is_IncSP         (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_IncSP          ; }
769 int be_is_SetSP         (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_SetSP          ; }
770 int be_is_AddSP         (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_AddSP          ; }
771 int be_is_RegParams     (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_RegParams      ; }
772 int be_is_StackParam    (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_StackParam     ; }
773 int be_is_FrameAddr     (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_FrameAddr      ; }
774 int be_is_FrameLoad     (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_FrameLoad      ; }
775 int be_is_FrameStore    (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_FrameStore     ; }
776 int be_is_Barrier       (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Barrier        ; }
777
778 int be_has_frame_entity(const ir_node *irn)
779 {
780         switch(be_get_irn_opcode(irn)) {
781         case beo_StackParam:
782         case beo_Spill:
783         case beo_Reload:
784         case beo_FrameStore:
785         case beo_FrameLoad:
786         case beo_FrameAddr:
787                 return 1;
788         default:
789                 return 0;
790         }
791 }
792
793 ir_entity *be_get_frame_entity(const ir_node *irn)
794 {
795         if (be_has_frame_entity(irn)) {
796                 be_frame_attr_t *a = get_irn_attr(irn);
797                 return a->ent;
798         }
799         return NULL;
800 }
801
802 int be_get_frame_offset(const ir_node *irn)
803 {
804         assert(is_be_node(irn));
805         if (be_has_frame_entity(irn)) {
806                 be_frame_attr_t *a = get_irn_attr(irn);
807                 return a->offset;
808         }
809         return 0;
810 }
811
812 void be_set_MemPerm_in_entity(const ir_node *irn, int n, ir_entity *ent)
813 {
814         be_memperm_attr_t *attr = get_irn_attr(irn);
815
816         assert(be_is_MemPerm(irn));
817         assert(n < be_get_MemPerm_entity_arity(irn));
818
819         attr->in_entities[n] = ent;
820 }
821
822 ir_entity* be_get_MemPerm_in_entity(const ir_node* irn, int n)
823 {
824         be_memperm_attr_t *attr = get_irn_attr(irn);
825
826         assert(be_is_MemPerm(irn));
827         assert(n < be_get_MemPerm_entity_arity(irn));
828
829         return attr->in_entities[n];
830 }
831
832 void be_set_MemPerm_out_entity(const ir_node *irn, int n, ir_entity *ent)
833 {
834         be_memperm_attr_t *attr = get_irn_attr(irn);
835
836         assert(be_is_MemPerm(irn));
837         assert(n < be_get_MemPerm_entity_arity(irn));
838
839         attr->out_entities[n] = ent;
840 }
841
842 ir_entity* be_get_MemPerm_out_entity(const ir_node* irn, int n)
843 {
844         be_memperm_attr_t *attr = get_irn_attr(irn);
845
846         assert(be_is_MemPerm(irn));
847         assert(n < be_get_MemPerm_entity_arity(irn));
848
849         return attr->out_entities[n];
850 }
851
852 int be_get_MemPerm_entity_arity(const ir_node *irn)
853 {
854         return get_irn_arity(irn) - 1;
855 }
856
857 static void be_limited(void *data, bitset_t *bs)
858 {
859         be_req_t *req = data;
860
861         switch(req->kind) {
862         case be_req_kind_negate_old_limited:
863         case be_req_kind_old_limited:
864                 req->x.old_limited.old_limited(req->x.old_limited.old_limited_env, bs);
865                 if(req->kind == be_req_kind_negate_old_limited)
866                         bitset_flip_all(bs);
867                 break;
868         case be_req_kind_single_reg:
869                 bitset_clear_all(bs);
870                 bitset_set(bs, req->x.single_reg->index);
871                 break;
872         }
873 }
874
875 static INLINE be_req_t *get_req(ir_node *irn, int pos)
876 {
877         int idx           = pos < 0 ? -(pos + 1) : pos;
878         be_node_attr_t *a = get_irn_attr(irn);
879         be_reg_data_t *rd = &a->reg_data[idx];
880         be_req_t       *r = pos < 0 ? &rd->req : &rd->in_req;
881
882         assert(is_be_node(irn));
883         assert(!(pos >= 0) || pos < get_irn_arity(irn));
884         assert(!(pos < 0)  || -(pos + 1) <= a->max_reg_data);
885
886         return r;
887 }
888
889 void be_set_constr_single_reg(ir_node *irn, int pos, const arch_register_t *reg)
890 {
891         be_req_t *r = get_req(irn, pos);
892
893         r->kind            = be_req_kind_single_reg;
894         r->x.single_reg    = reg;
895         r->req.limited     = be_limited;
896         r->req.limited_env = r;
897         r->req.type        = arch_register_req_type_limited;
898         r->req.cls         = reg->reg_class;
899 }
900
901 void be_set_constr_limited(ir_node *irn, int pos, const arch_register_req_t *req)
902 {
903         be_req_t *r = get_req(irn, pos);
904
905         assert(arch_register_req_is(req, limited));
906
907         r->kind            = be_req_kind_old_limited;
908         r->req.limited     = be_limited;
909         r->req.limited_env = r;
910         r->req.type        = arch_register_req_type_limited;
911         r->req.cls         = req->cls;
912
913         r->x.old_limited.old_limited     = req->limited;
914         r->x.old_limited.old_limited_env = req->limited_env;
915 }
916
917 void be_node_set_flags(ir_node *irn, int pos, arch_irn_flags_t flags)
918 {
919         be_req_t *r = get_req(irn, pos);
920         r->flags = flags;
921 }
922
923 void be_node_set_reg_class(ir_node *irn, int pos, const arch_register_class_t *cls)
924 {
925         be_req_t *r = get_req(irn, pos);
926
927         r->req.cls = cls;
928
929         if (cls == NULL)
930                 r->req.type = arch_register_req_type_none;
931         else if (r->req.type == arch_register_req_type_none)
932                 r->req.type = arch_register_req_type_normal;
933 }
934
935 void be_node_set_req_type(ir_node *irn, int pos, arch_register_req_type_t type)
936 {
937         be_req_t *r = get_req(irn, pos);
938         r->req.type = type;
939 }
940
941 ir_node *be_get_IncSP_pred(ir_node *irn) {
942         assert(be_is_IncSP(irn));
943         return get_irn_n(irn, 0);
944 }
945
946 void be_set_IncSP_pred(ir_node *incsp, ir_node *pred) {
947         assert(be_is_IncSP(incsp));
948         set_irn_n(incsp, 0, pred);
949 }
950
951 ir_node *be_get_IncSP_mem(ir_node *irn) {
952         assert(be_is_IncSP(irn));
953         return get_irn_n(irn, 1);
954 }
955
956 void be_set_IncSP_offset(ir_node *irn, int offset)
957 {
958         be_stack_attr_t *a = get_irn_attr(irn);
959         assert(be_is_IncSP(irn));
960         a->offset = offset;
961 }
962
963 int be_get_IncSP_offset(const ir_node *irn)
964 {
965         be_stack_attr_t *a = get_irn_attr(irn);
966         assert(be_is_IncSP(irn));
967         return a->offset;
968 }
969
970 ir_node *be_spill(const arch_env_t *arch_env, ir_node *irn)
971 {
972         ir_node                     *bl        = get_nodes_block(irn);
973         ir_graph                    *irg       = get_irn_irg(bl);
974         ir_node                     *frame     = get_irg_frame(irg);
975         const arch_register_class_t *cls       = arch_get_irn_reg_class(arch_env, irn, -1);
976         const arch_register_class_t *cls_frame = arch_get_irn_reg_class(arch_env, frame, -1);
977         ir_node                     *spill;
978
979         spill = be_new_Spill(cls, cls_frame, irg, bl, frame, irn);
980         return spill;
981 }
982
983 ir_node *be_reload(const arch_env_t *arch_env, const arch_register_class_t *cls, ir_node *insert, ir_mode *mode, ir_node *spill)
984 {
985         ir_node  *reload;
986         ir_node  *bl    = is_Block(insert) ? insert : get_nodes_block(insert);
987         ir_graph *irg   = get_irn_irg(bl);
988         ir_node  *frame = get_irg_frame(irg);
989         const arch_register_class_t *cls_frame = arch_get_irn_reg_class(arch_env, frame, -1);
990
991         assert(be_is_Spill(spill) || (is_Phi(spill) && get_irn_mode(spill) == mode_M));
992
993         reload = be_new_Reload(cls, cls_frame, irg, bl, frame, spill, mode);
994
995         if (is_Block(insert)) {
996                 insert = sched_skip(insert, 0, sched_skip_cf_predicator, (void *) arch_env);
997                 sched_add_after(insert, reload);
998         }
999
1000         else
1001                 sched_add_before(insert, reload);
1002
1003         return reload;
1004 }
1005
1006 /*
1007   ____              ____
1008  |  _ \ ___  __ _  |  _ \ ___  __ _ ___
1009  | |_) / _ \/ _` | | |_) / _ \/ _` / __|
1010  |  _ <  __/ (_| | |  _ <  __/ (_| \__ \
1011  |_| \_\___|\__, | |_| \_\___|\__, |___/
1012             |___/                |_|
1013
1014 */
1015
1016
1017 static void *put_out_reg_req(arch_register_req_t *req, const ir_node *irn, int out_pos)
1018 {
1019         const be_node_attr_t *a = get_irn_attr(irn);
1020
1021         if(out_pos < a->max_reg_data) {
1022                 memcpy(req, &a->reg_data[out_pos].req, sizeof(req[0]));
1023
1024                 if(be_is_Copy(irn)) {
1025                         req->type |= arch_register_req_type_should_be_same;
1026                         req->other_same = be_get_Copy_op(irn);
1027                 }
1028         }
1029         else {
1030                 req->type = arch_register_req_type_none;
1031                 req->cls  = NULL;
1032         }
1033
1034         return req;
1035 }
1036
1037 static void *put_in_reg_req(arch_register_req_t *req, const ir_node *irn, int pos)
1038 {
1039         const be_node_attr_t *a = get_irn_attr(irn);
1040
1041         if(pos < get_irn_arity(irn) && pos < a->max_reg_data)
1042                 memcpy(req, &a->reg_data[pos].in_req, sizeof(req[0]));
1043         else {
1044                 req->type = arch_register_req_type_none;
1045                 req->cls  = NULL;
1046         }
1047
1048         return req;
1049 }
1050
1051 static const arch_register_req_t *
1052 be_node_get_irn_reg_req(const void *self, arch_register_req_t *req, const ir_node *irn, int pos)
1053 {
1054         int out_pos = pos;
1055
1056         if (pos < 0) {
1057                 if (get_irn_mode(irn) == mode_T)
1058                         return NULL;
1059
1060                 out_pos = redir_proj((const ir_node **)&irn, pos);
1061                 assert(is_be_node(irn));
1062                 return put_out_reg_req(req, irn, out_pos);
1063         }
1064
1065         else {
1066                 if (is_be_node(irn)) {
1067                         /*
1068                                 For spills and reloads, we return "none" as requirement for frame pointer,
1069                                 so every input is ok. Some backends need this (e.g. STA). We use an arbitrary
1070                                 large number as pos, so put_in_reg_req will return "none" as requirement.
1071                         */
1072                         if ((be_is_Spill(irn)  && pos == be_pos_Spill_frame) ||
1073                                 (be_is_Reload(irn) && pos == be_pos_Reload_frame))
1074                                 return put_in_reg_req(req, irn, INT_MAX);
1075                         else
1076                                 return put_in_reg_req(req, irn, pos);
1077                 }
1078                 return NULL;
1079         }
1080
1081         return req;
1082 }
1083
1084 const arch_register_t *
1085 be_node_get_irn_reg(const void *_self, const ir_node *irn)
1086 {
1087         be_reg_data_t *r = retrieve_reg_data(irn);
1088         return r ? r->reg : NULL;
1089 }
1090
1091 static arch_irn_class_t be_node_classify(const void *_self, const ir_node *irn)
1092 {
1093         redir_proj((const ir_node **) &irn, -1);
1094
1095         switch(be_get_irn_opcode(irn)) {
1096 #define XXX(a,b) case beo_ ## a: return arch_irn_class_ ## b
1097                 XXX(Spill, spill);
1098                 XXX(Reload, reload);
1099                 XXX(Perm, perm);
1100                 XXX(Copy, copy);
1101                 XXX(Return, branch);
1102                 XXX(StackParam, stackparam);
1103 #undef XXX
1104                 default:
1105                 return arch_irn_class_normal;
1106         }
1107
1108         return 0;
1109 }
1110
1111 static arch_irn_flags_t be_node_get_flags(const void *_self, const ir_node *irn)
1112 {
1113         be_reg_data_t *r = retrieve_reg_data(irn);
1114         return r ? r->req.flags : 0;
1115 }
1116
1117 static ir_entity *be_node_get_frame_entity(const void *self, const ir_node *irn)
1118 {
1119         return be_get_frame_entity(irn);
1120 }
1121
1122 static void be_node_set_frame_entity(const void *self, ir_node *irn, ir_entity *ent)
1123 {
1124         be_frame_attr_t *a;
1125
1126         assert(be_has_frame_entity(irn));
1127
1128         a = get_irn_attr(irn);
1129         a->ent = ent;
1130 }
1131
1132 static void be_node_set_frame_offset(const void *self, ir_node *irn, int offset)
1133 {
1134         if(be_has_frame_entity(irn)) {
1135                 be_frame_attr_t *a = get_irn_attr(irn);
1136                 a->offset = offset;
1137         }
1138 }
1139
1140 static int be_node_get_sp_bias(const void *self, const ir_node *irn)
1141 {
1142         return be_is_IncSP(irn) ? be_get_IncSP_offset(irn) : 0;
1143 }
1144
1145 /*
1146   ___ ____  _   _   _   _                 _ _
1147  |_ _|  _ \| \ | | | | | | __ _ _ __   __| | | ___ _ __
1148   | || |_) |  \| | | |_| |/ _` | '_ \ / _` | |/ _ \ '__|
1149   | ||  _ <| |\  | |  _  | (_| | | | | (_| | |  __/ |
1150  |___|_| \_\_| \_| |_| |_|\__,_|_| |_|\__,_|_|\___|_|
1151
1152 */
1153
1154 static const arch_irn_ops_if_t be_node_irn_ops_if = {
1155         be_node_get_irn_reg_req,
1156         be_node_set_irn_reg,
1157         be_node_get_irn_reg,
1158         be_node_classify,
1159         be_node_get_flags,
1160         be_node_get_frame_entity,
1161         be_node_set_frame_entity,
1162         be_node_set_frame_offset,
1163         be_node_get_sp_bias,
1164         NULL,    /* get_inverse             */
1165         NULL,    /* get_op_estimated_cost   */
1166         NULL,    /* possible_memory_operand */
1167         NULL,    /* perform_memory_operand  */
1168 };
1169
1170 static const arch_irn_ops_t be_node_irn_ops = {
1171         &be_node_irn_ops_if
1172 };
1173
1174 const void *be_node_get_irn_ops(const arch_irn_handler_t *self, const ir_node *irn)
1175 {
1176         redir_proj((const ir_node **) &irn, -1);
1177         return is_be_node(irn) ? &be_node_irn_ops : NULL;
1178 }
1179
1180 const arch_irn_handler_t be_node_irn_handler = {
1181         be_node_get_irn_ops
1182 };
1183
1184 /*
1185   ____  _     _   ___ ____  _   _   _   _                 _ _
1186  |  _ \| |__ (_) |_ _|  _ \| \ | | | | | | __ _ _ __   __| | | ___ _ __
1187  | |_) | '_ \| |  | || |_) |  \| | | |_| |/ _` | '_ \ / _` | |/ _ \ '__|
1188  |  __/| | | | |  | ||  _ <| |\  | |  _  | (_| | | | | (_| | |  __/ |
1189  |_|   |_| |_|_| |___|_| \_\_| \_| |_| |_|\__,_|_| |_|\__,_|_|\___|_|
1190
1191 */
1192
1193 typedef struct {
1194         arch_irn_handler_t irn_handler;
1195         arch_irn_ops_t     irn_ops;
1196         const arch_env_t   *arch_env;
1197         pmap               *regs;
1198 } phi_handler_t;
1199
1200 #define get_phi_handler_from_handler(h)  container_of(h, phi_handler_t, irn_handler)
1201 #define get_phi_handler_from_ops(h)      container_of(h, phi_handler_t, irn_ops)
1202
1203 static const void *phi_get_irn_ops(const arch_irn_handler_t *handler, const ir_node *irn)
1204 {
1205         const phi_handler_t *h = get_phi_handler_from_handler(handler);
1206         return is_Phi(irn) && mode_is_datab(get_irn_mode(irn)) ? &h->irn_ops : NULL;
1207 }
1208
1209 /**
1210  * Get register class of a Phi.
1211  *
1212  */
1213 static const arch_register_req_t *get_Phi_reg_req_recursive(const phi_handler_t *h, arch_register_req_t *req, const ir_node *phi, pset **visited)
1214 {
1215         int n = get_irn_arity(phi);
1216         ir_node *op;
1217         int i;
1218
1219         if(*visited && pset_find_ptr(*visited, phi))
1220                 return NULL;
1221
1222         for(i = 0; i < n; ++i) {
1223                 op = get_irn_n(phi, i);
1224                 if(!is_Phi(op))
1225                         return arch_get_register_req(h->arch_env, req, op, BE_OUT_POS(0));
1226         }
1227
1228         /*
1229         The operands of that Phi were all Phis themselves.
1230         We have to start a DFS for a non-Phi argument now.
1231         */
1232         if(!*visited)
1233                 *visited = pset_new_ptr(16);
1234
1235         pset_insert_ptr(*visited, phi);
1236
1237         for(i = 0; i < n; ++i) {
1238                 op = get_irn_n(phi, i);
1239                 if(get_Phi_reg_req_recursive(h, req, op, visited))
1240                         return req;
1241         }
1242
1243         return NULL;
1244 }
1245
1246 static const arch_register_req_t *phi_get_irn_reg_req(const void *self, arch_register_req_t *req, const ir_node *irn, int pos)
1247 {
1248         phi_handler_t *phi_handler = get_phi_handler_from_ops(self);
1249         pset *visited              = NULL;
1250
1251         get_Phi_reg_req_recursive(phi_handler, req, irn, &visited);
1252         /* Set the requirements type to normal, since an operand of the Phi could have had constraints. */
1253         req->type = arch_register_req_type_normal;
1254         if(visited)
1255                 del_pset(visited);
1256
1257         return req;
1258 }
1259
1260 static void phi_set_irn_reg(const void *self, ir_node *irn, const arch_register_t *reg)
1261 {
1262         phi_handler_t *h = get_phi_handler_from_ops(self);
1263         pmap_insert(h->regs, irn, (void *) reg);
1264 }
1265
1266 static const arch_register_t *phi_get_irn_reg(const void *self, const ir_node *irn)
1267 {
1268         phi_handler_t *h = get_phi_handler_from_ops(self);
1269         return pmap_get(h->regs, (void *) irn);
1270 }
1271
1272 static arch_irn_class_t phi_classify(const void *_self, const ir_node *irn)
1273 {
1274         return arch_irn_class_normal;
1275 }
1276
1277 static arch_irn_flags_t phi_get_flags(const void *_self, const ir_node *irn)
1278 {
1279         return arch_irn_flags_none;
1280 }
1281
1282 static ir_entity *phi_get_frame_entity(const void *_self, const ir_node *irn)
1283 {
1284         return NULL;
1285 }
1286
1287 static void phi_set_frame_entity(const void *_self, ir_node *irn, ir_entity *ent)
1288 {
1289 }
1290
1291 static void phi_set_frame_offset(const void *_self, ir_node *irn, int bias)
1292 {
1293 }
1294
1295 static int phi_get_sp_bias(const void* self, const ir_node *irn)
1296 {
1297         return 0;
1298 }
1299
1300 static const arch_irn_ops_if_t phi_irn_ops = {
1301         phi_get_irn_reg_req,
1302         phi_set_irn_reg,
1303         phi_get_irn_reg,
1304         phi_classify,
1305         phi_get_flags,
1306         phi_get_frame_entity,
1307         phi_set_frame_entity,
1308         phi_set_frame_offset,
1309         phi_get_sp_bias,
1310         NULL,    /* get_inverse             */
1311         NULL,    /* get_op_estimated_cost   */
1312         NULL,    /* possible_memory_operand */
1313         NULL,    /* perform_memory_operand  */
1314 };
1315
1316 static const arch_irn_handler_t phi_irn_handler = {
1317         phi_get_irn_ops
1318 };
1319
1320 arch_irn_handler_t *be_phi_handler_new(const arch_env_t *arch_env)
1321 {
1322         phi_handler_t *h           = xmalloc(sizeof(h[0]));
1323         h->irn_handler.get_irn_ops = phi_get_irn_ops;
1324         h->irn_ops.impl            = &phi_irn_ops;
1325         h->arch_env                = arch_env;
1326         h->regs                    = pmap_create();
1327         return (arch_irn_handler_t *) h;
1328 }
1329
1330 void be_phi_handler_free(arch_irn_handler_t *handler)
1331 {
1332         phi_handler_t *h = (void *) handler;
1333         pmap_destroy(h->regs);
1334         free(handler);
1335 }
1336
1337 const void *be_phi_get_irn_ops(const arch_irn_handler_t *self, const ir_node *irn)
1338 {
1339         phi_handler_t *phi_handler = get_phi_handler_from_handler(self);
1340         return is_Phi(irn) ? &phi_handler->irn_ops : NULL;
1341 }
1342
1343 void be_phi_handler_reset(arch_irn_handler_t *handler)
1344 {
1345         phi_handler_t *h = get_phi_handler_from_handler(handler);
1346         if(h->regs)
1347                 pmap_destroy(h->regs);
1348         h->regs = pmap_create();
1349 }
1350
1351 /*
1352   _   _           _        ____                        _
1353  | \ | | ___   __| | ___  |  _ \ _   _ _ __ ___  _ __ (_)_ __   __ _
1354  |  \| |/ _ \ / _` |/ _ \ | | | | | | | '_ ` _ \| '_ \| | '_ \ / _` |
1355  | |\  | (_) | (_| |  __/ | |_| | |_| | | | | | | |_) | | | | | (_| |
1356  |_| \_|\___/ \__,_|\___| |____/ \__,_|_| |_| |_| .__/|_|_| |_|\__, |
1357                                                 |_|            |___/
1358 */
1359
1360 /**
1361  * Dumps a register requirement to a file.
1362  */
1363 static void dump_node_req(FILE *f, int idx, be_req_t *req)
1364 {
1365         unsigned i;
1366         int did_something = 0;
1367         char buf[16];
1368         const char *prefix = buf;
1369
1370         snprintf(buf, sizeof(buf), "#%d ", idx);
1371         buf[sizeof(buf) - 1] = '\0';
1372
1373         if(req->flags != arch_irn_flags_none) {
1374                 fprintf(f, "%sflags: ", prefix);
1375                 prefix = "";
1376                 for(i = arch_irn_flags_none; i <= log2_ceil(arch_irn_flags_last); ++i) {
1377                         if(req->flags & (1 << i)) {
1378                                 fprintf(f, "%s%s", prefix, arch_irn_flag_str(1 << i));
1379                                 prefix = "|";
1380                         }
1381                 }
1382                 prefix = ", ";
1383                 did_something = 1;
1384         }
1385
1386         if(req->req.cls != 0) {
1387                 char tmp[256];
1388                 fprintf(f, prefix);
1389                 arch_register_req_format(tmp, sizeof(tmp), &req->req);
1390                 fprintf(f, "%s", tmp);
1391                 did_something = 1;
1392         }
1393
1394         if(did_something)
1395                 fprintf(f, "\n");
1396 }
1397
1398 /**
1399  * Dumps node register requirements to a file.
1400  */
1401 static void dump_node_reqs(FILE *f, ir_node *irn)
1402 {
1403         int i;
1404         be_node_attr_t *a = get_irn_attr(irn);
1405
1406         fprintf(f, "registers: \n");
1407         for(i = 0; i < a->max_reg_data; ++i) {
1408                 be_reg_data_t *rd = &a->reg_data[i];
1409                 if(rd->reg)
1410                         fprintf(f, "#%d: %s\n", i, rd->reg->name);
1411         }
1412
1413         fprintf(f, "in requirements\n");
1414         for(i = 0; i < a->max_reg_data; ++i) {
1415                 dump_node_req(f, i, &a->reg_data[i].in_req);
1416         }
1417
1418         fprintf(f, "\nout requirements\n");
1419         for(i = 0; i < a->max_reg_data; ++i) {
1420                 dump_node_req(f, i, &a->reg_data[i].req);
1421         }
1422 }
1423
1424 /**
1425  * ir_op-Operation: dump a be node to file
1426  */
1427 static int dump_node(ir_node *irn, FILE *f, dump_reason_t reason)
1428 {
1429         be_node_attr_t *at = get_irn_attr(irn);
1430
1431         assert(is_be_node(irn));
1432
1433         switch(reason) {
1434                 case dump_node_opcode_txt:
1435                         fprintf(f, get_op_name(get_irn_op(irn)));
1436                         break;
1437                 case dump_node_mode_txt:
1438                         fprintf(f, get_mode_name(get_irn_mode(irn)));
1439                         break;
1440                 case dump_node_nodeattr_txt:
1441                         break;
1442                 case dump_node_info_txt:
1443                         dump_node_reqs(f, irn);
1444
1445                         if(be_has_frame_entity(irn)) {
1446                                 be_frame_attr_t *a = (be_frame_attr_t *) at;
1447                                 if (a->ent) {
1448                                         int bits = get_type_size_bits(get_entity_type(a->ent));
1449                                         ir_fprintf(f, "frame entity: %+F, offset 0x%x (%d), size 0x%x (%d) bits\n",
1450                                           a->ent, a->offset, a->offset, bits, bits);
1451                                 }
1452
1453                         }
1454
1455                         switch(be_get_irn_opcode(irn)) {
1456                         case beo_IncSP:
1457                                 {
1458                                         be_stack_attr_t *a = (be_stack_attr_t *) at;
1459                                         if (a->offset == BE_STACK_FRAME_SIZE_EXPAND)
1460                                                 fprintf(f, "offset: FRAME_SIZE\n");
1461                                         else if(a->offset == BE_STACK_FRAME_SIZE_SHRINK)
1462                                                 fprintf(f, "offset: -FRAME SIZE\n");
1463                                         else
1464                                                 fprintf(f, "offset: %u\n", a->offset);
1465                                 }
1466                                 break;
1467                         case beo_Call:
1468                                 {
1469                                         be_call_attr_t *a = (be_call_attr_t *) at;
1470
1471                                         if (a->ent)
1472                                                 fprintf(f, "\ncalling: %s\n", get_entity_name(a->ent));
1473                                 }
1474                                 break;
1475                         case beo_MemPerm:
1476                                 {
1477                                         int i;
1478                                         for(i = 0; i < be_get_MemPerm_entity_arity(irn); ++i) {
1479                                                 ir_entity *in, *out;
1480                                                 in = be_get_MemPerm_in_entity(irn, i);
1481                                                 out = be_get_MemPerm_out_entity(irn, i);
1482                                                 if(in) {
1483                                                         fprintf(f, "\nin[%d]: %s\n", i, get_entity_name(in));
1484                                                 }
1485                                                 if(out) {
1486                                                         fprintf(f, "\nout[%d]: %s\n", i, get_entity_name(out));
1487                                                 }
1488                                         }
1489                                 }
1490                                 break;
1491
1492                         default:
1493                                 break;
1494                         }
1495         }
1496
1497         return 0;
1498 }
1499
1500 /**
1501  * ir_op-Operation:
1502  * Copies the backend specific attributes from old node to new node.
1503  */
1504 static void copy_attr(const ir_node *old_node, ir_node *new_node)
1505 {
1506         be_node_attr_t *old_attr = get_irn_attr(old_node);
1507         be_node_attr_t *new_attr = get_irn_attr(new_node);
1508         int i;
1509
1510         assert(is_be_node(old_node));
1511         assert(is_be_node(new_node));
1512
1513         memcpy(new_attr, old_attr, get_op_attr_size(get_irn_op(old_node)));
1514         new_attr->reg_data = NULL;
1515
1516         if(new_attr->max_reg_data > 0) {
1517                 new_attr->reg_data = NEW_ARR_D(be_reg_data_t, get_irg_obstack(get_irn_irg(new_node)), new_attr->max_reg_data);
1518                 memcpy(new_attr->reg_data, old_attr->reg_data, new_attr->max_reg_data * sizeof(be_reg_data_t));
1519
1520                 for(i = 0; i < old_attr->max_reg_data; ++i) {
1521                         be_req_t *r;
1522
1523                         r = &new_attr->reg_data[i].req;
1524                         r->req.limited_env = r;
1525
1526                         r = &new_attr->reg_data[i].in_req;
1527                         r->req.limited_env = r;
1528                 }
1529         }
1530 }
1531
1532 static const ir_op_ops be_node_op_ops = {
1533         NULL,
1534         NULL,
1535         NULL,
1536         NULL,
1537         NULL,
1538         copy_attr,
1539         NULL,
1540         NULL,
1541         NULL,
1542         NULL,
1543         NULL,
1544         dump_node,
1545         NULL
1546 };