benode.c 27.8 KB
Newer Older
Sebastian Hack's avatar
Sebastian Hack committed
1
2
3
4
5
6
7
/**
 * @file   benode.c
 * @date   17.05.2005
 * @author Sebastian Hack
 *
 * Backend node support.
 *
8
9
 * This file provdies Perm, Copy, Spill and Reload nodes.
 *
Sebastian Hack's avatar
Sebastian Hack committed
10
11
12
 * Copyright (C) 2005 Universitaet Karlsruhe
 * Released under the GPL
 */
13

Michael Beck's avatar
Michael Beck committed
14
15
16
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
Sebastian Hack's avatar
Sebastian Hack committed
17
18
19
20
21
22

#include <stdlib.h>

#include "obst.h"
#include "set.h"
#include "pmap.h"
23
#include "util.h"
Sebastian Hack's avatar
Sebastian Hack committed
24
#include "debug.h"
25
#include "fourcc.h"
Sebastian Hack's avatar
Sebastian Hack committed
26
#include "bitfiddle.h"
Sebastian Hack's avatar
Sebastian Hack committed
27
28
29
30

#include "irop_t.h"
#include "irmode_t.h"
#include "irnode_t.h"
31
#include "ircons_t.h"
32
#include "irprintf.h"
Sebastian Hack's avatar
Sebastian Hack committed
33

34
35
36
#include "be_t.h"
#include "belive_t.h"
#include "besched_t.h"
Sebastian Hack's avatar
Sebastian Hack committed
37
38
#include "benode_t.h"

39
40
#include "beirgmod.h"

Sebastian Hack's avatar
Sebastian Hack committed
41
42
/* Sometimes we want to put const nodes into get_irn_generic_attr ... */
#define get_irn_attr(irn) get_irn_generic_attr((ir_node *) (irn))
Daniel Grund's avatar
Daniel Grund committed
43

Sebastian Hack's avatar
Sebastian Hack committed
44
static unsigned be_node_tag = FOURCC('B', 'E', 'N', 'O');
45

Sebastian Hack's avatar
Sebastian Hack committed
46
typedef enum _node_kind_t {
Christian Würdig's avatar
Christian Würdig committed
47
48
49
50
	node_kind_spill,
	node_kind_reload,
	node_kind_perm,
	node_kind_copy,
Sebastian Hack's avatar
Sebastian Hack committed
51
	node_kind_kill,
Christian Würdig's avatar
Christian Würdig committed
52
	node_kind_last
Sebastian Hack's avatar
Sebastian Hack committed
53
54
55
} node_kind_t;

typedef struct {
Christian Würdig's avatar
Christian Würdig committed
56
57
58
59
60
	node_kind_t kind;
	const arch_register_class_t *cls;
	ir_op *op;
	int n_pos;
	int *pos;
Sebastian Hack's avatar
Sebastian Hack committed
61
62
} be_op_t;

Sebastian Hack's avatar
Sebastian Hack committed
63
64
65
66
67
68
typedef enum {
	be_req_kind_old_limited,
	be_req_kind_negate_old_limited,
	be_req_kind_single_reg
} be_req_kind_t;

Sebastian Hack's avatar
Sebastian Hack committed
69
70
typedef struct {
	arch_register_req_t req;
Sebastian Hack's avatar
Sebastian Hack committed
71
	be_req_kind_t       kind;
Sebastian Hack's avatar
Sebastian Hack committed
72
	arch_irn_flags_t    flags;
Sebastian Hack's avatar
Sebastian Hack committed
73
74
75
76
77
78
79
80
	union {
		struct {
			void (*old_limited)(void *ptr, bitset_t *bs);
			void *old_limited_env;
		} old_limited;

		const arch_register_t *single_reg;
	} x;
Sebastian Hack's avatar
Sebastian Hack committed
81
82
} be_req_t;

83
typedef struct {
84
	const arch_register_t *reg;
Sebastian Hack's avatar
Sebastian Hack committed
85
	be_req_t              req;
Sebastian Hack's avatar
Sebastian Hack committed
86
	be_req_t              in_req;
87
88
89
} be_reg_data_t;

typedef struct {
Sebastian Hack's avatar
Sebastian Hack committed
90
	int                         max_reg_data;
Sebastian Hack's avatar
Sebastian Hack committed
91
92
	const arch_register_class_t *cls;
	be_reg_data_t               *reg_data;
93
94
} be_node_attr_t;

Sebastian Hack's avatar
Sebastian Hack committed
95
96
97
98
99
100
typedef struct {
	be_node_attr_t node_attr;
	int offset;           /**< The offset by which the stack shall be increased/decreased. */
	be_stack_dir_t dir;   /**< The direction in which the stack shall be modified (along or in the other direction). */
} be_stack_attr_t;

101
102
103
104
105
106
107
108
109
110
111
typedef struct {
	be_node_attr_t node_attr;
	entity *ent;
	int offset;
} be_frame_attr_t;

typedef struct {
	be_frame_attr_t frame_attr;
	ir_node *spill_ctx;  /**< The node in whose context this spill was introduced. */
} be_spill_attr_t;

Sebastian Hack's avatar
Sebastian Hack committed
112
113
114
115
116
static ir_op *op_Spill;
static ir_op *op_Reload;
static ir_op *op_Perm;
static ir_op *op_Copy;
static ir_op *op_Keep;
Sebastian Hack's avatar
Sebastian Hack committed
117
static ir_op *op_Call;
Sebastian Hack's avatar
Sebastian Hack committed
118
static ir_op *op_Return;
Sebastian Hack's avatar
Sebastian Hack committed
119
120
static ir_op *op_IncSP;
static ir_op *op_AddSP;
Sebastian Hack's avatar
Sebastian Hack committed
121
122
static ir_op *op_RegParams;
static ir_op *op_StackParam;
123
124
125
static ir_op *op_FrameAddr;
static ir_op *op_FrameLoad;
static ir_op *op_FrameStore;
Sebastian Hack's avatar
Sebastian Hack committed
126

Sebastian Hack's avatar
Sebastian Hack committed
127
static int beo_base = -1;
Sebastian Hack's avatar
Sebastian Hack committed
128

Sebastian Hack's avatar
Sebastian Hack committed
129
static const ir_op_ops be_node_op_ops;
Sebastian Hack's avatar
Sebastian Hack committed
130

131
132
133
134
135
136
137
138
139
140
141
#define N   irop_flag_none
#define L   irop_flag_labeled
#define C   irop_flag_commutative
#define X   irop_flag_cfopcode
#define I   irop_flag_ip_cfopcode
#define F   irop_flag_fragile
#define Y   irop_flag_forking
#define H   irop_flag_highlevel
#define c   irop_flag_constlike
#define K   irop_flag_keep

