benode.c 30.1 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
#define OUT_POS(x) (-((x) + 1))

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

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

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

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

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

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

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

96
97
98
99
100
101
102
103
104
105
106
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
107
108
109
110
111
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
112
static ir_op *op_Call;
Sebastian Hack's avatar
Sebastian Hack committed
113
static ir_op *op_Return;
Sebastian Hack's avatar
Sebastian Hack committed
114
115
static ir_op *op_IncSP;
static ir_op *op_AddSP;
Sebastian Hack's avatar
Sebastian Hack committed
116
static ir_op *op_SetSP;
Sebastian Hack's avatar
Sebastian Hack committed
117
118
static ir_op *op_RegParams;
static ir_op *op_StackParam;
119
120
121
static ir_op *op_FrameAddr;
static ir_op *op_FrameLoad;
static ir_op *op_FrameStore;
Sebastian Hack's avatar
Sebastian Hack committed
122

Sebastian Hack's avatar
Sebastian Hack committed
123
static int beo_base = -1;
Sebastian Hack's avatar
Sebastian Hack committed
124

Sebastian Hack's avatar
Sebastian Hack committed
125
static const ir_op_ops be_node_op_ops;
Sebastian Hack's avatar
Sebastian Hack committed
126

127
128
129
130
131
132
133
134
135
136
137
#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
138
139
void be_node_init(void) {
	static int inited = 0;
Sebastian Hack's avatar
Sebastian Hack committed
140

Sebastian Hack's avatar
Sebastian Hack committed
141
142
	if(inited)
		return;
Sebastian Hack's avatar
Sebastian Hack committed
143

Sebastian Hack's avatar
Sebastian Hack committed
144
	inited = 1;
Sebastian Hack's avatar
Sebastian Hack committed
145

146
147
	/* Acquire all needed opcodes. */
	beo_base = get_next_ir_opcodes(beo_Last - 1);
Sebastian Hack's avatar
Sebastian Hack committed
148

Sebastian Hack's avatar
Sebastian Hack committed
149
150
151
152
153
154
	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
155
	op_Return     = new_ir_op(beo_base + beo_Return,     "Return",     op_pin_state_pinned,     X, oparity_variable, 0, sizeof(be_node_attr_t),  &be_node_op_ops);
Sebastian Hack's avatar
Sebastian Hack committed
156
	op_AddSP      = new_ir_op(beo_base + beo_AddSP,      "AddSP",      op_pin_state_pinned,     N, oparity_unary,    0, sizeof(be_stack_attr_t), &be_node_op_ops);
Sebastian Hack's avatar
Sebastian Hack committed
157
	op_SetSP      = new_ir_op(beo_base + beo_SetSP,      "SetSP",      op_pin_state_pinned,     N, oparity_binary,   0, sizeof(be_stack_attr_t), &be_node_op_ops);
Sebastian Hack's avatar
Sebastian Hack committed
158
159
	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);
160
161
162
163
	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
164
165
166
167
168
169
170

	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
171
	set_op_tag(op_Return,     &be_node_tag);
Sebastian Hack's avatar
Sebastian Hack committed
172
	set_op_tag(op_AddSP,      &be_node_tag);
Sebastian Hack's avatar
Sebastian Hack committed
173
	set_op_tag(op_SetSP,      &be_node_tag);
Sebastian Hack's avatar
Sebastian Hack committed
174
175
176
	set_op_tag(op_IncSP,      &be_node_tag);
	set_op_tag(op_RegParams,  &be_node_tag);
	set_op_tag(op_StackParam, &be_node_tag);
177
178
179
	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
180
}
181

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

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

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

Sebastian Hack's avatar
Sebastian Hack committed
193
194
195
		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
196
197
			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
198
199
200
201
202
		}
	}

	return a;
}
203

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

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

Sebastian Hack's avatar
Sebastian Hack committed
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
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
237
	assert(out_pos < a->max_reg_data && "position too high");
Sebastian Hack's avatar
Sebastian Hack committed
238
239
240
241
	a->reg_data[out_pos].reg = reg;
}


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

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

	be_node_set_reg_class(res, 0, cls_frame);
	be_node_set_reg_class(res, 1, cls);
Sebastian Hack's avatar
Sebastian Hack committed
258
259
	return res;
}
260

