benode.c 31.3 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
#include "irgwalk.h"
Sebastian Hack's avatar
Sebastian Hack committed
34

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

40
41
#include "beirgmod.h"

Sebastian Hack's avatar
Sebastian Hack committed
42
43
#define OUT_POS(x) (-((x) + 1))

Sebastian Hack's avatar
Sebastian Hack committed
44
45
/* 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
46

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

Sebastian Hack's avatar
Sebastian Hack committed
49
#if 0
Sebastian Hack's avatar
Sebastian Hack committed
50
typedef enum _node_kind_t {
Christian Würdig's avatar
Christian Würdig committed
51
52
53
54
	node_kind_spill,
	node_kind_reload,
	node_kind_perm,
	node_kind_copy,
Sebastian Hack's avatar
Sebastian Hack committed
55
	node_kind_kill,
Christian Würdig's avatar
Christian Würdig committed
56
	node_kind_last
Sebastian Hack's avatar
Sebastian Hack committed
57
} node_kind_t;
Sebastian Hack's avatar
Sebastian Hack committed
58
#endif
Sebastian Hack's avatar
Sebastian Hack committed
59

Sebastian Hack's avatar
Sebastian Hack committed
60
61
62
63
64
65
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
66
67
typedef struct {
	arch_register_req_t req;
Sebastian Hack's avatar
Sebastian Hack committed
68
	be_req_kind_t       kind;
Sebastian Hack's avatar
Sebastian Hack committed
69
	arch_irn_flags_t    flags;
Sebastian Hack's avatar
Sebastian Hack committed
70
71
72
73
74
75
76
77
	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
78
79
} be_req_t;

80
typedef struct {
81
	const arch_register_t *reg;
Sebastian Hack's avatar
Sebastian Hack committed
82
	be_req_t              req;
Sebastian Hack's avatar
Sebastian Hack committed
83
	be_req_t              in_req;
84
85
86
} be_reg_data_t;

typedef struct {
Sebastian Hack's avatar
Sebastian Hack committed
87
	int                         max_reg_data;
Sebastian Hack's avatar
Sebastian Hack committed
88
	be_reg_data_t               *reg_data;
89
90
} be_node_attr_t;

Sebastian Hack's avatar
Sebastian Hack committed
91
92
93
94
95
96
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;

97
98
99
100
101
102
typedef struct {
	be_node_attr_t node_attr;
	entity *ent;
	int offset;
} be_frame_attr_t;

103
104
105
106
107
typedef struct {
	be_node_attr_t node_attr;
	entity *ent;
} be_call_attr_t;

108
109
110
111
112
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;

113
114
115
116
117
118
119
120
ir_op *op_be_Spill;
ir_op *op_be_Reload;
ir_op *op_be_Perm;
ir_op *op_be_Copy;
ir_op *op_be_Keep;
ir_op *op_be_Call;
ir_op *op_be_Return;
ir_op *op_be_IncSP;
121
ir_op *op_be_Alloca;
122
123
124
125
126
127
ir_op *op_be_SetSP;
ir_op *op_be_RegParams;
ir_op *op_be_StackParam;
ir_op *op_be_FrameAddr;
ir_op *op_be_FrameLoad;
ir_op *op_be_FrameStore;
Sebastian Hack's avatar
Sebastian Hack committed
128

Sebastian Hack's avatar
Sebastian Hack committed
129
static int beo_base = -1;
Sebastian Hack's avatar
Sebastian Hack committed
130

Sebastian Hack's avatar
Sebastian Hack committed
131
static const ir_op_ops be_node_op_ops;
Sebastian Hack's avatar
Sebastian Hack committed
132

133
134
135
136
137
138
139
140
141
142
143
#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
144
145
void be_node_init(void) {
	static int inited = 0;
Sebastian Hack's avatar
Sebastian Hack committed
146

Sebastian Hack's avatar
Sebastian Hack committed
147
148
	if(inited)
		return;
Sebastian Hack's avatar
Sebastian Hack committed
149

Sebastian Hack's avatar
Sebastian Hack committed
150
	inited = 1;
Sebastian Hack's avatar
Sebastian Hack committed
151

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

155
	op_be_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);
156
	op_be_Reload     = new_ir_op(beo_base + beo_Reload,     "Reload",     op_pin_state_mem_pinned, N, oparity_zero,     0, sizeof(be_frame_attr_t), &be_node_op_ops);
157
158
159
	op_be_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_be_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_be_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);
Sebastian Hack's avatar
Sebastian Hack committed
160
	op_be_Call       = new_ir_op(beo_base + beo_Call,       "Call",       op_pin_state_pinned,     N, oparity_variable, 0, sizeof(be_call_attr_t),  &be_node_op_ops);
161
	op_be_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);
162
	op_be_Alloca     = new_ir_op(beo_base + beo_Alloca,     "Alloca",     op_pin_state_pinned,     N, oparity_unary,    0, sizeof(be_node_attr_t),  &be_node_op_ops);
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
	op_be_SetSP      = new_ir_op(beo_base + beo_SetSP,      "SetSP",      op_pin_state_pinned,     N, oparity_binary,   0, sizeof(be_stack_attr_t), &be_node_op_ops);
	op_be_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_be_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);
	op_be_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_be_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_be_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_be_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);

	set_op_tag(op_be_Spill,      &be_node_tag);
	set_op_tag(op_be_Reload,     &be_node_tag);
	set_op_tag(op_be_Perm,       &be_node_tag);
	set_op_tag(op_be_Copy,       &be_node_tag);
	set_op_tag(op_be_Keep,       &be_node_tag);
	set_op_tag(op_be_Call,       &be_node_tag);
	set_op_tag(op_be_Return,     &be_node_tag);
178
	set_op_tag(op_be_Alloca,     &be_node_tag);
179
180
181
182
183
184
185
	set_op_tag(op_be_SetSP,      &be_node_tag);
	set_op_tag(op_be_IncSP,      &be_node_tag);
	set_op_tag(op_be_RegParams,  &be_node_tag);
	set_op_tag(op_be_StackParam, &be_node_tag);
	set_op_tag(op_be_FrameLoad,  &be_node_tag);
	set_op_tag(op_be_FrameStore, &be_node_tag);
	set_op_tag(op_be_FrameAddr,  &be_node_tag);
Sebastian Hack's avatar
Sebastian Hack committed
186
}
187

Sebastian Hack's avatar
Sebastian Hack committed
188
static void *init_node_attr(ir_node* irn, int max_reg_data)
Sebastian Hack's avatar
Sebastian Hack committed
189
{
Sebastian Hack's avatar
Sebastian Hack committed
190
	ir_graph *irg     = get_irn_irg(irn);
Sebastian Hack's avatar
Sebastian Hack committed
191
192
	be_node_attr_t *a = get_irn_attr(irn);

193
	memset(a, 0, sizeof(get_op_attr_size(get_irn_op(irn))));
Sebastian Hack's avatar
Sebastian Hack committed
194
195
	a->max_reg_data = max_reg_data;
	a->reg_data     = NULL;
Sebastian Hack's avatar
Sebastian Hack committed
196

Sebastian Hack's avatar
Sebastian Hack committed
197
	if(max_reg_data > 0) {
Sebastian Hack's avatar
Sebastian Hack committed
198
199
		int i;

Sebastian Hack's avatar
Sebastian Hack committed
200
201
202
		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
203
204
			a->reg_data[i].req.req.cls  = NULL;
			a->reg_data[i].req.req.type = arch_register_req_type_none;
Sebastian Hack's avatar
Sebastian Hack committed
205
206
207
208
209
		}
	}

	return a;
}
210

211
212
static INLINE int is_be_node(const ir_node *irn)
{
Sebastian Hack's avatar
Sebastian Hack committed
213
	return get_op_tag(get_irn_op(irn)) == &be_node_tag;
214
215
}

Sebastian Hack's avatar
Sebastian Hack committed
216
be_opcode_t be_get_irn_opcode(const ir_node *irn)
217
{
Sebastian Hack's avatar
Sebastian Hack committed
218
	return is_be_node(irn) ? get_irn_opcode(irn) - beo_base : beo_NoBeOp;
219
220
}

Sebastian Hack's avatar
Sebastian Hack committed
221
222
223
224
225
static int redir_proj(const ir_node **node, int pos)
{
	const ir_node *n = *node;

	if(is_Proj(n)) {
226
227
		ir_node *irn;

Sebastian Hack's avatar
Sebastian Hack committed
228
		assert(pos == -1 && "Illegal pos for a Proj");
229
230
231
232
233
		*node = irn = get_Proj_pred(n);
		if(is_Proj(irn)) {
			assert(get_irn_mode(irn) == mode_T);
			*node = get_Proj_pred(irn);
		}
Sebastian Hack's avatar
Sebastian Hack committed
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
		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
250
	assert(out_pos < a->max_reg_data && "position too high");
Sebastian Hack's avatar
Sebastian Hack committed
251
252
253
254
	a->reg_data[out_pos].reg = reg;
}


Sebastian Hack's avatar
Sebastian Hack committed
255
ir_node *be_new_Spill(const arch_register_class_t *cls, const arch_register_class_t *cls_frame, ir_graph *irg, ir_node *bl, ir_node *frame, ir_node *to_spill, ir_node *ctx)
256
{
Sebastian Hack's avatar
Sebastian Hack committed
257
	be_spill_attr_t *a;
Sebastian Hack's avatar
Sebastian Hack committed
258
	ir_node *in[2];
Sebastian Hack's avatar
Sebastian Hack committed
259
	ir_node *res;
260

Sebastian Hack's avatar
Sebastian Hack committed
261
262
	in[0] = frame;
	in[1] = to_spill;
263
	res   = new_ir_node(NULL, irg, bl, op_be_Spill, mode_M, 2, in);
Sebastian Hack's avatar
Sebastian Hack committed
264
	a     = init_node_attr(res, 2);
265
266
	a->frame_attr.ent = NULL;
	a->frame_attr.offset = 0;
Sebastian Hack's avatar
Sebastian Hack committed
267
	a->spill_ctx = ctx;
Sebastian Hack's avatar
Sebastian Hack committed
268
269
270

	be_node_set_reg_class(res, 0, cls_frame);
	be_node_set_reg_class(res, 1, cls);
Sebastian Hack's avatar
Sebastian Hack committed
271
272
	return res;
}
273

Sebastian Hack's avatar
Sebastian Hack committed
274
ir_node *be_new_Reload(const arch_register_class_t *cls, const arch_register_class_t *cls_frame, ir_graph *irg, ir_node *bl, ir_node *frame, ir_node *mem, ir_mode *mode)
275
{
Sebastian Hack's avatar
Sebastian Hack committed
276
	ir_node *in[2];
Sebastian Hack's avatar
Sebastian Hack committed
277
	ir_node *res;
278

Sebastian Hack's avatar
Sebastian Hack committed
279
280
	in[0] = frame;
	in[1] = mem;
281
	res   = new_ir_node(NULL, irg, bl, op_be_Reload, mode, 2, in);
Sebastian Hack's avatar
Sebastian Hack committed
282
283
284
	init_node_attr(res, 2);
	be_node_set_reg_class(res, 0, cls_frame);
	be_node_set_reg_class(res, -1, cls);
Sebastian Hack's avatar
Sebastian Hack committed
285
286
	return res;
}
287

Sebastian Hack's avatar
Sebastian Hack committed
288
289
290
ir_node *(be_get_Reload_mem)(const ir_node *irn)
{
	assert(be_is_Reload(irn));
Daniel Grund's avatar
Daniel Grund committed
291
	return get_irn_n(irn, be_pos_Reload_mem);
Sebastian Hack's avatar
Sebastian Hack committed
292
293
}

Sebastian Hack's avatar
Sebastian Hack committed
294
295
ir_node *be_new_Perm(const arch_register_class_t *cls, ir_graph *irg, ir_node *bl, int n, ir_node *in[])
{
Sebastian Hack's avatar
Sebastian Hack committed
296
	int i;
297
	ir_node *irn = new_ir_node(NULL, irg, bl, op_be_Perm, mode_T, n, in);
Sebastian Hack's avatar
Sebastian Hack committed
298
299
300
301
302
303
	init_node_attr(irn, n);
	for(i = 0; i < n; ++i) {
		be_node_set_reg_class(irn, i, cls);
		be_node_set_reg_class(irn, OUT_POS(i), cls);
	}

Sebastian Hack's avatar
Sebastian Hack committed
304
305
	return irn;
}
306

Sebastian Hack's avatar
Sebastian Hack committed
307
308
309
310
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;
311

Sebastian Hack's avatar
Sebastian Hack committed
312
	in[0] = op;
313
	res   = new_ir_node(NULL, irg, bl, op_be_Copy, get_irn_mode(op), 1, in);
Sebastian Hack's avatar
Sebastian Hack committed
314
315
316
	init_node_attr(res, 1);
	be_node_set_reg_class(res, 0, cls);
	be_node_set_reg_class(res, OUT_POS(0), cls);
Sebastian Hack's avatar
Sebastian Hack committed
317
	return res;
318
319
}

Sebastian Hack's avatar
Sebastian Hack committed
320
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
321
{
Sebastian Hack's avatar
Sebastian Hack committed
322
	int i;
Sebastian Hack's avatar
Sebastian Hack committed
323
	ir_node *irn;
Sebastian Hack's avatar
Sebastian Hack committed
324

325
	irn = new_ir_node(NULL, irg, bl, op_be_Keep, mode_ANY, n, in);
Sebastian Hack's avatar
Sebastian Hack committed
326
327
328
329
	init_node_attr(irn, n);
	for(i = 0; i < n; ++i) {
		be_node_set_reg_class(irn, i, cls);
	}
Sebastian Hack's avatar
Sebastian Hack committed
330
331
	keep_alive(irn);
	return irn;
Sebastian Hack's avatar
Sebastian Hack committed
332
333
}

Sebastian Hack's avatar
Sebastian Hack committed
334
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
335
{
Sebastian Hack's avatar
Sebastian Hack committed
336
337
338
	int real_n = 3 + n;
	ir_node *irn;
	ir_node **real_in;
Sebastian Hack's avatar
Sebastian Hack committed
339

Sebastian Hack's avatar
Sebastian Hack committed
340
341
342
343
344
345
346
	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]));

347
	irn = new_ir_node(NULL, irg, bl, op_be_Call, mode_T, real_n, real_in);
Sebastian Hack's avatar
Sebastian Hack committed
348
	init_node_attr(irn, (n_outs > real_n ? n_outs : real_n));
Sebastian Hack's avatar
Sebastian Hack committed
349
	return irn;
Sebastian Hack's avatar
Sebastian Hack committed
350
351
}

352
353
354
355
356
357
358
359
360
361
362
363
364
365
entity *be_Call_get_entity(const ir_node *call)
{
	be_call_attr_t *a = get_irn_attr(call);
	assert(be_is_Call(call));
	return a->ent;
}

void    be_Call_set_entity(ir_node *call, entity *ent)
{
	be_call_attr_t *a = get_irn_attr(call);
	assert(be_is_Call(call));
	a->ent = ent;
}

Sebastian Hack's avatar
Sebastian Hack committed
366
367
ir_node *be_new_Return(ir_graph *irg, ir_node *bl, int n, ir_node *in[])
{
368
	ir_node *irn = new_ir_node(NULL, irg, bl, op_be_Return, mode_X, n, in);
Sebastian Hack's avatar
Sebastian Hack committed
369
	init_node_attr(irn, n);
Sebastian Hack's avatar
Sebastian Hack committed
370
371
372
373

	return irn;
}

374
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
375
{
Sebastian Hack's avatar
Sebastian Hack committed
376
377
378
379
380
	be_stack_attr_t *a;
	ir_node *irn;
	ir_node *in[1];

	in[0]     = old_sp;
381
	in[1]     = mem;
382
	irn       = new_ir_node(NULL, irg, bl, op_be_IncSP, sp->reg_class->mode, 2, in);
Sebastian Hack's avatar
Sebastian Hack committed
383
	a         = init_node_attr(irn, 1);
Sebastian Hack's avatar
Sebastian Hack committed
384
385
386
	a->dir    = dir;
	a->offset = offset;

Sebastian Hack's avatar
Sebastian Hack committed
387
	be_node_set_flags(irn, -1, arch_irn_flags_ignore);
Sebastian Hack's avatar
Sebastian Hack committed
388

Sebastian Hack's avatar
Sebastian Hack committed
389
	/* Set output constraint to stack register. */