Sebastian Hack's avatar
Sebastian Hack committed
142
143
void be_node_init(void) {
	static int inited = 0;
Sebastian Hack's avatar
Sebastian Hack committed
144

Sebastian Hack's avatar
Sebastian Hack committed
145
146
	if(inited)
		return;
Sebastian Hack's avatar
Sebastian Hack committed
147

Sebastian Hack's avatar
Sebastian Hack committed
148
	inited = 1;
Sebastian Hack's avatar
Sebastian Hack committed
149

150
151
	/* Acquire all needed opcodes. */
	beo_base = get_next_ir_opcodes(beo_Last - 1);
Sebastian Hack's avatar
Sebastian Hack committed
152

Sebastian Hack's avatar
Sebastian Hack committed
153
154
155
156
157
158
	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);
	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);
	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);
	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);
	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);
	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);
Sebastian Hack's avatar
Sebastian Hack committed
159
	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);
Sebastian Hack's avatar
Sebastian Hack committed
160
161
162
	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);
	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);
	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);
163
164
165
166
	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);
	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);
	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);
	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);
Sebastian Hack's avatar
Sebastian Hack committed
167
168
169
170
171
172
173

	set_op_tag(op_Spill,      &be_node_tag);
	set_op_tag(op_Reload,     &be_node_tag);
	set_op_tag(op_Perm,       &be_node_tag);
	set_op_tag(op_Copy,       &be_node_tag);
	set_op_tag(op_Keep,       &be_node_tag);
	set_op_tag(op_Call,       &be_node_tag);
Sebastian Hack's avatar
Sebastian Hack committed
174
	set_op_tag(op_Return,     &be_node_tag);
Sebastian Hack's avatar
Sebastian Hack committed
175
176
177
178
	set_op_tag(op_AddSP,      &be_node_tag);
	set_op_tag(op_IncSP,      &be_node_tag);
	set_op_tag(op_RegParams,  &be_node_tag);
	set_op_tag(op_StackParam, &be_node_tag);
179
180
181
	set_op_tag(op_FrameLoad,  &be_node_tag);
	set_op_tag(op_FrameStore, &be_node_tag);
	set_op_tag(op_FrameAddr,  &be_node_tag);
Sebastian Hack's avatar
Sebastian Hack committed
182
}
183

Sebastian Hack's avatar
Sebastian Hack committed
184
static void *init_node_attr(ir_node* irn, const arch_register_class_t *cls, ir_graph *irg, int max_reg_data)
Sebastian Hack's avatar
Sebastian Hack committed
185
186
187
{
	be_node_attr_t *a = get_irn_attr(irn);

Sebastian Hack's avatar
Sebastian Hack committed
188
189
190
	a->max_reg_data = max_reg_data;
	a->cls          = cls;
	a->reg_data     = NULL;
Sebastian Hack's avatar
Sebastian Hack committed
191

Sebastian Hack's avatar
Sebastian Hack committed
192
	if(max_reg_data > 0) {
Sebastian Hack's avatar
Sebastian Hack committed
193
194
		int i;

Sebastian Hack's avatar
Sebastian Hack committed
195
196
197
		a->reg_data = NEW_ARR_D(be_reg_data_t, get_irg_obstack(irg), max_reg_data);
		memset(a->reg_data, 0, max_reg_data * sizeof(a->reg_data[0]));
		for(i = 0; i < max_reg_data; ++i) {
Sebastian Hack's avatar
Sebastian Hack committed
198
199
			a->reg_data[i].req.req.cls  = cls;
			a->reg_data[i].req.req.type = arch_register_req_type_normal;
Sebastian Hack's avatar
Sebastian Hack committed
200
201
202
203
204
		}
	}

	return a;
}
205

206
207
static INLINE int is_be_node(const ir_node *irn)
{
Sebastian Hack's avatar
Sebastian Hack committed
208
	return get_op_tag(get_irn_op(irn)) == &be_node_tag;
209
210
}

Sebastian Hack's avatar
Sebastian Hack committed
211
be_opcode_t be_get_irn_opcode(const ir_node *irn)
212
{
Sebastian Hack's avatar
Sebastian Hack committed
213
	return is_be_node(irn) ? get_irn_opcode(irn) - beo_base : beo_NoBeOp;
214
215
}

Sebastian Hack's avatar
Sebastian Hack committed
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
static int redir_proj(const ir_node **node, int pos)
{
	const ir_node *n = *node;

	if(is_Proj(n)) {
		assert(pos == -1 && "Illegal pos for a Proj");
		*node = get_Proj_pred(n);
		return get_Proj_proj(n);
	}

	return 0;
}

static void
be_node_set_irn_reg(const void *_self, ir_node *irn, const arch_register_t *reg)
{
	int out_pos;
	be_node_attr_t *a;

	out_pos = redir_proj((const ir_node **) &irn, -1);
	a       = get_irn_attr(irn);

	assert(is_be_node(irn));
Sebastian Hack's avatar
Sebastian Hack committed
239
	assert(out_pos < a->max_reg_data && "position too high");
Sebastian Hack's avatar
Sebastian Hack committed
240
241
242
243
	a->reg_data[out_pos].reg = reg;
}


Sebastian Hack's avatar
Sebastian Hack committed
244
ir_node *be_new_Spill(const arch_register_class_t *cls, ir_graph *irg, ir_node *bl, ir_node *to_spill, ir_node *ctx)
245
{
Sebastian Hack's avatar
Sebastian Hack committed
246
247
248
	be_spill_attr_t *a;
	ir_node *in[1];
	ir_node *res;
249

Sebastian Hack's avatar
Sebastian Hack committed
250
251
252
	in[0] = to_spill;
	res   = new_ir_node(NULL, irg, bl, op_Spill, mode_M, 1, in);
	a     = init_node_attr(res, cls, irg, 0);
253
254
	a->frame_attr.ent = NULL;
	a->frame_attr.offset = 0;
Sebastian Hack's avatar
Sebastian Hack committed
255
256
257
	a->spill_ctx = ctx;
	return res;
}
258

Sebastian Hack's avatar
Sebastian Hack committed
259
ir_node *be_new_Reload(const arch_register_class_t *cls, ir_graph *irg, ir_node *bl, ir_mode *mode, ir_node *mem)
260
{
Sebastian Hack's avatar
Sebastian Hack committed
261
262
	ir_node *in[1];
	ir_node *res;
263

Sebastian Hack's avatar
Sebastian Hack committed
264
265
266
267
268
	in[0] = mem;
	res   = new_ir_node(NULL, irg, bl, op_Reload, mode, 1, in);
	init_node_attr(res, cls, irg, 1);
	return res;
}
269

Sebastian Hack's avatar
Sebastian Hack committed
270
271
272
273
274
275
ir_node *be_new_Perm(const arch_register_class_t *cls, ir_graph *irg, ir_node *bl, int n, ir_node *in[])
{
	ir_node *irn = new_ir_node(NULL, irg, bl, op_Perm, mode_T, n, in);
	init_node_attr(irn, cls, irg, n);
	return irn;
}
276

