benode.c 32.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
#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
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;
Sebastian Hack's avatar
Sebastian Hack committed
118
ir_op *op_be_CopyKeep;
119
120
121
ir_op *op_be_Call;
ir_op *op_be_Return;
ir_op *op_be_IncSP;
Sebastian Hack's avatar
Sebastian Hack committed
122
ir_op *op_be_AddSP;
123
124
125
126
127
128
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
129
ir_op *op_be_Epilogue;
Sebastian Hack's avatar
Sebastian Hack committed
130

Sebastian Hack's avatar
Sebastian Hack committed
131
static int beo_base = -1;
Sebastian Hack's avatar
Sebastian Hack committed
132

Sebastian Hack's avatar
Sebastian Hack committed
133
static const ir_op_ops be_node_op_ops;
Sebastian Hack's avatar
Sebastian Hack committed
134

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

Sebastian Hack's avatar
Sebastian Hack committed
149
150
	if(inited)
		return;
Sebastian Hack's avatar
Sebastian Hack committed
151

Sebastian Hack's avatar
Sebastian Hack committed
152
	inited = 1;
Sebastian Hack's avatar
Sebastian Hack committed
153

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

157
	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);
158
	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);
159
160
161
	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
162
	op_be_CopyKeep   = new_ir_op(beo_base + beo_CopyKeep,   "CopyKeep",   op_pin_state_pinned,     K, oparity_variable, 0, sizeof(be_node_attr_t),  &be_node_op_ops);
Sebastian Hack's avatar
Sebastian Hack committed
163
	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);
164
	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);
Sebastian Hack's avatar
Sebastian Hack committed
165
	op_be_AddSP      = new_ir_op(beo_base + beo_AddSP,      "AddSP",      op_pin_state_pinned,     N, oparity_unary,    0, sizeof(be_node_attr_t),  &be_node_op_ops);
166
167
168
169
170
171
172
	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);
Sebastian Hack's avatar
Sebastian Hack committed
173
	op_be_Epilogue   = new_ir_op(beo_base + beo_Epilogue,   "Epilogue",   op_pin_state_pinned,     N, oparity_any,      0, sizeof(be_node_attr_t),  &be_node_op_ops);
174
175
176
177
178
179

	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);
Sebastian Hack's avatar
Sebastian Hack committed
180
	set_op_tag(op_be_CopyKeep,   &be_node_tag);
181
182
	set_op_tag(op_be_Call,       &be_node_tag);
	set_op_tag(op_be_Return,     &be_node_tag);
Sebastian Hack's avatar
Sebastian Hack committed
183
	set_op_tag(op_be_AddSP,      &be_node_tag);
184
185
186
187
188
189
190
	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
191
	set_op_tag(op_be_Epilogue,   &be_node_tag);
Sebastian Hack's avatar
Sebastian Hack committed
192
}
193

Sebastian Hack's avatar
Sebastian Hack committed
194
static void *init_node_attr(ir_node* irn, int max_reg_data)
Sebastian Hack's avatar
Sebastian Hack committed
195
{
Sebastian Hack's avatar
Sebastian Hack committed
196
	ir_graph *irg     = get_irn_irg(irn);
Sebastian Hack's avatar
Sebastian Hack committed
197
198
	be_node_attr_t *a = get_irn_attr(irn);

199
	memset(a, 0, sizeof(get_op_attr_size(get_irn_op(irn))));
Sebastian Hack's avatar
Sebastian Hack committed
200
201
	a->max_reg_data = max_reg_data;
	a->reg_data     = NULL;
Sebastian Hack's avatar
Sebastian Hack committed
202

Sebastian Hack's avatar
Sebastian Hack committed
203
	if(max_reg_data > 0) {
Sebastian Hack's avatar
Sebastian Hack committed
204
205
		int i;

Sebastian Hack's avatar
Sebastian Hack committed
206
207
208
		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
209
210
			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
211
212
213
214
215
		}
	}

	return a;
}
216