Sebastian Hack's avatar
Sebastian Hack committed
390
	be_node_set_reg_class(irn, 0, sp->reg_class);
Sebastian Hack's avatar
Sebastian Hack committed
391
	be_set_constr_single_reg(irn, -1, sp);
Sebastian Hack's avatar
Sebastian Hack committed
392
	be_node_set_irn_reg(NULL, irn, sp);
Sebastian Hack's avatar
Sebastian Hack committed
393
394

	return irn;
Sebastian Hack's avatar
Sebastian Hack committed
395
}
Sebastian Hack's avatar
Sebastian Hack committed
396

397
ir_node *be_new_Alloca(const arch_register_t *sp, ir_graph *irg, ir_node *bl, ir_node *mem, ir_node *old_sp, ir_node *sz)
Sebastian Hack's avatar
Sebastian Hack committed
398
{
Sebastian Hack's avatar
Sebastian Hack committed
399
	be_node_attr_t *a;
Sebastian Hack's avatar
Sebastian Hack committed
400
	ir_node *irn;
401
	ir_node *in[3];
Sebastian Hack's avatar
Sebastian Hack committed
402

403
404
405
406
407
	in[0]    = mem;
	in[1]    = old_sp;
	in[2]    = sz;
	irn      = new_ir_node(NULL, irg, bl, op_be_Alloca, mode_T, 3, in);
	a        = init_node_attr(irn, 3);
Sebastian Hack's avatar
Sebastian Hack committed
408

409
	be_node_set_flags(irn, OUT_POS(pn_Alloc_res), arch_irn_flags_ignore);
Sebastian Hack's avatar
Sebastian Hack committed
410
411

	/* Set output constraint to stack register. */
412
	be_set_constr_single_reg(irn, OUT_POS(pn_Alloc_res), sp);
Sebastian Hack's avatar
Sebastian Hack committed
413
414
415
416
417
418
419
420
421
422
423
424
425

	return irn;
}

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)
{
	be_node_attr_t *a;
	ir_node *irn;
	ir_node *in[3];

	in[0]    = mem;
	in[1]    = old_sp;
	in[2]    = op;
426
	irn      = new_ir_node(NULL, irg, bl, op_be_SetSP, get_irn_mode(old_sp), 3, in);
Sebastian Hack's avatar
Sebastian Hack committed
427
428
429
430
431
432
433
434
	a        = init_node_attr(irn, 3);

	be_node_set_flags(irn, OUT_POS(0), arch_irn_flags_ignore);

	/* Set output constraint to stack register. */
	be_set_constr_single_reg(irn, OUT_POS(0), sp);
	be_node_set_reg_class(irn, 1, sp->reg_class);
	be_node_set_reg_class(irn, 2, sp->reg_class);
Sebastian Hack's avatar
Sebastian Hack committed
435
	be_node_set_irn_reg(NULL, irn, sp);
Sebastian Hack's avatar
Sebastian Hack committed
436
437

	return irn;
Sebastian Hack's avatar
Sebastian Hack committed
438
}
Sebastian Hack's avatar
Sebastian Hack committed
439