Sebastian Hack's avatar
Sebastian Hack committed
261
ir_node *be_new_Reload(const arch_register_class_t *cls, const arch_register_class_t *cls_frame, ir_graph *irg, ir_node *bl, ir_node *frame, ir_node *mem, ir_mode *mode)
262
{
Sebastian Hack's avatar
Sebastian Hack committed
263
	ir_node *in[2];
Sebastian Hack's avatar
Sebastian Hack committed
264
	ir_node *res;
265

Sebastian Hack's avatar
Sebastian Hack committed
266
267
268
269
270
271
	in[0] = frame;
	in[1] = mem;
	res   = new_ir_node(NULL, irg, bl, op_Reload, mode, 2, in);
	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
272
273
	return res;
}
274

Sebastian Hack's avatar
Sebastian Hack committed
275
276
277
278
279
280
ir_node *(be_get_Reload_mem)(const ir_node *irn)
{
	assert(be_is_Reload(irn));
	return get_irn_n(irn, 1);
}

Sebastian Hack's avatar
Sebastian Hack committed
281
282
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
283
	int i;
Sebastian Hack's avatar
Sebastian Hack committed
284
	ir_node *irn = new_ir_node(NULL, irg, bl, op_Perm, mode_T, n, in);
Sebastian Hack's avatar
Sebastian Hack committed
285
286
287
288
289
290
	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
291
292
	return irn;
}
293

Sebastian Hack's avatar
Sebastian Hack committed
294
295
296
297
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;
298

Sebastian Hack's avatar
Sebastian Hack committed
299
300
	in[0] = op;
	res   = new_ir_node(NULL, irg, bl, op_Copy, get_irn_mode(op), 1, in);
Sebastian Hack's avatar
Sebastian Hack committed
301
302
303
	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
304
	return res;
305
306
}

Sebastian Hack's avatar
Sebastian Hack committed
307
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
308
{
Sebastian Hack's avatar
Sebastian Hack committed
309
	int i;
Sebastian Hack's avatar
Sebastian Hack committed
310
	ir_node *irn;
Sebastian Hack's avatar
Sebastian Hack committed
311

Sebastian Hack's avatar
Sebastian Hack committed
312
	irn = new_ir_node(NULL, irg, bl, op_Keep, mode_ANY, n, in);
Sebastian Hack's avatar
Sebastian Hack committed
313
314
315
316
	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
317
318
	keep_alive(irn);
	return irn;
Sebastian Hack's avatar
Sebastian Hack committed
319
320
}

Sebastian Hack's avatar
Sebastian Hack committed
321
ir_node *be_new_Call(ir_graph *irg, ir_node *bl, ir_node *mem, ir_node *sp, ir_node *ptr, int n_outs, int n, ir_node *in[])
Sebastian Hack's avatar
Sebastian Hack committed
322
{
Sebastian Hack's avatar
Sebastian Hack committed
323
324
325
	int real_n = 3 + n;
	ir_node *irn;
	ir_node **real_in;
Sebastian Hack's avatar
Sebastian Hack committed
326

Sebastian Hack's avatar
Sebastian Hack committed
327
328
329
330
331
332
333
334
	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
335
	init_node_attr(irn, (n_outs > real_n ? n_outs : real_n));
Sebastian Hack's avatar
Sebastian Hack committed
336
	return irn;
Sebastian Hack's avatar
Sebastian Hack committed
337
338
}

Sebastian Hack's avatar
Sebastian Hack committed
339
340
341
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);
Sebastian Hack's avatar
Sebastian Hack committed
342
	init_node_attr(irn, n);
Sebastian Hack's avatar
Sebastian Hack committed
343
344
345
346

	return irn;
}

347
ir_node *be_new_IncSP(const arch_register_t *sp, ir_graph *irg, ir_node *bl, ir_node *old_sp, ir_node *mem, unsigned offset, be_stack_dir_t dir)
Sebastian Hack's avatar
Sebastian Hack committed
348
{
Sebastian Hack's avatar
Sebastian Hack committed
349
350
351
352
353
	be_stack_attr_t *a;
	ir_node *irn;
	ir_node *in[1];

	in[0]     = old_sp;
354
355
	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
356
	a         = init_node_attr(irn, 1);
Sebastian Hack's avatar
Sebastian Hack committed
357
358
359
	a->dir    = dir;
	a->offset = offset;

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

Sebastian Hack's avatar
Sebastian Hack committed
362
	/* Set output constraint to stack register. */
Sebastian Hack's avatar
Sebastian Hack committed
363
	be_node_set_reg_class(irn, 0, sp->reg_class);
Sebastian Hack's avatar
Sebastian Hack committed
364
	be_set_constr_single_reg(irn, -1, sp);
Sebastian Hack's avatar
Sebastian Hack committed
365
	be_node_set_irn_reg(NULL, irn, sp);
Sebastian Hack's avatar
Sebastian Hack committed
366
367

	return irn;
Sebastian Hack's avatar
Sebastian Hack committed
368
}
Sebastian Hack's avatar
Sebastian Hack committed
369