217
218
static INLINE int is_be_node(const ir_node *irn)
{
Sebastian Hack's avatar
Sebastian Hack committed
219
	return get_op_tag(get_irn_op(irn)) == &be_node_tag;
220
221
}

Sebastian Hack's avatar
Sebastian Hack committed
222
be_opcode_t be_get_irn_opcode(const ir_node *irn)
223
{
Sebastian Hack's avatar
Sebastian Hack committed
224
	return is_be_node(irn) ? get_irn_opcode(irn) - beo_base : beo_NoBeOp;
225
226
}

Sebastian Hack's avatar
Sebastian Hack committed
227
228
229
230
231
static int redir_proj(const ir_node **node, int pos)
{
	const ir_node *n = *node;

	if(is_Proj(n)) {
232
233
		ir_node *irn;

Sebastian Hack's avatar
Sebastian Hack committed
234
		assert(pos == -1 && "Illegal pos for a Proj");
235
236
237
238
239
		*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
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
		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
256
	assert(out_pos < a->max_reg_data && "position too high");
Sebastian Hack's avatar
Sebastian Hack committed
257
258
259
260
	a->reg_data[out_pos].reg = reg;
}


Sebastian Hack's avatar
Sebastian Hack committed
261
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)
262
{
Sebastian Hack's avatar
Sebastian Hack committed
263
	be_spill_attr_t *a;
Sebastian Hack's avatar
Sebastian Hack committed
264
	ir_node *in[2];
Sebastian Hack's avatar
Sebastian Hack committed
265
	ir_node *res;
266

Sebastian Hack's avatar
Sebastian Hack committed
267
268
	in[0] = frame;
	in[1] = to_spill;
269
	res   = new_ir_node(NULL, irg, bl, op_be_Spill, mode_M, 2, in);
Sebastian Hack's avatar
Sebastian Hack committed
270
	a     = init_node_attr(res, 2);
271
272
	a->frame_attr.ent = NULL;
	a->frame_attr.offset = 0;
Sebastian Hack's avatar
Sebastian Hack committed
273
	a->spill_ctx = ctx;
Sebastian Hack's avatar
Sebastian Hack committed
274
275
276

	be_node_set_reg_class(res, 0, cls_frame);
	be_node_set_reg_class(res, 1, cls);
Sebastian Hack's avatar
Sebastian Hack committed
277
278
	return res;
}
279

Sebastian Hack's avatar
Sebastian Hack committed
280
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)
281
{
Sebastian Hack's avatar
Sebastian Hack committed
282
	ir_node *in[2];
Sebastian Hack's avatar
Sebastian Hack committed
283
	ir_node *res;
284

Sebastian Hack's avatar
Sebastian Hack committed
285
286
	in[0] = frame;
	in[1] = mem;
287
	res   = new_ir_node(NULL, irg, bl, op_be_Reload, mode, 2, in);
Sebastian Hack's avatar
Sebastian Hack committed
288
289
290
	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
291
292
	return res;
}
293

Sebastian Hack's avatar
Sebastian Hack committed
294
295
296
ir_node *(be_get_Reload_mem)(const ir_node *irn)
{
	assert(be_is_Reload(irn));
Daniel Grund's avatar
Daniel Grund committed
297
	return get_irn_n(irn, be_pos_Reload_mem);
Sebastian Hack's avatar
Sebastian Hack committed
298
299
}

Sebastian Hack's avatar
Sebastian Hack committed
300
301
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
302
	int i;
303
	ir_node *irn = new_ir_node(NULL, irg, bl, op_be_Perm, mode_T, n, in);
Sebastian Hack's avatar
Sebastian Hack committed
304
305
306
307
308
309
	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
310
311
	return irn;
}
312

Sebastian Hack's avatar
Sebastian Hack committed
313
314
315
316
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;
317

Sebastian Hack's avatar
Sebastian Hack committed
318
	in[0] = op;
319
	res   = new_ir_node(NULL, irg, bl, op_be_Copy, get_irn_mode(op), 1, in);