Sebastian Hack's avatar
Sebastian Hack committed
440
ir_node *be_new_StackParam(const arch_register_class_t *cls, const arch_register_class_t *cls_frame, ir_graph *irg, ir_node *bl, ir_mode *mode, ir_node *frame_pointer, entity *ent)
Sebastian Hack's avatar
Sebastian Hack committed
441
{
442
	be_frame_attr_t *a;
Sebastian Hack's avatar
Sebastian Hack committed
443
444
445
	ir_node *irn;
	ir_node *in[1];

446
	in[0] = frame_pointer;
447
	irn = new_ir_node(NULL, irg, bl, op_be_StackParam, mode, 1, in);
Sebastian Hack's avatar
Sebastian Hack committed
448
	a = init_node_attr(irn, 1);
449
	a->ent = ent;
Sebastian Hack's avatar
Sebastian Hack committed
450
451
452

	be_node_set_reg_class(irn, 0, cls_frame);
	be_node_set_reg_class(irn, OUT_POS(0), cls);
Sebastian Hack's avatar
Sebastian Hack committed
453
	return irn;
Sebastian Hack's avatar
Sebastian Hack committed
454
}
Sebastian Hack's avatar
Sebastian Hack committed
455

456
ir_node *be_new_RegParams(ir_graph *irg, ir_node *bl, int n_outs)
Sebastian Hack's avatar
Sebastian Hack committed
457
458
459
460
{
	ir_node *irn;
	ir_node *in[1];

461
	irn = new_ir_node(NULL, irg, bl, op_be_RegParams, mode_T, 0, in);
Sebastian Hack's avatar
Sebastian Hack committed
462
	init_node_attr(irn, n_outs);
Sebastian Hack's avatar
Sebastian Hack committed
463
464
465
	return irn;
}