Sebastian Hack's avatar
Sebastian Hack committed
370
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
371
{
Sebastian Hack's avatar
Sebastian Hack committed
372
	be_node_attr_t *a;
Sebastian Hack's avatar
Sebastian Hack committed
373
374
375
376
377
378
	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
379
	a        = init_node_attr(irn, 1);
Sebastian Hack's avatar
Sebastian Hack committed
380

Sebastian Hack's avatar
Sebastian Hack committed
381
	be_node_set_flags(irn, OUT_POS(0), arch_irn_flags_ignore);
Sebastian Hack's avatar
Sebastian Hack committed
382
383

	/* Set output constraint to stack register. */
Sebastian Hack's avatar
Sebastian Hack committed
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
	be_set_constr_single_reg(irn, OUT_POS(0), sp);
	be_node_set_irn_reg(NULL, irn, sp);

	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;
	irn      = new_ir_node(NULL, irg, bl, op_SetSP, get_irn_mode(old_sp), 3, in);
	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
408
	be_node_set_irn_reg(NULL, irn, sp);
Sebastian Hack's avatar
Sebastian Hack committed
409
410

	return irn;
Sebastian Hack's avatar
Sebastian Hack committed
411
}
Sebastian Hack's avatar
Sebastian Hack committed
412

Sebastian Hack's avatar
Sebastian Hack committed
413
ir_node *be_new_StackParam(const arch_register_class_t *cls, const arch_register_class_t *cls_frame, ir_graph *irg, ir_node *bl, ir_mode *mode, ir_node *frame_pointer, entity *ent)
Sebastian Hack's avatar
Sebastian Hack committed
414
{
415
	be_frame_attr_t *a;
Sebastian Hack's avatar
Sebastian Hack committed
416
417
418
	ir_node *irn;
	ir_node *in[1];

419
420
	in[0] = frame_pointer;
	irn = new_ir_node(NULL, irg, bl, op_StackParam, mode, 1, in);
Sebastian Hack's avatar
Sebastian Hack committed
421
	a = init_node_attr(irn, 1);
422
	a->ent = ent;
Sebastian Hack's avatar
Sebastian Hack committed
423
424
425

	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
426
	return irn;
Sebastian Hack's avatar
Sebastian Hack committed
427
}
Sebastian Hack's avatar
Sebastian Hack committed
428

429
ir_node *be_new_RegParams(ir_graph *irg, ir_node *bl, int n_outs)
Sebastian Hack's avatar
Sebastian Hack committed
430
431
432
433
{
	ir_node *irn;
	ir_node *in[1];

434
	irn = new_ir_node(NULL, irg, bl, op_RegParams, mode_T, 0, in);
Sebastian Hack's avatar
Sebastian Hack committed
435
	init_node_attr(irn, n_outs);
Sebastian Hack's avatar
Sebastian Hack committed
436
437
438
	return irn;
}

439
440
441
442
443
444
445
446
447
448
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);
Sebastian Hack's avatar
Sebastian Hack committed
449
	a      = init_node_attr(irn, 3);
450
451
452
	a->ent = ent;
	a->offset = 0;
	be_node_set_reg_class(irn, 1, cls_frame);
Sebastian Hack's avatar
Sebastian Hack committed
453
	be_node_set_reg_class(irn, OUT_POS(pn_Load_res), cls_data);
454
455
456
457
458
459
460
461
462
463
464
465
466
467
	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);
Sebastian Hack's avatar
Sebastian Hack committed
468
	a      = init_node_attr(irn, 3);
469
470
471
472
473
474
475
476
	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