Sebastian Hack's avatar
Sebastian Hack committed
320
321
322
	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
323
	return res;
324
325
}

Sebastian Hack's avatar
Sebastian Hack committed
326
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
327
{
Sebastian Hack's avatar
Sebastian Hack committed
328
	int i;
Sebastian Hack's avatar
Sebastian Hack committed
329
	ir_node *irn;
Sebastian Hack's avatar
Sebastian Hack committed
330

331
	irn = new_ir_node(NULL, irg, bl, op_be_Keep, mode_ANY, n, in);
Sebastian Hack's avatar
Sebastian Hack committed
332
333
334
335
	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
336
337
	keep_alive(irn);
	return irn;
Sebastian Hack's avatar
Sebastian Hack committed
338
339
}

Sebastian Hack's avatar
Sebastian Hack committed
340
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
341
{
Sebastian Hack's avatar
Sebastian Hack committed
342
343
344
	int real_n = 3 + n;
	ir_node *irn;
	ir_node **real_in;
Sebastian Hack's avatar
Sebastian Hack committed
345

Sebastian Hack's avatar
Sebastian Hack committed
346
347
348
349
350
351
352
	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]));

353
	irn = new_ir_node(NULL, irg, bl, op_be_Call, mode_T, real_n, real_in);
Sebastian Hack's avatar
Sebastian Hack committed
354
	init_node_attr(irn, (n_outs > real_n ? n_outs : real_n));
Sebastian Hack's avatar
Sebastian Hack committed
355
	return irn;
Sebastian Hack's avatar
Sebastian Hack committed
356
357
}

358
359
360
361
362
363
364
365
366
367
368
369
370
371
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
372
373
ir_node *be_new_Return(ir_graph *irg, ir_node *bl, int n, ir_node *in[])
{
374
	ir_node *irn = new_ir_node(NULL, irg, bl, op_be_Return, mode_X, n, in);
Sebastian Hack's avatar
Sebastian Hack committed
375
	init_node_attr(irn, n);
Sebastian Hack's avatar
Sebastian Hack committed
376
377
378
379

	return irn;
}

380
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
381
{
Sebastian Hack's avatar
Sebastian Hack committed
382
383
384
385
386
	be_stack_attr_t *a;
	ir_node *irn;
	ir_node *in[1];

	in[0]     = old_sp;
387
	in[1]     = mem;
388
	irn       = new_ir_node(NULL, irg, bl, op_be_IncSP, sp->reg_class->mode, 2, in);
Sebastian Hack's avatar
Sebastian Hack committed
389
	a         = init_node_attr(irn, 1);
Sebastian Hack's avatar
Sebastian Hack committed
390
391
392
	a->dir    = dir;
	a->offset = offset;

Sebastian Hack's avatar
Sebastian Hack committed
393
	be_node_set_flags(irn, -1, arch_irn_flags_ignore);
Sebastian Hack's avatar
Sebastian Hack committed
394

Sebastian Hack's avatar
Sebastian Hack committed
395
	/* Set output constraint to stack register. */
Sebastian Hack's avatar
Sebastian Hack committed
396
	be_node_set_reg_class(irn, 0, sp->reg_class);
Sebastian Hack's avatar
Sebastian Hack committed
397
	be_set_constr_single_reg(irn, -1, sp);
Sebastian Hack's avatar
Sebastian Hack committed
398
	be_node_set_irn_reg(NULL, irn, sp);
Sebastian Hack's avatar
Sebastian Hack committed
399
400

	return irn;
Sebastian Hack's avatar
Sebastian Hack committed
401
}
Sebastian Hack's avatar
Sebastian Hack committed
402