466
467
468
469
470
471
472
473
474
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;
475
	irn    = new_ir_node(NULL, irg, bl, op_be_FrameLoad, mode_T, 2, in);
Sebastian Hack's avatar
Sebastian Hack committed
476
	a      = init_node_attr(irn, 3);
477
478
479
	a->ent = ent;
	a->offset = 0;
	be_node_set_reg_class(irn, 1, cls_frame);
Sebastian Hack's avatar
Sebastian Hack committed
480
	be_node_set_reg_class(irn, OUT_POS(pn_Load_res), cls_data);
481
482
483
484
485
486
487
488
489
490
491
492
493
	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;
494
	irn    = new_ir_node(NULL, irg, bl, op_be_FrameStore, mode_T, 3, in);
Sebastian Hack's avatar
Sebastian Hack committed
495
	a      = init_node_attr(irn, 3);
496
497
498
499
500
501
502
503
	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
504
{
505
	be_frame_attr_t *a;
Sebastian Hack's avatar
Sebastian Hack committed
506
507
508
	ir_node *irn;
	ir_node *in[1];

509
	in[0]  = frame;
510
	irn    = new_ir_node(NULL, irg, bl, op_be_FrameAddr, get_irn_mode(frame), 1, in);
Sebastian Hack's avatar
Sebastian Hack committed
511
	a      = init_node_attr(irn, 1);
512
513
514
	a->ent = ent;
	a->offset = 0;
	be_node_set_reg_class(irn, 0, cls_frame);
Sebastian Hack's avatar
Sebastian Hack committed
515
	be_node_set_reg_class(irn, OUT_POS(0), cls_frame);
Sebastian Hack's avatar
Sebastian Hack committed
516
517
518
	return irn;
}