Sebastian Hack's avatar
Sebastian Hack committed
277
278
279
280
ir_node *be_new_Copy(const arch_register_class_t *cls, ir_graph *irg, ir_node *bl, ir_node *op)
{
	ir_node *in[1];
	ir_node *res;
281

Sebastian Hack's avatar
Sebastian Hack committed
282
283
284
285
	in[0] = op;
	res   = new_ir_node(NULL, irg, bl, op_Copy, get_irn_mode(op), 1, in);
	init_node_attr(res, cls, irg, 1);
	return res;
286
287
}

Sebastian Hack's avatar
Sebastian Hack committed
288
ir_node *be_new_Keep(const arch_register_class_t *cls, ir_graph *irg, ir_node *bl, int n, ir_node *in[])
Sebastian Hack's avatar
Sebastian Hack committed
289
{
Sebastian Hack's avatar
Sebastian Hack committed
290
	ir_node *irn;
Sebastian Hack's avatar
Sebastian Hack committed
291

Sebastian Hack's avatar
Sebastian Hack committed
292
293
294
295
	irn = new_ir_node(NULL, irg, bl, op_Keep, mode_ANY, n, in);
	init_node_attr(irn, cls, irg, 0);
	keep_alive(irn);
	return irn;
Sebastian Hack's avatar
Sebastian Hack committed
296
297
}

Sebastian Hack's avatar
Sebastian Hack committed
298
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[])
Sebastian Hack's avatar
Sebastian Hack committed
299
{
Sebastian Hack's avatar
Sebastian Hack committed
300
301
302
	int real_n = 3 + n;
	ir_node *irn;
	ir_node **real_in;
Sebastian Hack's avatar
Sebastian Hack committed
303

Sebastian Hack's avatar
Sebastian Hack committed
304
305
306
307
308
309
310
311
	real_in = malloc(sizeof(real_in[0]) * (real_n));

	real_in[0] = mem;
	real_in[1] = sp;
	real_in[2] = ptr;
	memcpy(&real_in[3], in, n * sizeof(in[0]));

	irn = new_ir_node(NULL, irg, bl, op_Call, mode_T, real_n, real_in);
Sebastian Hack's avatar
Sebastian Hack committed
312
	init_node_attr(irn, NULL, irg, (n_outs > real_n ? n_outs : real_n));
Sebastian Hack's avatar
Sebastian Hack committed
313
	return irn;
Sebastian Hack's avatar
Sebastian Hack committed
314
315
}

Sebastian Hack's avatar
Sebastian Hack committed
316
317
318
319
320
321
322
323
ir_node *be_new_Return(ir_graph *irg, ir_node *bl, int n, ir_node *in[])
{
	ir_node *irn = new_ir_node(NULL, irg, bl, op_Return, mode_X, n, in);
	init_node_attr(irn, NULL, irg, n);

	return irn;
}

324
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)
Sebastian Hack's avatar
Sebastian Hack committed
325
{
Sebastian Hack's avatar
Sebastian Hack committed
326
327
328
329
330
	be_stack_attr_t *a;
	ir_node *irn;
	ir_node *in[1];

	in[0]     = old_sp;
331
332
	in[1]     = mem;
	irn       = new_ir_node(NULL, irg, bl, op_IncSP, sp->reg_class->mode, 2, in);
Sebastian Hack's avatar
Sebastian Hack committed
333
334
335
336
	a         = init_node_attr(irn, sp->reg_class, irg, 1);
	a->dir    = dir;
	a->offset = offset;

Sebastian Hack's avatar
Sebastian Hack committed
337
	be_node_set_flags(irn, -1, arch_irn_flags_ignore);
Sebastian Hack's avatar
Sebastian Hack committed
338

Sebastian Hack's avatar
Sebastian Hack committed
339
340
	/* Set output constraint to stack register. */
	be_set_constr_single_reg(irn, -1, sp);
Sebastian Hack's avatar
Sebastian Hack committed
341
	be_node_set_irn_reg(NULL, irn, sp);
Sebastian Hack's avatar
Sebastian Hack committed
342
343

	return irn;
Sebastian Hack's avatar
Sebastian Hack committed
344
}
Sebastian Hack's avatar
Sebastian Hack committed
345

Sebastian Hack's avatar
Sebastian Hack committed
346
ir_node *be_new_AddSP(const arch_register_t *sp, ir_graph *irg, ir_node *bl, ir_node *old_sp, ir_node *op)
Sebastian Hack's avatar
Sebastian Hack committed
347
{
Sebastian Hack's avatar
Sebastian Hack committed
348
	be_node_attr_t *a;
Sebastian Hack's avatar
Sebastian Hack committed
349
350
351
352
353
354
	ir_node *irn;
	ir_node *in[2];

	in[0]    = old_sp;
	in[1]    = op;
	irn      = new_ir_node(NULL, irg, bl, op_AddSP, sp->reg_class->mode, 2, in);
Sebastian Hack's avatar
Sebastian Hack committed
355
	a        = init_node_attr(irn, sp->reg_class, irg, 1);
Sebastian Hack's avatar
Sebastian Hack committed
356
357

	be_node_set_flags(irn, -1, arch_irn_flags_ignore);
Sebastian Hack's avatar
Sebastian Hack committed
358
359
360

	/* Set output constraint to stack register. */
	be_set_constr_single_reg(irn, -1, sp);
Sebastian Hack's avatar
Sebastian Hack committed
361
	be_node_set_irn_reg(NULL, irn, sp);
Sebastian Hack's avatar
Sebastian Hack committed
362
363

	return irn;
Sebastian Hack's avatar
Sebastian Hack committed
364
}
Sebastian Hack's avatar
Sebastian Hack committed
365

366
ir_node *be_new_StackParam(const arch_register_class_t *cls, ir_graph *irg, ir_node *bl, ir_mode *mode, ir_node *frame_pointer, entity *ent)
Sebastian Hack's avatar
Sebastian Hack committed
367
{
368
	be_frame_attr_t *a;
Sebastian Hack's avatar
Sebastian Hack committed
369
370
371
	ir_node *irn;
	ir_node *in[1];

372
373
374
375
	in[0] = frame_pointer;
	irn = new_ir_node(NULL, irg, bl, op_StackParam, mode, 1, in);
	a = init_node_attr(irn, cls, irg, 1);
	a->ent = ent;
Sebastian Hack's avatar
Sebastian Hack committed
376
	return irn;
Sebastian Hack's avatar
Sebastian Hack committed
377
}
Sebastian Hack's avatar
Sebastian Hack committed
378

379
ir_node *be_new_RegParams(ir_graph *irg, ir_node *bl, int n_outs)
Sebastian Hack's avatar
Sebastian Hack committed
380
381
382
383
{
	ir_node *irn;
	ir_node *in[1];

384
385
	irn = new_ir_node(NULL, irg, bl, op_RegParams, mode_T, 0, in);
	init_node_attr(irn, NULL, irg, n_outs);
Sebastian Hack's avatar
Sebastian Hack committed
386
387
388
	return irn;
}