Sebastian Hack's avatar
Sebastian Hack committed
403
ir_node *be_new_AddSP(const arch_register_t *sp, ir_graph *irg, ir_node *bl, ir_node *old_sp, ir_node *sz)
Sebastian Hack's avatar
Sebastian Hack committed
404
{
Sebastian Hack's avatar
Sebastian Hack committed
405
	be_node_attr_t *a;
Sebastian Hack's avatar
Sebastian Hack committed
406
	ir_node *irn;
Sebastian Hack's avatar
Sebastian Hack committed
407
	ir_node *in[be_pos_AddSP_last];
Sebastian Hack's avatar
Sebastian Hack committed
408

Sebastian Hack's avatar
Sebastian Hack committed
409
410
	in[be_pos_AddSP_old_sp] = old_sp;
	in[be_pos_AddSP_size]   = sz;
Sebastian Hack's avatar
Sebastian Hack committed
411

Sebastian Hack's avatar
Sebastian Hack committed
412
413
414
415
	irn      = new_ir_node(NULL, irg, bl, op_be_AddSP, mode_T, be_pos_AddSP_last, in);
	a        = init_node_attr(irn, be_pos_AddSP_last);

	be_node_set_flags(irn, OUT_POS(0), arch_irn_flags_ignore);
Sebastian Hack's avatar
Sebastian Hack committed
416
417

	/* Set output constraint to stack register. */
Sebastian Hack's avatar
Sebastian Hack committed
418
	be_set_constr_single_reg(irn, OUT_POS(0), sp);
Sebastian Hack's avatar
Sebastian Hack committed
419
420
421
422
423
424
425
426
427
428
429
430
431

	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;
432
	irn      = new_ir_node(NULL, irg, bl, op_be_SetSP, get_irn_mode(old_sp), 3, in);
Sebastian Hack's avatar
Sebastian Hack committed
433
434
435
436
437
438
439
440
	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
441
	be_node_set_irn_reg(NULL, irn, sp);
Sebastian Hack's avatar
Sebastian Hack committed
442
443

	return irn;
Sebastian Hack's avatar
Sebastian Hack committed
444
}
Sebastian Hack's avatar
Sebastian Hack committed
445

Sebastian Hack's avatar
Sebastian Hack committed
446
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
447
{
448
	be_frame_attr_t *a;
Sebastian Hack's avatar
Sebastian Hack committed
449
450
451
	ir_node *irn;
	ir_node *in[1];

452
	in[0] = frame_pointer;
453
	irn = new_ir_node(NULL, irg, bl, op_be_StackParam, mode, 1, in);
Sebastian Hack's avatar
Sebastian Hack committed
454
	a = init_node_attr(irn, 1);
455
	a->ent = ent;
Sebastian Hack's avatar
Sebastian Hack committed
456
457
458

	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
459
	return irn;
Sebastian Hack's avatar
Sebastian Hack committed
460
}
Sebastian Hack's avatar
Sebastian Hack committed
461

462
ir_node *be_new_RegParams(ir_graph *irg, ir_node *bl, int n_outs)
Sebastian Hack's avatar
Sebastian Hack committed
463
464
465
466
{
	ir_node *irn;
	ir_node *in[1];

467
	irn = new_ir_node(NULL, irg, bl, op_be_RegParams, mode_T, 0, in);
Sebastian Hack's avatar
Sebastian Hack committed
468
	init_node_attr(irn, n_outs);
Sebastian Hack's avatar
Sebastian Hack committed
469
470
471
	return irn;
}

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

515
	in[0]  = frame;
516
	irn    = new_ir_node(NULL, irg, bl, op_be_FrameAddr, get_irn_mode(frame), 1, in);
Sebastian Hack's avatar
Sebastian Hack committed
517
	a      = init_node_attr(irn, 1);
518
519
520
	a->ent = ent;
	a->offset = 0;
	be_node_set_reg_class(irn, 0, cls_frame);
Sebastian Hack's avatar
Sebastian Hack committed
521
	be_node_set_reg_class(irn, OUT_POS(0), cls_frame);
Sebastian Hack's avatar
Sebastian Hack committed
522
523
524
	return irn;
}