Sebastian Hack's avatar
Sebastian Hack committed
519
520
521
522
523
524
525
526
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          ; }
Sebastian Hack's avatar
Sebastian Hack committed
527
int be_is_SetSP         (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_SetSP          ; }
528
int be_is_Alloca        (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Alloca         ; }
Sebastian Hack's avatar
Sebastian Hack committed
529
530
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     ; }
531
532
533
534
535
536
537
538
539
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:
540
	case beo_Reload:
541
542
543
544
545
546
547
548
549
	case beo_FrameStore:
	case beo_FrameLoad:
	case beo_FrameAddr:
		return 1;
	}

	return 0;
}

550
entity *be_get_frame_entity(const ir_node *irn)
551
552
553
554
555
556
557
{
	if(be_has_frame_entity(irn)) {
		be_frame_attr_t *a = get_irn_attr(irn);
		return a->ent;
	}
	return NULL;
}
Sebastian Hack's avatar
Sebastian Hack committed
558

Sebastian Hack's avatar
Sebastian Hack committed
559
static void be_limited(void *data, bitset_t *bs)
Sebastian Hack's avatar
Sebastian Hack committed
560
{
Sebastian Hack's avatar
Sebastian Hack committed
561
562
	be_req_t *req = data;

Sebastian Hack's avatar
Sebastian Hack committed
563
564
565
566
567
568
569
570
571
572
573
574
	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
575
576
}

Sebastian Hack's avatar
Sebastian Hack committed
577
static INLINE be_req_t *get_req(ir_node *irn, int pos)
Sebastian Hack's avatar
Sebastian Hack committed
578
{
Michael Beck's avatar
Michael Beck committed
579
	int idx           = pos < 0 ? -(pos + 1) : pos;
Sebastian Hack's avatar
Sebastian Hack committed
580
581
582
583
584
585
	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
586
	assert(!(pos < 0)  || -(pos + 1) <= a->max_reg_data);
Sebastian Hack's avatar
Sebastian Hack committed
587

Sebastian Hack's avatar
Sebastian Hack committed
588
589
590
591
592
593
594
	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
595
596
597
598
599
600
601
602
	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;
}

603
604
void be_set_constr_limited(ir_node *irn, int pos, const arch_register_req_t *req)
{
Sebastian Hack's avatar
Sebastian Hack committed
605
	be_req_t *r = get_req(irn, pos);
606
607
608
609
610
611
612
613
614
615
616
617
618

	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
619
620
621
622
623
624
625
626
627
628
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
629
630
	if(r->req.type == arch_register_req_type_none)
		r->req.type = arch_register_req_type_normal;
Sebastian Hack's avatar
Sebastian Hack committed
631
632
}