389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
ir_node *be_new_FrameLoad(const arch_register_class_t *cls_frame, const arch_register_class_t *cls_data,
						  ir_graph *irg, ir_node *bl, ir_node *mem, ir_node *frame, entity *ent)
{
	be_frame_attr_t *a;
	ir_node *irn;
	ir_node *in[2];

	in[0]  = mem;
	in[1]  = frame;
	irn    = new_ir_node(NULL, irg, bl, op_FrameLoad, mode_T, 2, in);
	a      = init_node_attr(irn, NULL, irg, 3);
	a->ent = ent;
	a->offset = 0;
	be_node_set_reg_class(irn, 1, cls_frame);
	be_node_set_reg_class(irn, -(pn_Load_res + 1), cls_data);
	return irn;
}

ir_node *be_new_FrameStore(const arch_register_class_t *cls_frame, const arch_register_class_t *cls_data,
						   ir_graph *irg, ir_node *bl, ir_node *mem, ir_node *frame, ir_node *data, entity *ent)
{
	be_frame_attr_t *a;
	ir_node *irn;
	ir_node *in[3];

	in[0]  = mem;
	in[1]  = frame;
	in[2]  = data;
	irn    = new_ir_node(NULL, irg, bl, op_FrameStore, mode_T, 3, in);
	a      = init_node_attr(irn, NULL, irg, 3);
	a->ent = ent;
	a->offset = 0;
	be_node_set_reg_class(irn, 1, cls_frame);
	be_node_set_reg_class(irn, 2, cls_data);
	return irn;
}

ir_node *be_new_FrameAddr(const arch_register_class_t *cls_frame, ir_graph *irg, ir_node *bl, ir_node *frame, entity *ent)
Sebastian Hack's avatar
Sebastian Hack committed
427
{
428
	be_frame_attr_t *a;
Sebastian Hack's avatar
Sebastian Hack committed
429
430
431
	ir_node *irn;
	ir_node *in[1];

432
433
434
435
436
437
438
	in[0]  = frame;
	irn    = new_ir_node(NULL, irg, bl, op_FrameAddr, get_irn_mode(frame), 1, in);
	a      = init_node_attr(irn, NULL, irg, 1);
	a->ent = ent;
	a->offset = 0;
	be_node_set_reg_class(irn, 0, cls_frame);
	be_node_set_reg_class(irn, -1, cls_frame);
Sebastian Hack's avatar
Sebastian Hack committed
439
440
441
	return irn;
}

Sebastian Hack's avatar
Sebastian Hack committed
442
443
444
445
446
447
448
449
450
451
452
int be_is_Spill         (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Spill          ; }
int be_is_Reload        (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Reload         ; }
int be_is_Copy          (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Copy           ; }
int be_is_Perm          (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Perm           ; }
int be_is_Keep          (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Keep           ; }
int be_is_Call          (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Call           ; }
int be_is_Return        (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Return         ; }
int be_is_IncSP         (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_IncSP          ; }
int be_is_AddSP         (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_AddSP          ; }
int be_is_RegParams     (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_RegParams      ; }
int be_is_StackParam    (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_StackParam     ; }
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
int be_is_FrameAddr     (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_FrameAddr      ; }
int be_is_FrameLoad     (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_FrameLoad      ; }
int be_is_FrameStore    (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_FrameStore     ; }

int be_has_frame_entity(const ir_node *irn)
{
	switch(be_get_irn_opcode(irn)) {
	case beo_StackParam:
	case beo_Spill:
	case beo_FrameStore:
	case beo_FrameLoad:
	case beo_FrameAddr:
		return 1;
	}

	return 0;
}

471
entity *be_get_frame_entity(const ir_node *irn)
472
473
474
475
476
477
478
479
480
481
482
{
	if(be_has_frame_entity(irn)) {
		be_frame_attr_t *a = get_irn_attr(irn);
		return a->ent;
	}

	else if(be_get_irn_opcode(irn) == beo_Reload)
		return be_get_spill_entity(irn);

	return NULL;
}
Sebastian Hack's avatar
Sebastian Hack committed
483

Sebastian Hack's avatar
Sebastian Hack committed
484
static void be_limited(void *data, bitset_t *bs)
Sebastian Hack's avatar
Sebastian Hack committed
485
{
Sebastian Hack's avatar
Sebastian Hack committed
486
487
	be_req_t *req = data;

Sebastian Hack's avatar
Sebastian Hack committed
488
489
490
491
492
493
494
495
496
497
498
499
	switch(req->kind) {
	case be_req_kind_negate_old_limited:
	case be_req_kind_old_limited:
		req->x.old_limited.old_limited(req->x.old_limited.old_limited_env, bs);
		if(req->kind == be_req_kind_negate_old_limited)
			bitset_flip_all(bs);
		break;
	case be_req_kind_single_reg:
		bitset_clear_all(bs);
		bitset_set(bs, req->x.single_reg->index);
		break;
	}
Sebastian Hack's avatar
Sebastian Hack committed
500
501
}

Sebastian Hack's avatar
Sebastian Hack committed
502
static INLINE be_req_t *get_req(ir_node *irn, int pos)
Sebastian Hack's avatar
Sebastian Hack committed
503
{
Michael Beck's avatar
Michael Beck committed
504
	int idx           = pos < 0 ? -(pos + 1) : pos;
Sebastian Hack's avatar
Sebastian Hack committed
505
506
507
508
509
510
	be_node_attr_t *a = get_irn_attr(irn);
	be_reg_data_t *rd = &a->reg_data[idx];
	be_req_t       *r = pos < 0 ? &rd->req : &rd->in_req;

	assert(is_be_node(irn));
	assert(!(pos >= 0) || pos < get_irn_arity(irn));
Sebastian Hack's avatar
Sebastian Hack committed
511
	assert(!(pos < 0)  || -(pos + 1) <= a->max_reg_data);
Sebastian Hack's avatar
Sebastian Hack committed
512

Sebastian Hack's avatar
Sebastian Hack committed
513
514
515
516
517
518
519
	return r;
}

void be_set_constr_single_reg(ir_node *irn, int pos, const arch_register_t *reg)
{
	be_req_t *r = get_req(irn, pos);

Sebastian Hack's avatar
Sebastian Hack committed
520
521
522
523
524
525
526
527
	r->kind            = be_req_kind_single_reg;
	r->x.single_reg    = reg;
	r->req.limited     = be_limited;
	r->req.limited_env = r;
	r->req.type        = arch_register_req_type_limited;
	r->req.cls         = reg->reg_class;
}

528
529
void be_set_constr_limited(ir_node *irn, int pos, const arch_register_req_t *req)
{
Sebastian Hack's avatar
Sebastian Hack committed
530
	be_req_t *r = get_req(irn, pos);
531
532
533
534
535
536
537
538
539
540
541
542
543

	assert(arch_register_req_is(req, limited));

	r->kind            = be_req_kind_old_limited;
	r->req.limited     = be_limited;
	r->req.limited_env = r;
	r->req.type        = arch_register_req_type_limited;
	r->req.cls         = req->cls;

	r->x.old_limited.old_limited     = req->limited;
	r->x.old_limited.old_limited_env = req->limited_env;
}