Sebastian Hack's avatar
Sebastian Hack committed
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
ir_node *be_new_CopyKeep(const arch_register_class_t *cls, ir_graph *irg, ir_node *bl, ir_node *src, int n, ir_node *in_keep[], ir_mode *mode)
{
	ir_node *irn;
	ir_node **in = (ir_node **) alloca((n + 1) * sizeof(in[0]));

	in[0] = src;
	memcpy(&in[1], in_keep, n * sizeof(in[0]));
	irn   = new_ir_node(NULL, irg, bl, op_be_CopyKeep, mode, n + 1, in);
	init_node_attr(irn, n);
	be_node_set_reg_class(irn, OUT_POS(0), cls);
	be_node_set_reg_class(irn, 0, cls);

	return irn;
}

ir_node *be_new_CopyKeep_single(const arch_register_class_t *cls, ir_graph *irg, ir_node *bl, ir_node *src, ir_node *keep, ir_mode *mode)
{
	ir_node *in[1];

	in[0] = keep;
	return be_new_CopyKeep(cls, irg, bl, src, 1, in, mode);
}

ir_node *be_new_Epilogue(ir_graph *irg, ir_node *bl, int n, ir_node *in[])
{
	ir_node *irn;

	irn = new_ir_node(NULL, irg, bl, op_be_Epilogue, mode_T, n, in);
	init_node_attr(irn, n);
	return irn;
}

Sebastian Hack's avatar
Sebastian Hack committed
557
558
559
560
561
562
563
564
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
565
int be_is_SetSP         (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_SetSP          ; }
Sebastian Hack's avatar
Sebastian Hack committed
566
int be_is_AddSP         (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_AddSP          ; }
Sebastian Hack's avatar
Sebastian Hack committed
567
568
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     ; }
569
570
571
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     ; }
Sebastian Hack's avatar
Sebastian Hack committed
572
int be_is_Epilogue        (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_Epilogue         ; }
573
574
575
576
577
578

int be_has_frame_entity(const ir_node *irn)
{
	switch(be_get_irn_opcode(irn)) {
	case beo_StackParam:
	case beo_Spill:
579
	case beo_Reload:
580
581
582
583
584
585
586
587
588
	case beo_FrameStore:
	case beo_FrameLoad:
	case beo_FrameAddr:
		return 1;
	}

	return 0;
}

589
entity *be_get_frame_entity(const ir_node *irn)
590
591
592
593
594
595
596
{
	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
597

Sebastian Hack's avatar
Sebastian Hack committed
598
static void be_limited(void *data, bitset_t *bs)
Sebastian Hack's avatar
Sebastian Hack committed
599
{
Sebastian Hack's avatar
Sebastian Hack committed
600
601
	be_req_t *req = data;

Sebastian Hack's avatar
Sebastian Hack committed
602
603
604
605
606
607
608
609
610
611
612
613
	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
614
615
}

Sebastian Hack's avatar
Sebastian Hack committed
616
static INLINE be_req_t *get_req(ir_node *irn, int pos)
Sebastian Hack's avatar
Sebastian Hack committed
617
{
Michael Beck's avatar
Michael Beck committed
618
	int idx           = pos < 0 ? -(pos + 1) : pos;
Sebastian Hack's avatar
Sebastian Hack committed
619
620
621
622
623
624
	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
625
	assert(!(pos < 0)  || -(pos + 1) <= a->max_reg_data);
Sebastian Hack's avatar
Sebastian Hack committed
626

Sebastian Hack's avatar
Sebastian Hack committed
627
628
629
630
631
632
633
	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
634
635
636
637
638
639
640
641
	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;
}

642
643
void be_set_constr_limited(ir_node *irn, int pos, const arch_register_req_t *req)
{
Sebastian Hack's avatar
Sebastian Hack committed
644
	be_req_t *r = get_req(irn, pos);
645
646
647
648
649
650
651
652
653
654
655
656
657

	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
658
659
660
661
662
663
664
665
666
667
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
668
669
	if(r->req.type == arch_register_req_type_none)
		r->req.type = arch_register_req_type_normal;
Sebastian Hack's avatar
Sebastian Hack committed
670
671
}

Sebastian Hack's avatar
Sebastian Hack committed
672
673
674
675
676
677
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;
}
678