477
{
478
	be_frame_attr_t *a;
Sebastian Hack's avatar
Sebastian Hack committed
479
480
481
	ir_node *irn;
	ir_node *in[1];

482
483
	in[0]  = frame;
	irn    = new_ir_node(NULL, irg, bl, op_FrameAddr, get_irn_mode(frame), 1, in);
Sebastian Hack's avatar
Sebastian Hack committed
484
	a      = init_node_attr(irn, 1);
485
486
487
	a->ent = ent;
	a->offset = 0;
	be_node_set_reg_class(irn, 0, cls_frame);
Sebastian Hack's avatar
Sebastian Hack committed
488
	be_node_set_reg_class(irn, OUT_POS(0), cls_frame);
Sebastian Hack's avatar
Sebastian Hack committed
489
490
491
	return irn;
}

Sebastian Hack's avatar
Sebastian Hack committed
492
493
494
495
496
497
498
499
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
500
int be_is_SetSP         (const ir_node *irn) { return be_get_irn_opcode(irn) == beo_SetSP          ; }
Sebastian Hack's avatar
Sebastian Hack committed
501
502
503
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     ; }
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
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;
}

522
entity *be_get_frame_entity(const ir_node *irn)
523
524
525
526
527
528
529
530
531
532
533
{
	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
534

Sebastian Hack's avatar
Sebastian Hack committed
535
static void be_limited(void *data, bitset_t *bs)
Sebastian Hack's avatar
Sebastian Hack committed
536
{
Sebastian Hack's avatar
Sebastian Hack committed
537
538
	be_req_t *req = data;

Sebastian Hack's avatar
Sebastian Hack committed
539
540
541
542
543
544
545
546
547
548
549
550
	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
551
552
}

Sebastian Hack's avatar
Sebastian Hack committed
553
static INLINE be_req_t *get_req(ir_node *irn, int pos)
Sebastian Hack's avatar
Sebastian Hack committed
554
{
Michael Beck's avatar
Michael Beck committed
555
	int idx           = pos < 0 ? -(pos + 1) : pos;
Sebastian Hack's avatar
Sebastian Hack committed
556
557
558
559
560
561
	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
562
	assert(!(pos < 0)  || -(pos + 1) <= a->max_reg_data);
Sebastian Hack's avatar
Sebastian Hack committed
563

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

579
580
void be_set_constr_limited(ir_node *irn, int pos, const arch_register_req_t *req)
{
Sebastian Hack's avatar
Sebastian Hack committed
581
	be_req_t *r = get_req(irn, pos);
582
583
584
585
586
587
588
589
590
591
592
593
594

	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
595
596
597
598
599
600
601
602
603
604
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
605
606
	if(r->req.type == arch_register_req_type_none)
		r->req.type = arch_register_req_type_normal;
Sebastian Hack's avatar
Sebastian Hack committed
607
608
}

Sebastian Hack's avatar
Sebastian Hack committed
609
610
611
612
613
614
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;
}
615

616
unsigned be_get_IncSP_offset(const ir_node *irn)
Sebastian Hack's avatar
Sebastian Hack committed
617
{
Sebastian Hack's avatar
Sebastian Hack committed
618
619
620
621
	be_stack_attr_t *a = get_irn_attr(irn);
	assert(be_is_IncSP(irn));
	return a->offset;
}
Sebastian Hack's avatar
Sebastian Hack committed
622

Sebastian Hack's avatar
Sebastian Hack committed
623
624
625
626
627
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
628
629
}

630
be_stack_dir_t be_get_IncSP_direction(const ir_node *irn)
Sebastian Hack's avatar
Sebastian Hack committed
631
{
Sebastian Hack's avatar
Sebastian Hack committed
632
633
634
	be_stack_attr_t *a = get_irn_attr(irn);
	assert(be_is_IncSP(irn));
	return a->dir;
Sebastian Hack's avatar
Sebastian Hack committed
635
636
}

637
void be_set_Spill_entity(ir_node *irn, entity *ent)
638
{
Sebastian Hack's avatar
Sebastian Hack committed
639
640
	be_spill_attr_t *a = get_irn_attr(irn);
	assert(be_is_Spill(irn));
641
	a->frame_attr.ent = ent;
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
}

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
658
		else if(be_get_irn_opcode(irn) == beo_Spill)
659
660
661
662
663
664
			return irn;
	}

	return NULL;
}