Sebastian Hack's avatar
Sebastian Hack committed
544
545
546
547
548
549
550
551
552
553
554
555
void be_node_set_flags(ir_node *irn, int pos, arch_irn_flags_t flags)
{
	be_req_t *r = get_req(irn, pos);
	r->flags = flags;
}

void be_node_set_reg_class(ir_node *irn, int pos, const arch_register_class_t *cls)
{
	be_req_t *r = get_req(irn, pos);
	r->req.cls = cls;
}

Sebastian Hack's avatar
Sebastian Hack committed
556
557
558
559
560
561
void be_set_IncSP_offset(ir_node *irn, unsigned offset)
{
	be_stack_attr_t *a = get_irn_attr(irn);
	assert(be_is_IncSP(irn));
	a->offset = offset;
}
562

Sebastian Hack's avatar
Sebastian Hack committed
563
unsigned be_get_IncSP_offset(ir_node *irn)
Sebastian Hack's avatar
Sebastian Hack committed
564
{
Sebastian Hack's avatar
Sebastian Hack committed
565
566
567
568
	be_stack_attr_t *a = get_irn_attr(irn);
	assert(be_is_IncSP(irn));
	return a->offset;
}
Sebastian Hack's avatar
Sebastian Hack committed
569

Sebastian Hack's avatar
Sebastian Hack committed
570
571
572
573
574
void be_set_IncSP_direction(ir_node *irn, be_stack_dir_t dir)
{
	be_stack_attr_t *a = get_irn_attr(irn);
	assert(be_is_IncSP(irn));
	a->dir = dir;
Sebastian Hack's avatar
Sebastian Hack committed
575
576
}

Sebastian Hack's avatar
Sebastian Hack committed
577
be_stack_dir_t be_get_IncSP_direction(ir_node *irn)
Sebastian Hack's avatar
Sebastian Hack committed
578
{
Sebastian Hack's avatar
Sebastian Hack committed
579
580
581
	be_stack_attr_t *a = get_irn_attr(irn);
	assert(be_is_IncSP(irn));
	return a->dir;
Sebastian Hack's avatar
Sebastian Hack committed
582
583
}

584
void be_set_Spill_entity(ir_node *irn, entity *ent)
585
{
Sebastian Hack's avatar
Sebastian Hack committed
586
587
	be_spill_attr_t *a = get_irn_attr(irn);
	assert(be_is_Spill(irn));
588
	a->frame_attr.ent = ent;
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
}

static ir_node *find_a_spill_walker(ir_node *irn, unsigned visited_nr)
{
	if(get_irn_visited(irn) < visited_nr) {
		set_irn_visited(irn, visited_nr);

		if(is_Phi(irn)) {
			int i, n;
			for(i = 0, n = get_irn_arity(irn); i < n; ++i) {
				ir_node *n = find_a_spill_walker(get_irn_n(irn, i), visited_nr);
				if(n != NULL)
					return n;
			}
		}

Sebastian Hack's avatar
Sebastian Hack committed
605
		else if(be_get_irn_opcode(irn) == beo_Spill)
606
607
608
609
610
611
			return irn;
	}

	return NULL;
}

Sebastian Hack's avatar
Sebastian Hack committed
612
613
614
ir_node *be_get_Spill_context(const ir_node *irn) {
	const be_spill_attr_t *a = get_irn_attr(irn);
	assert(be_is_Spill(irn));
615
616
617
	return a->spill_ctx;
}

618
619
620
621
622
623
/**
 * Finds a spill for a reload.
 * If the reload is directly using the spill, this is simple,
 * else we perform DFS from the reload (over all PhiMs) and return
 * the first spill node we find.
 */
624
static INLINE ir_node *find_a_spill(const ir_node *irn)
625
626
627
628
{
	ir_graph *irg       = get_irn_irg(irn);
	unsigned visited_nr = get_irg_visited(irg) + 1;

Sebastian Hack's avatar
Sebastian Hack committed
629
	assert(be_is_Reload(irn));
630
	set_irg_visited(irg, visited_nr);
631
	return find_a_spill_walker((ir_node *)irn, visited_nr);
632
633
}

634
entity *be_get_spill_entity(const ir_node *irn)
635
{
Sebastian Hack's avatar
Sebastian Hack committed
636
	int opc           = get_irn_opcode(irn);
637

Sebastian Hack's avatar
Sebastian Hack committed
638
	switch(be_get_irn_opcode(irn)) {
Sebastian Hack's avatar
Sebastian Hack committed
639
	case beo_Reload:
640
		return be_get_spill_entity(find_a_spill(irn));
Sebastian Hack's avatar
Sebastian Hack committed
641
642
643
	case beo_Spill:
		{
			be_spill_attr_t *a = get_irn_attr(irn);
644
			return a->frame_attr.ent;
Sebastian Hack's avatar
Sebastian Hack committed
645
		}
646
	default:
Sebastian Hack's avatar
Sebastian Hack committed
647
		assert(0 && "Must give spill/reload node");
648
649
	}

650
	return NULL;
Sebastian Hack's avatar
Sebastian Hack committed
651
652
}

Sebastian Hack's avatar
Sebastian Hack committed
653
ir_node *be_spill(const arch_env_t *arch_env, ir_node *irn, ir_node *ctx)
Sebastian Hack's avatar
Sebastian Hack committed
654
{
Christian Würdig's avatar
Christian Würdig committed
655
	const arch_register_class_t *cls = arch_get_irn_reg_class(arch_env, irn, -1);
656

Christian Würdig's avatar
Christian Würdig committed
657
658
	ir_node *bl    = get_nodes_block(irn);
	ir_graph *irg  = get_irn_irg(bl);
Sebastian Hack's avatar
Sebastian Hack committed
659
	ir_node *spill = be_new_Spill(cls, irg, bl, irn, ctx);
Sebastian Hack's avatar
Sebastian Hack committed
660
661
662
663
664
665
666
667
668
669
670
671
	ir_node *insert;

	/*
	 * search the right insertion point. a spill of a phi cannot be put
	 * directly after the phi, if there are some phis behind the one which
	 * is spilled.
	 */
	insert = sched_next(irn);
	while(is_Phi(insert) && !sched_is_end(insert))
		insert = sched_next(insert);

	sched_add_before(insert, spill);
Christian Würdig's avatar
Christian Würdig committed
672
	return spill;
Sebastian Hack's avatar
Sebastian Hack committed
673
674
}

Sebastian Hack's avatar
Sebastian Hack committed
675
676
677
ir_node *be_reload(const arch_env_t *arch_env,
				   const arch_register_class_t *cls,
				   ir_node *irn, int pos, ir_mode *mode, ir_node *spill)