679
unsigned be_get_IncSP_offset(const ir_node *irn)
Sebastian Hack's avatar
Sebastian Hack committed
680
{
Sebastian Hack's avatar
Sebastian Hack committed
681
682
683
684
	be_stack_attr_t *a = get_irn_attr(irn);
	assert(be_is_IncSP(irn));
	return a->offset;
}
Sebastian Hack's avatar
Sebastian Hack committed
685

Sebastian Hack's avatar
Sebastian Hack committed
686
687
688
689
690
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
691
692
}

693
be_stack_dir_t be_get_IncSP_direction(const ir_node *irn)
Sebastian Hack's avatar
Sebastian Hack committed
694
{
Sebastian Hack's avatar
Sebastian Hack committed
695
696
697
	be_stack_attr_t *a = get_irn_attr(irn);
	assert(be_is_IncSP(irn));
	return a->dir;
Sebastian Hack's avatar
Sebastian Hack committed
698
699
}

700
void be_set_Spill_entity(ir_node *irn, entity *ent)
701
{
Sebastian Hack's avatar
Sebastian Hack committed
702
703
	be_spill_attr_t *a = get_irn_attr(irn);
	assert(be_is_Spill(irn));
704
	a->frame_attr.ent = ent;
705
706
707
708
}

static ir_node *find_a_spill_walker(ir_node *irn, unsigned visited_nr)
{
709
710
711
	unsigned nr = get_irn_visited(irn);

	set_irn_visited(irn, visited_nr);
712

713
714
715
	if(is_Phi(irn)) {
		int i, n;
		if(nr < visited_nr) {
716
717
718
719
720
721
722
723
			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;
			}
		}
	}

724
725
726
	else if(be_get_irn_opcode(irn) == beo_Spill)
		return irn;

727
728
729
	return NULL;
}

Sebastian Hack's avatar
Sebastian Hack committed
730
731
732
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));
733
734
735
	return a->spill_ctx;
}

736
737
738
739
740
741
/**
 * 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.
 */
742
static INLINE ir_node *find_a_spill(const ir_node *irn)
743
744
745
746
{
	ir_graph *irg       = get_irn_irg(irn);
	unsigned visited_nr = get_irg_visited(irg) + 1;

Sebastian Hack's avatar
Sebastian Hack committed
747
	assert(be_is_Reload(irn));
748
	set_irg_visited(irg, visited_nr);
Sebastian Hack's avatar
Sebastian Hack committed
749
	return find_a_spill_walker(be_get_Reload_mem(irn), visited_nr);
750
751
}

752
entity *be_get_spill_entity(const ir_node *irn)
753
{
Sebastian Hack's avatar
Sebastian Hack committed
754
	int opc           = get_irn_opcode(irn);
755

Sebastian Hack's avatar
Sebastian Hack committed
756
	switch(be_get_irn_opcode(irn)) {
Sebastian Hack's avatar
Sebastian Hack committed
757
	case beo_Reload:
758
759
760
761
		{
			ir_node *spill = find_a_spill(irn);
			return be_get_spill_entity(spill);
		}
Sebastian Hack's avatar
Sebastian Hack committed
762
763
764
	case beo_Spill:
		{
			be_spill_attr_t *a = get_irn_attr(irn);
765
			return a->frame_attr.ent;
Sebastian Hack's avatar
Sebastian Hack committed
766
		}
767
	default:
Sebastian Hack's avatar
Sebastian Hack committed
768
		assert(0 && "Must give spill/reload node");
769
		break;
770
771
	}

772
	return NULL;
Sebastian Hack's avatar
Sebastian Hack committed
773
774
}

Sebastian Hack's avatar
Sebastian Hack committed
775
static void link_reload_walker(ir_node *irn, void *data)
776
{
Sebastian Hack's avatar
Sebastian Hack committed
777
	ir_node **root = (ir_node **) data;
778
	if(be_is_Reload(irn)) {
Sebastian Hack's avatar
Sebastian Hack committed
779
780
		set_irn_link(irn, *root);
		*root = irn;
781
782
783
784
785
	}
}