Sebastian Hack's avatar
Sebastian Hack committed
665
666
667
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));
668
669
670
	return a->spill_ctx;
}

671
672
673
674
675
676
/**
 * 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.
 */
677
static INLINE ir_node *find_a_spill(const ir_node *irn)
678
679
680
681
{
	ir_graph *irg       = get_irn_irg(irn);
	unsigned visited_nr = get_irg_visited(irg) + 1;

Sebastian Hack's avatar
Sebastian Hack committed
682
	assert(be_is_Reload(irn));
683
	set_irg_visited(irg, visited_nr);
Sebastian Hack's avatar
Sebastian Hack committed
684
	return find_a_spill_walker(be_get_Reload_mem(irn), visited_nr);
685
686
}

687
entity *be_get_spill_entity(const ir_node *irn)
688
{
Sebastian Hack's avatar
Sebastian Hack committed
689
	int opc           = get_irn_opcode(irn);
690

Sebastian Hack's avatar
Sebastian Hack committed
691
	switch(be_get_irn_opcode(irn)) {
Sebastian Hack's avatar
Sebastian Hack committed
692
	case beo_Reload:
693
		return be_get_spill_entity(find_a_spill(irn));
Sebastian Hack's avatar
Sebastian Hack committed
694
695
696
	case beo_Spill:
		{
			be_spill_attr_t *a = get_irn_attr(irn);
697
			return a->frame_attr.ent;
Sebastian Hack's avatar
Sebastian Hack committed
698
		}
699
	default:
Sebastian Hack's avatar
Sebastian Hack committed
700
		assert(0 && "Must give spill/reload node");
701
702
	}

703
	return NULL;
Sebastian Hack's avatar
Sebastian Hack committed
704
705
}

Sebastian Hack's avatar
Sebastian Hack committed
706
ir_node *be_spill(const arch_env_t *arch_env, ir_node *irn, ir_node *ctx)
Sebastian Hack's avatar
Sebastian Hack committed
707
{
Christian Würdig's avatar
Christian Würdig committed
708
709
	ir_node *bl    = get_nodes_block(irn);
	ir_graph *irg  = get_irn_irg(bl);
Sebastian Hack's avatar
Sebastian Hack committed
710
711
	ir_node *frame = get_irg_frame(irg);
	ir_node *spill;
Sebastian Hack's avatar
Sebastian Hack committed
712
713
	ir_node *insert;

Sebastian Hack's avatar
Sebastian Hack committed
714
715
716
717
718
	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
719
720
721
	/*
	 * 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
722
723
	 * 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
724
725
	 */
	insert = sched_next(irn);
Sebastian Hack's avatar
Sebastian Hack committed
726
	while((is_Phi(insert) || is_Proj(insert)) && !sched_is_end(insert))
Sebastian Hack's avatar
Sebastian Hack committed
727
728
		insert = sched_next(insert);

Sebastian Hack's avatar
Sebastian Hack committed
729
730
731
732
733
734
735
736
	/*
	 * 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.
	 */
	if(bl == get_irg_start_block(irg))
		insert = sched_next(frame);

Sebastian Hack's avatar
Sebastian Hack committed
737
	sched_add_before(insert, spill);
Christian Würdig's avatar
Christian Würdig committed
738
	return spill;
Sebastian Hack's avatar
Sebastian Hack committed
739
740
}

Sebastian Hack's avatar
Sebastian Hack committed
741
ir_node *be_reload(const arch_env_t *arch_env, const arch_register_class_t *cls, ir_node *reloader, ir_mode *mode, ir_node *spill)
Sebastian Hack's avatar
Sebastian Hack committed
742
743
744
{
	ir_node *reload;

Daniel Grund's avatar
Bugfix    
Daniel Grund committed
745
	ir_node *bl    = is_Block(reloader) ? reloader : get_nodes_block(reloader);
Sebastian Hack's avatar
Sebastian Hack committed
746
747
748
	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
749

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

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

Sebastian Hack's avatar
Sebastian Hack committed
754
	sched_add_before(reloader, reload);
Christian Würdig's avatar
Christian Würdig committed
755
	return reload;
Sebastian Hack's avatar
Sebastian Hack committed
756
}
Sebastian Hack's avatar
Sebastian Hack committed
757