Sebastian Hack's avatar
Sebastian Hack committed
678
679
680
{
	ir_node *reload;

Christian Würdig's avatar
Christian Würdig committed
681
682
	ir_node *bl   = get_nodes_block(irn);
	ir_graph *irg = get_irn_irg(bl);
Sebastian Hack's avatar
Sebastian Hack committed
683

Sebastian Hack's avatar
Sebastian Hack committed
684
	assert(be_is_Spill(spill) || (is_Phi(spill) && get_irn_mode(spill) == mode_M));
Sebastian Hack's avatar
Sebastian Hack committed
685

Sebastian Hack's avatar
Sebastian Hack committed
686
	reload = be_new_Reload(cls, irg, bl, mode, spill);
Sebastian Hack's avatar
Sebastian Hack committed
687

Sebastian Hack's avatar
Sebastian Hack committed
688
	set_irn_n(irn, pos, reload);
Christian Würdig's avatar
Christian Würdig committed
689
690
	sched_add_before(irn, reload);
	return reload;
Sebastian Hack's avatar
Sebastian Hack committed
691
}
Sebastian Hack's avatar
Sebastian Hack committed
692

Sebastian Hack's avatar
Sebastian Hack committed
693
static void *put_out_reg_req(arch_register_req_t *req, const ir_node *irn, int out_pos)
Sebastian Hack's avatar
Sebastian Hack committed
694
{
Sebastian Hack's avatar
Sebastian Hack committed
695
	const be_node_attr_t *a = get_irn_attr(irn);
Daniel Grund's avatar
Daniel Grund committed
696

Sebastian Hack's avatar
Sebastian Hack committed
697
	if(out_pos < a->max_reg_data)
Sebastian Hack's avatar
Sebastian Hack committed
698
699
700
701
		memcpy(req, &a->reg_data[out_pos].req, sizeof(req[0]));
	else {
		req->type = arch_register_req_type_none;
		req->cls  = NULL;
Sebastian Hack's avatar
Sebastian Hack committed
702
	}
Sebastian Hack's avatar
Sebastian Hack committed
703

Sebastian Hack's avatar
Sebastian Hack committed
704
	return req;
Sebastian Hack's avatar
Sebastian Hack committed
705
706
}

Sebastian Hack's avatar
Sebastian Hack committed
707
static void *put_in_reg_req(arch_register_req_t *req, const ir_node *irn, int pos)
708
{
Sebastian Hack's avatar
Sebastian Hack committed
709
710
711
	const be_node_attr_t *a = get_irn_attr(irn);
	int n                   = get_irn_arity(irn);

Sebastian Hack's avatar
Sebastian Hack committed
712
	if(pos < get_irn_arity(irn) && pos < a->max_reg_data)
Sebastian Hack's avatar
Sebastian Hack committed
713
714
715
716
		memcpy(req, &a->reg_data[pos].in_req, sizeof(req[0]));
	else {
		req->type = arch_register_req_type_none;
		req->cls  = NULL;
Sebastian Hack's avatar
Sebastian Hack committed
717
718
719
	}

	return req;
720
721
}

Sebastian Hack's avatar
Sebastian Hack committed
722
static const arch_register_req_t *
723
be_node_get_irn_reg_req(const void *self, arch_register_req_t *req, const ir_node *irn, int pos)
Sebastian Hack's avatar
Sebastian Hack committed
724
{
Sebastian Hack's avatar
Sebastian Hack committed
725
	int out_pos = pos;
Sebastian Hack's avatar
Sebastian Hack committed
726

Sebastian Hack's avatar
Sebastian Hack committed
727
728
729
	if(pos < 0) {
		if(get_irn_mode(irn) == mode_T)
			return NULL;
Daniel Grund's avatar
Daniel Grund committed
730

Sebastian Hack's avatar
Sebastian Hack committed
731
732
733
734
		out_pos = redir_proj((const ir_node **) &irn, pos);
		assert(is_be_node(irn));
		return put_out_reg_req(req, irn, out_pos);
	}
Daniel Grund's avatar
Daniel Grund committed
735

Sebastian Hack's avatar
Sebastian Hack committed
736
737
738
	else {
		return is_be_node(irn) ? put_in_reg_req(req, irn, pos) : NULL;
	}
Daniel Grund's avatar
Daniel Grund committed
739

Sebastian Hack's avatar
Sebastian Hack committed
740
	return req;
Sebastian Hack's avatar
Sebastian Hack committed
741
742
}

Sebastian Hack's avatar
Sebastian Hack committed
743
const arch_register_t *
744
be_node_get_irn_reg(const void *_self, const ir_node *irn)
Sebastian Hack's avatar
Sebastian Hack committed
745
746
747
{
	int out_pos;
	be_node_attr_t *a;
Daniel Grund's avatar
Daniel Grund committed
748

Christian Würdig's avatar
Christian Würdig committed
749
	out_pos = redir_proj((const ir_node **) &irn, -1);
Sebastian Hack's avatar
Sebastian Hack committed
750
	a       = get_irn_attr(irn);
Daniel Grund's avatar
Daniel Grund committed
751

Sebastian Hack's avatar
Sebastian Hack committed
752
	assert(is_be_node(irn));
Sebastian Hack's avatar
Sebastian Hack committed
753
	assert(out_pos < a->max_reg_data && "position too high");
Daniel Grund's avatar
Daniel Grund committed
754

Sebastian Hack's avatar
Sebastian Hack committed
755
	return a->reg_data[out_pos].reg;
Sebastian Hack's avatar
Sebastian Hack committed
756
757
}

Sebastian Hack's avatar
Sebastian Hack committed
758
static arch_irn_class_t be_node_classify(const void *_self, const ir_node *irn)
Sebastian Hack's avatar
Sebastian Hack committed
759
{
Christian Würdig's avatar
Christian Würdig committed
760
	redir_proj((const ir_node **) &irn, -1);
Sebastian Hack's avatar
Sebastian Hack committed
761

Sebastian Hack's avatar
Sebastian Hack committed
762
	switch(be_get_irn_opcode(irn)) {
Sebastian Hack's avatar
Sebastian Hack committed
763
764
765
766
767
#define XXX(a,b) case beo_ ## a: return arch_irn_class_ ## b;
		XXX(Spill, spill)
		XXX(Reload, reload)
		XXX(Perm, perm)
		XXX(Copy, copy)
Sebastian Hack's avatar
Sebastian Hack committed
768
#undef XXX
Sebastian Hack's avatar
Sebastian Hack committed
769
770
		default:
		return 0;
Sebastian Hack's avatar
Sebastian Hack committed
771
772
	}

Christian Würdig's avatar
Christian Würdig committed
773
	return 0;
Sebastian Hack's avatar
Sebastian Hack committed
774
775
}

Sebastian Hack's avatar
Sebastian Hack committed
776
static arch_irn_flags_t be_node_get_flags(const void *_self, const ir_node *irn)
Sebastian Hack's avatar
Sebastian Hack committed
777
{
Sebastian Hack's avatar
Sebastian Hack committed
778
	int out_pos;
Sebastian Hack's avatar
Sebastian Hack committed
779
780
	be_node_attr_t *a;

Sebastian Hack's avatar
Sebastian Hack committed
781
782
783
	out_pos = redir_proj((const ir_node **) &irn, -1);
	a       = get_irn_attr(irn);

Sebastian Hack's avatar
Sebastian Hack committed
784
	assert(is_be_node(irn));
Sebastian Hack's avatar
Sebastian Hack committed
785
786
787
	assert(out_pos < a->max_reg_data && "position too high");

	return a->reg_data[out_pos].req.flags;
Sebastian Hack's avatar
Sebastian Hack committed
788
789
}