void be_copy_entities_to_reloads(ir_graph *irg)
{
Sebastian Hack's avatar
Sebastian Hack committed
786
787
788
789
790
791
792
793
794
	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);
	}
795
796
}

Sebastian Hack's avatar
Sebastian Hack committed
797
ir_node *be_spill(const arch_env_t *arch_env, ir_node *irn, ir_node *ctx)
Sebastian Hack's avatar
Sebastian Hack committed
798
{
Christian Würdig's avatar
Christian Würdig committed
799
800
	ir_node *bl    = get_nodes_block(irn);
	ir_graph *irg  = get_irn_irg(bl);
Sebastian Hack's avatar
Sebastian Hack committed
801
802
	ir_node *frame = get_irg_frame(irg);
	ir_node *spill;
Sebastian Hack's avatar
Sebastian Hack committed
803
804
	ir_node *insert;

Sebastian Hack's avatar
Sebastian Hack committed
805
806
807
808
809
	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
810
811
812
	/*
	 * 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
813
814
	 * 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
815
816
	 */
	insert = sched_next(irn);
Sebastian Hack's avatar
Sebastian Hack committed
817
	while((is_Phi(insert) || is_Proj(insert)) && !sched_is_end(insert))
Sebastian Hack's avatar
Sebastian Hack committed
818
819
		insert = sched_next(insert);

Sebastian Hack's avatar
Sebastian Hack committed
820
821
822
823
	/*
	 * 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
824
825
	 * 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
826
	 */
Sebastian Hack's avatar
Sebastian Hack committed
827
	if(bl == get_irg_start_block(irg) && insert != bl && sched_comes_after(insert, frame))
Sebastian Hack's avatar
Sebastian Hack committed
828
829
		insert = sched_next(frame);

Sebastian Hack's avatar
Sebastian Hack committed
830
	sched_add_before(insert, spill);
Christian Würdig's avatar
Christian Würdig committed
831
	return spill;
Sebastian Hack's avatar
Sebastian Hack committed
832
833
}

Sebastian Hack's avatar
Sebastian Hack committed
834
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
835
836
837
{
	ir_node *reload;

Daniel Grund's avatar
Bugfix    
Daniel Grund committed
838
	ir_node *bl    = is_Block(reloader) ? reloader : get_nodes_block(reloader);
Sebastian Hack's avatar
Sebastian Hack committed
839
840
841
	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
842

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

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

Sebastian Hack's avatar
Sebastian Hack committed
847
	sched_add_before(reloader, reload);
Christian Würdig's avatar
Christian Würdig committed
848
	return reload;
Sebastian Hack's avatar
Sebastian Hack committed
849
}
Sebastian Hack's avatar
Sebastian Hack committed
850

Sebastian Hack's avatar
Sebastian Hack committed
851
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
852
{
Sebastian Hack's avatar
Sebastian Hack committed
853
	const be_node_attr_t *a = get_irn_attr(irn);
Daniel Grund's avatar
Daniel Grund committed
854

Sebastian Hack's avatar
Sebastian Hack committed
855
	if(out_pos < a->max_reg_data)
Sebastian Hack's avatar
Sebastian Hack committed
856
857
858
859
		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
860
	}
Sebastian Hack's avatar
Sebastian Hack committed
861

Sebastian Hack's avatar
Sebastian Hack committed
862
	return req;
Sebastian Hack's avatar
Sebastian Hack committed
863
864
}

Sebastian Hack's avatar
Sebastian Hack committed
865
static void *put_in_reg_req(arch_register_req_t *req, const ir_node *irn, int pos)
866
{
Sebastian Hack's avatar
Sebastian Hack committed
867
868
869
	const be_node_attr_t *a = get_irn_attr(irn);
	int n                   = get_irn_arity(irn);

Sebastian Hack's avatar
Sebastian Hack committed
870
	if(pos < get_irn_arity(irn) && pos < a->max_reg_data)
Sebastian Hack's avatar
Sebastian Hack committed
871
872
873
874
		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
875
876
877
	}

	return req;