Sebastian Hack's avatar
Sebastian Hack committed
633
634
635
636
637
638
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;
}
639

640
unsigned be_get_IncSP_offset(const ir_node *irn)
Sebastian Hack's avatar
Sebastian Hack committed
641
{
Sebastian Hack's avatar
Sebastian Hack committed
642
643
644
645
	be_stack_attr_t *a = get_irn_attr(irn);
	assert(be_is_IncSP(irn));
	return a->offset;
}
Sebastian Hack's avatar
Sebastian Hack committed
646

Sebastian Hack's avatar
Sebastian Hack committed
647
648
649
650
651
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
652
653
}

654
be_stack_dir_t be_get_IncSP_direction(const ir_node *irn)
Sebastian Hack's avatar
Sebastian Hack committed
655
{
Sebastian Hack's avatar
Sebastian Hack committed
656
657
658
	be_stack_attr_t *a = get_irn_attr(irn);
	assert(be_is_IncSP(irn));
	return a->dir;
Sebastian Hack's avatar
Sebastian Hack committed
659
660
}

661
void be_set_Spill_entity(ir_node *irn, entity *ent)
662
{
Sebastian Hack's avatar
Sebastian Hack committed
663
664
	be_spill_attr_t *a = get_irn_attr(irn);
	assert(be_is_Spill(irn));
665
	a->frame_attr.ent = ent;
666
667
668
669
}

static ir_node *find_a_spill_walker(ir_node *irn, unsigned visited_nr)
{
670
671
672
	unsigned nr = get_irn_visited(irn);

	set_irn_visited(irn, visited_nr);
673

674
675
676
	if(is_Phi(irn)) {
		int i, n;
		if(nr < visited_nr) {
677
678
679
680
681
682
683
684
			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;
			}
		}
	}

685
686
687
	else if(be_get_irn_opcode(irn) == beo_Spill)
		return irn;

688
689
690
	return NULL;
}

Sebastian Hack's avatar
Sebastian Hack committed
691
692
693
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));
694
695
696
	return a->spill_ctx;
}

697
698
699
700
701
702
/**
 * 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.
 */
703
static INLINE ir_node *find_a_spill(const ir_node *irn)
704
705
706
707
{
	ir_graph *irg       = get_irn_irg(irn);
	unsigned visited_nr = get_irg_visited(irg) + 1;

Sebastian Hack's avatar
Sebastian Hack committed
708
	assert(be_is_Reload(irn));
709
	set_irg_visited(irg, visited_nr);
Sebastian Hack's avatar
Sebastian Hack committed
710
	return find_a_spill_walker(be_get_Reload_mem(irn), visited_nr);
711
712
}

713
entity *be_get_spill_entity(const ir_node *irn)
714
{
Sebastian Hack's avatar
Sebastian Hack committed
715
	int opc           = get_irn_opcode(irn);
716

Sebastian Hack's avatar
Sebastian Hack committed
717
	switch(be_get_irn_opcode(irn)) {
Sebastian Hack's avatar
Sebastian Hack committed
718
	case beo_Reload:
719
720
721
722
		{
			ir_node *spill = find_a_spill(irn);
			return be_get_spill_entity(spill);
		}
Sebastian Hack's avatar
Sebastian Hack committed
723
724
725
	case beo_Spill:
		{
			be_spill_attr_t *a = get_irn_attr(irn);
726
			return a->frame_attr.ent;
Sebastian Hack's avatar
Sebastian Hack committed
727
		}
728
	default:
Sebastian Hack's avatar
Sebastian Hack committed
729
		assert(0 && "Must give spill/reload node");
730
		break;
731
732
	}

733
	return NULL;
Sebastian Hack's avatar
Sebastian Hack committed
734
735
}

Sebastian Hack's avatar
Sebastian Hack committed
736
static void link_reload_walker(ir_node *irn, void *data)
737
{
Sebastian Hack's avatar
Sebastian Hack committed
738
	ir_node **root = (ir_node **) data;
739
	if(be_is_Reload(irn)) {
Sebastian Hack's avatar
Sebastian Hack committed
740
741
		set_irn_link(irn, *root);
		*root = irn;
742
743
744
745
746
	}
}

void be_copy_entities_to_reloads(ir_graph *irg)
{
Sebastian Hack's avatar
Sebastian Hack committed
747
748
749
750
751
752
753
754
755
	ir_node *irn = NULL;
	irg_walk_graph(irg, link_reload_walker, NULL, (void *) &irn);

	while(irn) {
		be_frame_attr_t *a = get_irn_attr(irn);
		entity *ent        = be_get_spill_entity(irn);
		a->ent = ent;
		irn    = get_irn_link(irn);
	}
756
757
}