790
791
792
793
794
static entity *be_node_get_frame_entity(const void *self, const ir_node *irn)
{
	return be_get_frame_entity(irn);
}

795
static void be_node_set_stack_bias(const void *self, ir_node *irn, int bias)
796
797
798
799
{
}


800
static const arch_irn_ops_if_t be_node_irn_ops_if = {
Sebastian Hack's avatar
Sebastian Hack committed
801
802
803
804
805
	be_node_get_irn_reg_req,
	be_node_set_irn_reg,
	be_node_get_irn_reg,
	be_node_classify,
	be_node_get_flags,
806
807
	be_node_get_frame_entity,
	be_node_set_stack_bias
Sebastian Hack's avatar
Sebastian Hack committed
808
};
809

810
811
812
813
814
static const arch_irn_ops_t be_node_irn_ops = {
	&be_node_irn_ops_if
};

const void *be_node_get_arch_ops(const arch_irn_handler_t *self, const ir_node *irn)
815
{
Sebastian Hack's avatar
Sebastian Hack committed
816
817
	redir_proj((const ir_node **) &irn, -1);
	return is_be_node(irn) ? &be_node_irn_ops : NULL;
Sebastian Hack's avatar
Sebastian Hack committed
818
819
}

Sebastian Hack's avatar
Sebastian Hack committed
820
821
822
const arch_irn_handler_t be_node_irn_handler = {
	be_node_get_arch_ops
};
Sebastian Hack's avatar
Sebastian Hack committed
823

Sebastian Hack's avatar
Sebastian Hack committed
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877

static void dump_node_req(FILE *f, be_req_t *req)
{
	int i;
	int did_something = 0;
	const char *suffix = "";

	if(req->flags != arch_irn_flags_none) {
		fprintf(f, "flags: ");
		for(i = arch_irn_flags_none; i <= log2_ceil(arch_irn_flags_last); ++i) {
			if(req->flags & (1 << i)) {
				fprintf(f, "%s%s", suffix, arch_irn_flag_str(1 << i));
				suffix = "|";
			}
		}
		suffix = ", ";
		did_something = 1;
	}

	if(req->req.cls != 0) {
		char tmp[256];
		fprintf(f, suffix);
		arch_register_req_format(tmp, sizeof(tmp), &req->req);
		fprintf(f, "%s", tmp);
		did_something = 1;
	}

	if(did_something)
		fprintf(f, "\n");
}

static void dump_node_reqs(FILE *f, ir_node *irn)
{
	int i;
	be_node_attr_t *a = get_irn_attr(irn);

	fprintf(f, "registers: \n");
	for(i = 0; i < a->max_reg_data; ++i) {
		be_reg_data_t *rd = &a->reg_data[i];
		if(rd->reg)
			fprintf(f, "#%d: %s\n", i, rd->reg->name);
	}

	fprintf(f, "in requirements\n");
	for(i = 0; i < a->max_reg_data; ++i) {
		dump_node_req(f, &a->reg_data[i].in_req);
	}

	fprintf(f, "\nout requirements\n");
	for(i = 0; i < a->max_reg_data; ++i) {
		dump_node_req(f, &a->reg_data[i].req);
	}
}

878
879
static int dump_node(ir_node *irn, FILE *f, dump_reason_t reason)
{
Sebastian Hack's avatar
Sebastian Hack committed
880
	be_node_attr_t *at = get_irn_attr(irn);
881

882
883
	assert(is_be_node(irn));

884
885
	switch(reason) {
		case dump_node_opcode_txt:
Sebastian Hack's avatar
Sebastian Hack committed
886
			fprintf(f, get_op_name(get_irn_op(irn)));
887
888
889
890
891
892
893
			break;
		case dump_node_mode_txt:
			fprintf(f, get_mode_name(get_irn_mode(irn)));
			break;
		case dump_node_nodeattr_txt:
			break;
		case dump_node_info_txt:
Sebastian Hack's avatar
Sebastian Hack committed
894
			dump_node_reqs(f, irn);
895

896
897
898
899
900
901
902
903
			if(be_has_frame_entity(irn)) {
				be_frame_attr_t *a = (be_frame_attr_t *) at;
				if (a->ent) {
					unsigned ofs = get_entity_offset_bytes(a->ent);
					ir_fprintf(f, "frame entity: %+F offset %x (%d)\n", a->ent, ofs, ofs);
				}
			}

Sebastian Hack's avatar
Sebastian Hack committed
904
			switch(be_get_irn_opcode(irn)) {
Sebastian Hack's avatar
Sebastian Hack committed
905
906
907
908
			case beo_Spill:
				{
					be_spill_attr_t *a = (be_spill_attr_t *) at;
					ir_fprintf(f, "spill context: %+F\n", a->spill_ctx);
Christian Würdig's avatar
Christian Würdig committed
909
				}
Sebastian Hack's avatar
Sebastian Hack committed
910
911
912
913
914
915
916
				break;

			case beo_IncSP:
				{
					be_stack_attr_t *a = (be_stack_attr_t *) at;
					fprintf(f, "offset: %u\n", a->offset);
					fprintf(f, "direction: %s\n", a->dir == be_stack_dir_along ? "along" : "against");
Christian Würdig's avatar
Christian Würdig committed
917
				}
Sebastian Hack's avatar
Sebastian Hack committed
918
				break;
919
			}
Sebastian Hack's avatar
Sebastian Hack committed
920

921
922
	}

923
	return 0;
924
925
}

Sebastian Hack's avatar
Sebastian Hack committed
926
927
928
929
/**
 * Copies the backend specific attributes from old node to new node.
 */
static void copy_attr(const ir_node *old_node, ir_node *new_node)
Sebastian Hack's avatar
Sebastian Hack committed
930
{
Sebastian Hack's avatar
Sebastian Hack committed
931
	be_node_attr_t *old_attr = get_irn_attr(old_node);
Sebastian Hack's avatar
Sebastian Hack committed
932
	be_node_attr_t *new_attr = get_irn_attr(new_node);
Sebastian Hack's avatar
Sebastian Hack committed
933
	int i;
Sebastian Hack's avatar
Sebastian Hack committed
934
935
936
937

	assert(is_be_node(old_node));
	assert(is_be_node(new_node));

Sebastian Hack's avatar
Sebastian Hack committed
938
939
	memcpy(new_attr, old_attr, get_op_attr_size(get_irn_op(old_node)));
	new_attr->reg_data = NULL;
Sebastian Hack's avatar
Sebastian Hack committed
940

Sebastian Hack's avatar
Sebastian Hack committed
941
942
943
	if(new_attr->max_reg_data > 0) {
		new_attr->reg_data = NEW_ARR_D(be_reg_data_t, get_irg_obstack(get_irn_irg(new_node)), new_attr->max_reg_data);
		memcpy(new_attr->reg_data, old_attr->reg_data, new_attr->max_reg_data * sizeof(be_reg_data_t));
Sebastian Hack's avatar
Sebastian Hack committed
944
945
946
947
948
949
950
951
952
953

		for(i = 0; i < old_attr->max_reg_data; ++i) {
			be_req_t *r;

			r = &new_attr->reg_data[i].req;
			r->req.limited_env = r;

			r = &new_attr->reg_data[i].in_req;
			r->req.limited_env = r;
		}
Sebastian Hack's avatar
Sebastian Hack committed
954
	}
Sebastian Hack's avatar
Sebastian Hack committed
955
956
}