878
879
}

Sebastian Hack's avatar
Sebastian Hack committed
880
static const arch_register_req_t *
881
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
882
{
Sebastian Hack's avatar
Sebastian Hack committed
883
	int out_pos = pos;
Sebastian Hack's avatar
Sebastian Hack committed
884

Sebastian Hack's avatar
Sebastian Hack committed
885
886
887
	if(pos < 0) {
		if(get_irn_mode(irn) == mode_T)
			return NULL;
Daniel Grund's avatar
Daniel Grund committed
888

Sebastian Hack's avatar
Sebastian Hack committed
889
890
891
892
		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
893

Sebastian Hack's avatar
Sebastian Hack committed
894
895
896
	else {
		return is_be_node(irn) ? put_in_reg_req(req, irn, pos) : NULL;
	}
Daniel Grund's avatar
Daniel Grund committed
897

Sebastian Hack's avatar
Sebastian Hack committed
898
	return req;
Sebastian Hack's avatar
Sebastian Hack committed
899
900
}

Sebastian Hack's avatar
Sebastian Hack committed
901
const arch_register_t *
902
be_node_get_irn_reg(const void *_self, const ir_node *irn)
Sebastian Hack's avatar
Sebastian Hack committed
903
904
905
{
	int out_pos;
	be_node_attr_t *a;
Daniel Grund's avatar
Daniel Grund committed
906

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

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

Sebastian Hack's avatar
Sebastian Hack committed
913
	return a->reg_data[out_pos].reg;
Sebastian Hack's avatar
Sebastian Hack committed
914
915
}

Sebastian Hack's avatar
Sebastian Hack committed
916
static arch_irn_class_t be_node_classify(const void *_self, const ir_node *irn)
Sebastian Hack's avatar
Sebastian Hack committed
917
{
Christian Würdig's avatar
Christian Würdig committed
918
	redir_proj((const ir_node **) &irn, -1);
Sebastian Hack's avatar
Sebastian Hack committed
919

Sebastian Hack's avatar
Sebastian Hack committed
920
	switch(be_get_irn_opcode(irn)) {
Sebastian Hack's avatar
Sebastian Hack committed
921
922
923
924
925
#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
926
#undef XXX
Sebastian Hack's avatar
Sebastian Hack committed
927
928
		default:
		return 0;
Sebastian Hack's avatar
Sebastian Hack committed
929
930
	}

Christian Würdig's avatar
Christian Würdig committed
931
	return 0;
Sebastian Hack's avatar
Sebastian Hack committed
932
933
}

Sebastian Hack's avatar
Sebastian Hack committed
934
static arch_irn_flags_t be_node_get_flags(const void *_self, const ir_node *irn)
Sebastian Hack's avatar
Sebastian Hack committed
935
{
Sebastian Hack's avatar
Sebastian Hack committed
936
	int out_pos;
Sebastian Hack's avatar
Sebastian Hack committed
937
938
	be_node_attr_t *a;

Sebastian Hack's avatar
Sebastian Hack committed
939
940
941
	out_pos = redir_proj((const ir_node **) &irn, -1);
	a       = get_irn_attr(irn);

Sebastian Hack's avatar
Sebastian Hack committed
942
	assert(is_be_node(irn));
Sebastian Hack's avatar
Sebastian Hack committed
943
944
945
	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
946
947
}

948
949
950
951
952
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
953
static void be_node_set_frame_offset(const void *self, ir_node *irn, int offset)
954
{
Sebastian Hack's avatar
Sebastian Hack committed
955
956
957
958
	if(be_has_frame_entity(irn)) {
		be_frame_attr_t *a = get_irn_attr(irn);
		a->offset = offset;
	}
959
960
961
}


962
static const arch_irn_ops_if_t be_node_irn_ops_if = {
Sebastian Hack's avatar
Sebastian Hack committed
963
964
965