Sebastian Hack's avatar
Sebastian Hack committed
758
ir_node *be_spill(const arch_env_t *arch_env, ir_node *irn, ir_node *ctx)
Sebastian Hack's avatar
Sebastian Hack committed
759
{
Christian Würdig's avatar
Christian Würdig committed
760
761
	ir_node *bl    = get_nodes_block(irn);
	ir_graph *irg  = get_irn_irg(bl);
Sebastian Hack's avatar
Sebastian Hack committed
762
763
	ir_node *frame = get_irg_frame(irg);
	ir_node *spill;
Sebastian Hack's avatar
Sebastian Hack committed
764
765
	ir_node *insert;

Sebastian Hack's avatar
Sebastian Hack committed
766
767
768
769
770
	const arch_register_class_t *cls       = arch_get_irn_reg_class(arch_env, irn, -1);
	const arch_register_class_t *cls_frame = arch_get_irn_reg_class(arch_env, frame, -1);

	spill = be_new_Spill(cls, cls_frame, irg, bl, frame, irn, ctx);

Sebastian Hack's avatar
Sebastian Hack committed
771
772
773
	/*
	 * 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
Sebastian Hack's avatar
Sebastian Hack committed
774
775
	 * is spilled. Also, a spill of a Proj must be after all Projs of the
	 * same tuple node.
Sebastian Hack's avatar
Sebastian Hack committed
776
777
	 */
	insert = sched_next(irn);
Sebastian Hack's avatar
Sebastian Hack committed
778
	while((is_Phi(insert) || is_Proj(insert)) && !sched_is_end(insert))
Sebastian Hack's avatar
Sebastian Hack committed
779
780
		insert = sched_next(insert);

Sebastian Hack's avatar
Sebastian Hack committed
781
782
783
784
	/*
	 * Here's one special case:
	 * If the spill is in the start block, the spill must be after the frame
	 * pointer is set up. This is checked here and fixed.
Sebastian Hack's avatar
Sebastian Hack committed
785
786
	 * If the insertion point is already the block, everything is fine, since
	 * the Spill gets inserted at the end of the block.
Sebastian Hack's avatar
Sebastian Hack committed
787
	 */
Sebastian Hack's avatar
Sebastian Hack committed
788
	if(bl == get_irg_start_block(irg) && insert != bl && sched_comes_after(insert, frame))
Sebastian Hack's avatar
Sebastian Hack committed
789
790
		insert = sched_next(frame);

Sebastian Hack's avatar
Sebastian Hack committed
791
	sched_add_before(insert, spill);
Christian Würdig's avatar
Christian Würdig committed
792
	return spill;
Sebastian Hack's avatar
Sebastian Hack committed
793
794
}

Sebastian Hack's avatar
Sebastian Hack committed
795
ir_node *be_reload(const arch_env_t *arch_env, const arch_register_class_t *cls, ir_node *reloader, ir_mode *mode, ir_node *spill)
Sebastian Hack's avatar
Sebastian Hack committed
796
797
798
{
	ir_node *reload;

Daniel Grund's avatar
Bugfix    
Daniel Grund committed
799
	ir_node *bl    = is_Block(reloader) ? reloader : get_nodes_block(reloader);
Sebastian Hack's avatar
Sebastian Hack committed
800
801
802
	ir_graph *irg  = get_irn_irg(bl);
	ir_node *frame = get_irg_frame(irg);
	const arch_register_class_t *cls_frame = arch_get_irn_reg_class(arch_env, frame, -1);
Sebastian Hack's avatar
Sebastian Hack committed
803

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

Sebastian Hack's avatar
Sebastian Hack committed
806
	reload = be_new_Reload(cls, cls_frame, irg, bl, frame, spill, mode);
Sebastian Hack's avatar
Sebastian Hack committed
807

Sebastian Hack's avatar
Sebastian Hack committed
808
	sched_add_before(reloader, reload);
Christian Würdig's avatar
Christian Würdig committed
809
	return reload;
Sebastian Hack's avatar
Sebastian Hack committed
810
}
Sebastian Hack's avatar
Sebastian Hack committed
811

Sebastian Hack's avatar
Sebastian Hack committed
812
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
813
{
Sebastian Hack's avatar
Sebastian Hack committed
814
	const be_node_attr_t *a = get_irn_attr(irn);
Daniel Grund's avatar
Daniel Grund committed
815

Sebastian Hack's avatar
Sebastian Hack committed
816
	if(out_pos < a->max_reg_data)
Sebastian Hack's avatar
Sebastian Hack committed
817
818
819
820
		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
821
	}
Sebastian Hack's avatar
Sebastian Hack committed
822

Sebastian Hack's avatar
Sebastian Hack committed
823
	return req;
Sebastian Hack's avatar
Sebastian Hack committed
824
825
}

Sebastian Hack's avatar
Sebastian Hack committed
826
static void *put_in_reg_req(arch_register_req_t *req, const ir_node *irn, int pos)
827
{
Sebastian Hack's avatar
Sebastian Hack committed
828
829
830
	const be_node_attr_t *a = get_irn_attr(irn);
	int n                   = get_irn_arity(irn);

Sebastian Hack's avatar
Sebastian Hack committed
831
	if(pos < get_irn_arity(irn) && pos < a->max_reg_data)
Sebastian Hack's avatar
Sebastian Hack committed
832
833
834
835
		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
836
837
838
	}

	return req;
839
840
}