Sebastian Hack's avatar
Sebastian Hack committed
758
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
759
{
Sebastian Hack's avatar
Sebastian Hack committed
760
	const be_node_attr_t *a = get_irn_attr(irn);
Daniel Grund's avatar
Daniel Grund committed
761

Sebastian Hack's avatar
Sebastian Hack committed
762
	if(out_pos < a->max_reg_data)
Sebastian Hack's avatar
Sebastian Hack committed
763
764
765
766
		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
767
	}
Sebastian Hack's avatar
Sebastian Hack committed
768

Sebastian Hack's avatar
Sebastian Hack committed
769
	return req;
Sebastian Hack's avatar
Sebastian Hack committed
770
771
}

Sebastian Hack's avatar
Sebastian Hack committed
772
static void *put_in_reg_req(arch_register_req_t *req, const ir_node *irn, int pos)
773
{
Sebastian Hack's avatar
Sebastian Hack committed
774
775
776
	const be_node_attr_t *a = get_irn_attr(irn);
	int n                   = get_irn_arity(irn);

Sebastian Hack's avatar
Sebastian Hack committed
777
	if(pos < get_irn_arity(irn) && pos < a->max_reg_data)
Sebastian Hack's avatar
Sebastian Hack committed
778
779
780
781
		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
782
783
784
	}

	return req;
785
786
}

Sebastian Hack's avatar
Sebastian Hack committed
787
static const arch_register_req_t *
788
be_node_get_irn_reg_req(const void *self, arch_register_req_t *req, const ir_node *irn, int pos)
Sebastian Hack's avatar
Sebastian Hack committed
789
{
Sebastian Hack's avatar
Sebastian Hack committed
790
	int out_pos = pos;
Sebastian Hack's avatar
Sebastian Hack committed
791

Sebastian Hack's avatar
Sebastian Hack committed
792
793
794
	if(pos < 0) {
		if(get_irn_mode(irn) == mode_T)
			return NULL;
Daniel Grund's avatar
Daniel Grund committed
795

Sebastian Hack's avatar
Sebastian Hack committed
796
797
798
799
		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
800

Sebastian Hack's avatar
Sebastian Hack committed
801
802
803
	else {
		return is_be_node(irn) ? put_in_reg_req(req, irn, pos) : NULL;
	}
Daniel Grund's avatar
Daniel Grund committed
804

Sebastian Hack's avatar
Sebastian Hack committed
805
	return req;
Sebastian Hack's avatar
Sebastian Hack committed
806
807
}

Sebastian Hack's avatar
Sebastian Hack committed
808
const arch_register_t *
809
be_node_get_irn_reg(const void *_self, const ir_node *irn)
Sebastian Hack's avatar
Sebastian Hack committed
810
811
812
{
	int out_pos;
	be_node_attr_t *a;
Daniel Grund's avatar
Daniel Grund committed
813

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

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

Sebastian Hack's avatar
Sebastian Hack committed
820
	return a->reg_data[out_pos].reg;
Sebastian Hack's avatar
Sebastian Hack committed
821
822
}

Sebastian Hack's avatar
Sebastian Hack committed
823
static arch_irn_class_t be_node_classify(const void *_self, const ir_node *irn)
Sebastian Hack's avatar
Sebastian Hack committed
824
{
Christian Würdig's avatar
Christian Würdig committed
825
	redir_proj((const ir_node **) &irn, -1);
Sebastian Hack's avatar
Sebastian Hack committed
826

Sebastian Hack's avatar
Sebastian Hack committed
827
	switch(be_get_irn_opcode(irn)) {
Sebastian Hack's avatar
Sebastian Hack committed
828
829
830
831
832
#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
833
#undef XXX
Sebastian Hack's avatar
Sebastian Hack committed
834
835
		default:
		return 0;
Sebastian Hack's avatar
Sebastian Hack committed
836
837
	}

Christian Würdig's avatar
Christian Würdig committed
838
	return 0;
Sebastian Hack's avatar
Sebastian Hack committed
839
840
}

Sebastian Hack's avatar
Sebastian Hack committed
841
static arch_irn_flags_t be_node_get_flags(const void *_self, const ir_node *irn)
Sebastian Hack's avatar
Sebastian Hack committed
842
{
Sebastian Hack's avatar
Sebastian Hack committed
843
	int out_pos;
Sebastian Hack's avatar
Sebastian Hack committed
844
845
	be_node_attr_t *a;

Sebastian Hack's avatar
Sebastian Hack committed
846
847
848
	out_pos = redir_proj((const ir_node **) &irn, -1);
	a       = get_irn_attr(irn);

Sebastian Hack's avatar
Sebastian Hack committed
849
	assert(is_be_node(irn));
Sebastian Hack's avatar
Sebastian Hack committed
850
851
852
	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
853
854
}

855
856
857
858
859
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
860
static void be_node_set_frame_offset(const void *self, ir_node *irn, int offset)
861
{
Sebastian Hack's avatar
Sebastian Hack committed
862
863
864
865
	if(be_has_frame_entity(irn)) {
		be_frame_attr_t *a = get_irn_attr(irn);
		a->offset = offset;
	}
866
867
868
}


869
static const arch_irn_ops_if_t be_node_irn_ops_if = {
Sebastian Hack's avatar
Sebastian Hack committed
870
871
872
873
874
	be_node_get_irn_reg_req,
	be_node_set_irn_reg,
	be_node_get_irn_reg,
	be_node_classify,
	be_node_get_flags,
875
	be_node_get_frame_entity,
Sebastian Hack's avatar
Sebastian Hack committed
876
	be_node_set_frame_offset
Sebastian Hack's avatar
Sebastian Hack committed
877
};
878

879
880
881
882
883
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)
884
{
Sebastian Hack's avatar
Sebastian Hack committed
885
886
	redir_proj((const ir_node **) &irn, -1);
	return is_be_node(irn) ? &be_node_irn_ops : NULL;
Sebastian Hack's avatar
Sebastian Hack committed
887
888
}