Sebastian Hack's avatar
Sebastian Hack committed
957
958
959
960
961
962
static const ir_op_ops be_node_op_ops = {
	NULL,
	NULL,
	NULL,
	NULL,
	NULL,
Sebastian Hack's avatar
Sebastian Hack committed
963
	copy_attr,
Sebastian Hack's avatar
Sebastian Hack committed
964
965
966
967
968
969
970
971
972
	NULL,
	NULL,
	NULL,
	NULL,
	NULL,
	dump_node,
	NULL
};

Sebastian Hack's avatar
Sebastian Hack committed
973
pset *nodes_live_at(const arch_env_t *arch_env, const arch_register_class_t *cls, const ir_node *pos, pset *live)
Sebastian Hack's avatar
Sebastian Hack committed
974
{
Sebastian Hack's avatar
Sebastian Hack committed
975
	firm_dbg_module_t *dbg = firm_dbg_register("firm.be.node");
Christian Würdig's avatar
Christian Würdig committed
976
	const ir_node *bl      = is_Block(pos) ? pos : get_nodes_block(pos);
Sebastian Hack's avatar
Sebastian Hack committed
977
	ir_node *irn;
Christian Würdig's avatar
Christian Würdig committed
978
	irn_live_t *li;
Daniel Grund's avatar
Daniel Grund committed
979
980
981

	live_foreach(bl, li) {
		ir_node *irn = (ir_node *) li->irn;
Sebastian Hack's avatar
Sebastian Hack committed
982
		if(live_is_end(li) && arch_irn_consider_in_reg_alloc(arch_env, cls, irn))
Daniel Grund's avatar
Daniel Grund committed
983
984
985
			pset_insert_ptr(live, irn);
	}

Christian Würdig's avatar
Christian Würdig committed
986
	sched_foreach_reverse(bl, irn) {
Sebastian Hack's avatar
Sebastian Hack committed
987
		int i, n;
Christian Würdig's avatar
Christian Würdig committed
988
		ir_node *x;
Sebastian Hack's avatar
Sebastian Hack committed
989

Sebastian Hack's avatar
Sebastian Hack committed
990
991
992
993
		/*
		 * If we encounter the node we want to insert the Perm after,
		* exit immediately, so that this node is still live
		*/
Christian Würdig's avatar
Christian Würdig committed
994
		if(irn == pos)
Sebastian Hack's avatar
Sebastian Hack committed
995
			return live;
996

Christian Würdig's avatar
Christian Würdig committed
997
998
999
		DBG((dbg, LEVEL_1, "%+F\n", irn));
		for(x = pset_first(live); x; x = pset_next(live))
			DBG((dbg, LEVEL_1, "\tlive: %+F\n", x));
1000

1001
		if(arch_irn_consider_in_reg_alloc(arch_env, cls, irn))
Christian Würdig's avatar
Christian Würdig committed
1002
			pset_remove_ptr(live, irn);
1003

Christian Würdig's avatar
Christian Würdig committed
1004
1005
		for(i = 0, n = get_irn_arity(irn); i < n; ++i) {
			ir_node *op = get_irn_n(irn, i);
1006

Sebastian Hack's avatar
Sebastian Hack committed
1007
			if(arch_irn_consider_in_reg_alloc(arch_env, cls, op))
Christian Würdig's avatar
Christian Würdig committed
1008
1009
1010
				pset_insert_ptr(live, op);
		}
	}
Sebastian Hack's avatar
Sebastian Hack committed
1011

Christian Würdig's avatar
Christian Würdig committed
1012
	return live;
Sebastian Hack's avatar
Sebastian Hack committed
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
}

ir_node *insert_Perm_after(const arch_env_t *arch_env,
						   const arch_register_class_t *cls,
						   dom_front_info_t *dom_front,
						   ir_node *pos)
{
	ir_node *bl                 = is_Block(pos) ? pos : get_nodes_block(pos);
	ir_graph *irg               = get_irn_irg(bl);
	pset *live                  = pset_new_ptr_default();
	firm_dbg_module_t *dbg      = firm_dbg_register("be.node");

	ir_node *curr, *irn, *perm, **nodes;
	int i, n;

	DBG((dbg, LEVEL_1, "Insert Perm after: %+F\n", pos));

Christian Würdig's avatar
Christian Würdig committed
1030
	if(!nodes_live_at(arch_env, cls, pos, live));
Sebastian Hack's avatar
Sebastian Hack committed
1031

Christian Würdig's avatar
Christian Würdig committed
1032
	n = pset_count(live);
1033
1034
1035
1036

	if(n == 0)
		return NULL;

Christian Würdig's avatar
Christian Würdig committed
1037
	nodes = malloc(n * sizeof(nodes[0]));
Sebastian Hack's avatar
Sebastian Hack committed
1038

Christian Würdig's avatar
Christian Würdig committed
1039
1040
1041
1042
1043
	DBG((dbg, LEVEL_1, "live:\n"));
	for(irn = pset_first(live), i = 0; irn; irn = pset_next(live), i++) {
		DBG((dbg, LEVEL_1, "\t%+F\n", irn));
		nodes[i] = irn;
	}
1044

Sebastian Hack's avatar
Sebastian Hack committed
1045
	perm = be_new_Perm(cls, irg, bl, n, nodes);
Christian Würdig's avatar
Christian Würdig committed
1046
1047
	sched_add_after(pos, perm);
	free(nodes);
1048

Christian Würdig's avatar
Christian Würdig committed
1049
1050
	curr = perm;
	for(i = 0; i < n; ++i) {
Sebastian Hack's avatar
Sebastian Hack committed
1051
		ir_node *copies[2];
Christian Würdig's avatar
Christian Würdig committed
1052
		ir_node *perm_op = get_irn_n(perm, i);
1053
		const arch_register_t *reg = arch_get_irn_register(arch_env, perm_op);
1054

Christian Würdig's avatar
Christian Würdig committed
1055
1056
1057
		ir_mode *mode = get_irn_mode(perm_op);
		ir_node *proj = new_r_Proj(irg, bl, perm, mode, i);
		arch_set_irn_register(arch_env, proj, reg);