Sebastian Hack's avatar
Sebastian Hack committed
841
static const arch_register_req_t *
842
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
843
{
Sebastian Hack's avatar
Sebastian Hack committed
844
	int out_pos = pos;
Sebastian Hack's avatar
Sebastian Hack committed
845

Sebastian Hack's avatar
Sebastian Hack committed
846
847
848
	if(pos < 0) {
		if(get_irn_mode(irn) == mode_T)
			return NULL;
Daniel Grund's avatar
Daniel Grund committed
849

Sebastian Hack's avatar
Sebastian Hack committed
850
851
852
853
		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
854

Sebastian Hack's avatar
Sebastian Hack committed
855
856
857
	else {
		return is_be_node(irn) ? put_in_reg_req(req, irn, pos) : NULL;
	}
Daniel Grund's avatar
Daniel Grund committed
858

Sebastian Hack's avatar
Sebastian Hack committed
859
	return req;
Sebastian Hack's avatar
Sebastian Hack committed
860
861
}

Sebastian Hack's avatar
Sebastian Hack committed
862
const arch_register_t *
863
be_node_get_irn_reg(const void *_self, const ir_node *irn)
Sebastian Hack's avatar
Sebastian Hack committed
864
865
866
{
	int out_pos;
	be_node_attr_t *a;
Daniel Grund's avatar
Daniel Grund committed
867

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

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

Sebastian Hack's avatar
Sebastian Hack committed
874
	return a->reg_data[out_pos].reg;
Sebastian Hack's avatar
Sebastian Hack committed
875
876
}

Sebastian Hack's avatar
Sebastian Hack committed
877
static arch_irn_class_t be_node_classify(const void *_self, const ir_node *irn)
Sebastian Hack's avatar
Sebastian Hack committed
878
{
Christian Würdig's avatar
Christian Würdig committed
879
	redir_proj((const ir_node **) &irn, -1);
Sebastian Hack's avatar
Sebastian Hack committed
880

Sebastian Hack's avatar
Sebastian Hack committed
881
	switch(be_get_irn_opcode(irn)) {
Sebastian Hack's avatar
Sebastian Hack committed
882
883
884
885
886
#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
887
#undef XXX
Sebastian Hack's avatar
Sebastian Hack committed
888
889
		default:
		return 0;
Sebastian Hack's avatar
Sebastian Hack committed
890
891
	}

Christian Würdig's avatar
Christian Würdig committed
892
	return 0;
Sebastian Hack's avatar
Sebastian Hack committed
893
894
}

Sebastian Hack's avatar
Sebastian Hack committed
895
static arch_irn_flags_t be_node_get_flags(const void *_self, const ir_node *irn)
Sebastian Hack's avatar
Sebastian Hack committed
896
{
Sebastian Hack's avatar
Sebastian Hack committed
897
	int out_pos;
Sebastian Hack's avatar
Sebastian Hack committed
898
899
	be_node_attr_t *a;

Sebastian Hack's avatar
Sebastian Hack committed
900
901
902
	out_pos = redir_proj((const ir_node **) &irn, -1);
	a       = get_irn_attr(irn);

Sebastian Hack's avatar
Sebastian Hack committed
903
	assert(is_be_node(irn));
Sebastian Hack's avatar
Sebastian Hack committed
904
905
906
	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
907
908
}

909
910
911
912
913
static entity *be_node_get_frame_entity(const void *self, const ir_node *irn)
{
	return be_get_frame_entity(irn);
}

Sebastian Hack's avatar
Sebastian Hack committed
914
static void be_node_set_frame_offset(const void *self, ir_node *irn, int offset)
915
{
Sebastian Hack's avatar
Sebastian Hack committed
916
917
918
919
	if(be_has_frame_entity(irn)) {
		be_frame_attr_t *a = get_irn_attr(irn);
		a->offset = offset;
	}
920
921
922
}


923
static const arch_irn_ops_if_t be_node_irn_ops_if = {
Sebastian Hack's avatar
Sebastian Hack committed
924
925
926
927
928
	be_node_get_irn_reg_req,
	be_node_set_irn_reg,
	be_node_get_irn_reg,
	be_node_classify,
	be_node_get_flags,
929
	be_node_get_frame_entity,
Sebastian Hack's avatar
Sebastian Hack committed
930
	be_node_set_frame_offset
Sebastian Hack's avatar
Sebastian Hack committed
931
};
932

933
934
935
936
937
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)
938
{
Sebastian Hack's avatar
Sebastian Hack committed
939
940
	redir_proj((const ir_node **) &irn, -1);
	return is_be_node(irn) ? &be_node_irn_ops : NULL;
Sebastian Hack's avatar
Sebastian Hack committed
941
942
}

Sebastian Hack's avatar
Sebastian Hack committed
943
944
945
const arch_irn_handler_t be_node_irn_handler = {
	be_node_get_arch_ops
};
Sebastian Hack's avatar
Sebastian Hack committed
946

Sebastian Hack's avatar
Sebastian Hack committed
947
948
949

static void dump_node_req(FILE *f, be_req_t *req)
{
Sebastian Hack's avatar
Sebastian Hack committed
950
	unsigned i;
Sebastian Hack's avatar
Sebastian Hack committed
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
	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_ce