Sebastian Hack's avatar
Sebastian Hack committed
889
890
891
const arch_irn_handler_t be_node_irn_handler = {
	be_node_get_arch_ops
};
Sebastian Hack's avatar
Sebastian Hack committed
892

Sebastian Hack's avatar
Sebastian Hack committed
893
894
895

static void dump_node_req(FILE *f, be_req_t *req)
{
Sebastian Hack's avatar
Sebastian Hack committed
896
	unsigned i;
Sebastian Hack's avatar
Sebastian Hack committed
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
	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);
	}
}

947
948
static int dump_node(ir_node *irn, FILE *f, dump_reason_t reason)
{
Sebastian Hack's avatar
Sebastian Hack committed
949
	be_node_attr_t *at = get_irn_attr(irn);
950

951
952
	assert(is_be_node(irn));

953
954
	switch(reason) {
		case dump_node_opcode_txt:
Sebastian Hack's avatar
Sebastian Hack committed
955
			fprintf(f, get_op_name(get_irn_op(irn)));
956
957
958
959
960
961
962
			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
963
			dump_node_reqs(f, irn);
964

965
966
			if(be_has_frame_entity(irn)) {
				be_frame_attr_t *a = (be_frame_attr_t *) at;
Sebastian Hack's avatar
Sebastian Hack committed
967
968
969
				if (a->ent)
					ir_fprintf(f, "frame entity: %+F offset %x (%d)\n", a->ent, a->offset, a->offset);

970
971
			}

Sebastian Hack's avatar
Sebastian Hack committed
972
			switch(be_get_irn_opcode(irn)) {
Sebastian Hack's avatar
Sebastian Hack committed
973
974
975
976
			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
977
				}
Sebastian Hack's avatar
Sebastian Hack committed
978
979
980
981
982
983
984
				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
985
				}
Sebastian Hack's avatar
Sebastian Hack committed
986
				break;
987
			}
Sebastian Hack's avatar
Sebastian Hack committed
988

989
990
	}

991
	return 0;
992
993
}

Sebastian Hack's avatar
Sebastian Hack committed
994
995
996
997
/**
 * 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
998
{
Sebastian Hack's avatar
Sebastian Hack committed
999
	be_node_attr_t *old_attr = get_irn_attr(old_node);
Sebastian Hack's avatar
Sebastian Hack committed
1000
	be_node_attr_t *new_attr = get_irn_attr(new_node);
Sebastian Hack's avatar
Sebastian Hack committed
1001
	int i;
Sebastian Hack's avatar
Sebastian Hack committed
1002
1003
1004
1005

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

Sebastian Hack's avatar
Sebastian Hack committed
1006
1007
	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
1008

Sebastian Hack's avatar
Sebastian Hack committed
1009
1010
1011
	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));