benode.c 31 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
typedef struct {
	be_node_attr_t node_attr;
	entity *ent;
	int offset;
} be_frame_attr_t;

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

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

112
113
114
115
116
117
118
119
ir_op *op_be_Spill;
ir_op *op_be_Reload;
ir_op *op_be_Perm;
ir_op *op_be_Copy;
ir_op *op_be_Keep;
ir_op *op_be_Call;
ir_op *op_be_Return;
ir_op *op_be_IncSP;
120
ir_op *op_be_Alloca;
121
122
123
124
125
126
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
127

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

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

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

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

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

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

154
	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);
155
	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);
156
157
158
159
160
	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);
	op_be_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);
	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);
161
	op_be_Alloca     = new_ir_op(beo_base + beo_Alloca,     "Alloca",     op_pin_state_pinned,     N, oparity_unary,    0, sizeof(be_node_attr_t),  &be_node_op_ops);
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
	op_be_SetSP      = new_ir_op(beo_base + beo_SetSP,      "SetSP",      op_pin_state_pinned,     N, oparity_binary,   0, sizeof(be_stack_attr_t), &be_node_op_ops);
	op_be_IncSP      = new_ir_op(beo_base + beo_IncSP,      "IncSP",      op_pin_state_pinned,     N, oparity_binary,   0, sizeof(be_stack_attr_t), &be_node_op_ops);
	op_be_RegParams  = new_ir_op(beo_base + beo_RegParams,  "RegParams",  op_pin_state_pinned,     N, oparity_zero,     0, sizeof(be_node_attr_t),  &be_node_op_ops);
	op_be_StackParam = new_ir_op(beo_base + beo_StackParam, "StackParam", op_pin_state_pinned,     N, oparity_unary,    0, sizeof(be_frame_attr_t), &be_node_op_ops);
	op_be_FrameAddr  = new_ir_op(beo_base + beo_FrameAddr,  "FrameAddr",  op_pin_state_pinned,     N, oparity_binary,   0, sizeof(be_frame_attr_t), &be_node_op_ops);
	op_be_FrameLoad  = new_ir_op(beo_base + beo_FrameLoad,  "FrameLoad",  op_pin_state_pinned,     N, oparity_any,      0, sizeof(be_frame_attr_t), &be_node_op_ops);
	op_be_FrameStore = new_ir_op(beo_base + beo_FrameStore, "FrameStore", op_pin_state_pinned,     N, oparity_any,      0, sizeof(be_frame_attr_t), &be_node_op_ops);

	set_op_tag(op_be_Spill,      &be_node_tag);
	set_op_tag(op_be_Reload,     &be_node_tag);
	set_op_tag(op_be_Perm,       &be_node_tag);
	set_op_tag(op_be_Copy,       &be_node_tag);
	set_op_tag(op_be_Keep,       &be_node_tag);
	set_op_tag(op_be_Call,       &be_node_tag);
	set_op_tag(op_be_Return,     &be_node_tag);
177
	set_op_tag(op_be_Alloca,     &be_node_tag);
178
179
180
181
182
183
184
	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
185
}
186

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

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

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

Sebastian Hack's avatar
Sebastian Hack committed
199
200
201
		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
202
203
			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
204
205
206
207
208
		}
	}

	return a;
}
209

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

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

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

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

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


Sebastian Hack's avatar
Sebastian Hack committed
254
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)
255
{
Sebastian Hack's avatar
Sebastian Hack committed
256
	be_spill_attr_t *a;
Sebastian Hack's avatar
Sebastian Hack committed
257
	ir_node *in[2];
Sebastian Hack's avatar
Sebastian Hack committed
258
	ir_node *res;
259

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

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

Sebastian Hack's avatar
Sebastian Hack committed
273
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)
274
{
Sebastian Hack's avatar
Sebastian Hack committed
275
	ir_node *in[2];
Sebastian Hack's avatar
Sebastian Hack committed
276
	ir_node *res;
277

Sebastian Hack's avatar
Sebastian Hack committed
278
279
	in[0] = frame;
	in[1] = mem;
280
	res   = new_ir_node(NULL, irg, bl, op_be_Reload, mode, 2, in);
Sebastian Hack's avatar
Sebastian Hack committed
281
282
283
	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
284
285
	return res;
}
286

Sebastian Hack's avatar
Sebastian Hack committed
287
288
289
290
291
292
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
293
294
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
295
	int i;
296
	ir_node *irn = new_ir_node(NULL, irg, bl, op_be_Perm, mode_T, n, in);
Sebastian Hack's avatar
Sebastian Hack committed
297
298
299
300
301
302
	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
303
304
	return irn;
}
305

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

Sebastian Hack's avatar
Sebastian Hack committed
311
	in[0] = op;
312
	res   = new_ir_node(NULL, irg, bl, op_be_Copy, get_irn_mode(op), 1, in);
Sebastian Hack's avatar
Sebastian Hack committed
313
314
315
	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
316
	return res;
317
318
}

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

324
	irn = new_ir_node(NULL, irg, bl, op_be_Keep, mode_ANY, n, in);
Sebastian Hack's avatar
Sebastian Hack committed
325
326
327
328
	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
329
330
	keep_alive(irn);
	return irn;
Sebastian Hack's avatar
Sebastian Hack committed
331
332
}

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

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

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

351
352
353
354
355
356
357
358
359
360
361
362
363
364
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
365
366
ir_node *be_new_Return(ir_graph *irg, ir_node *bl, int n, ir_node *in[])
{
367
	ir_node *irn = new_ir_node(NULL, irg, bl, op_be_Return, mode_X, n, in);
Sebastian Hack's avatar
Sebastian Hack committed
368
	init_node_attr(irn, n);
Sebastian Hack's avatar
Sebastian Hack committed
369
370
371
372

	return irn;
}

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

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

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

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

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

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

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

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

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

	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;
425
	irn      = new_ir_node(NULL, irg, bl, op_be_SetSP, get_irn_mode(old_sp), 3, in);
Sebastian Hack's avatar
Sebastian Hack committed
426
427
428
429
430
431
432
433
	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
434
	be_node_set_irn_reg(NULL, irn, sp);
Sebastian Hack's avatar
Sebastian Hack committed
435
436

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

Sebastian Hack's avatar
Sebastian Hack committed
439
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
440
{
441
	be_frame_attr_t *a;
Sebastian Hack's avatar
Sebastian Hack committed
442
443
444
	ir_node *irn;
	ir_node *in[1];

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

	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
452
	return irn;
Sebastian Hack's avatar
Sebastian Hack committed
453
}
Sebastian Hack's avatar
Sebastian Hack committed
454

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

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

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

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

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

	return 0;
}

549
entity *be_get_frame_entity(const ir_node *irn)
550
551
552
553
554
555
556
{
	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
557

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

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

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

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

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

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

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

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

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

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

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

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

	set_irn_visited(irn, visited_nr);
672

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

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

687
688
689
	return NULL;
}

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

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

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

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

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

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

735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
static void entity_copy_walker(ir_node *irn, void *data)
{
	if(be_is_Reload(irn)) {
		be_frame_attr_t *a = get_irn_attr(irn);
		entity *ent        = be_get_spill_entity(irn);

		a->ent = ent;
	}
}

void be_copy_entities_to_reloads(ir_graph *irg)
{
	irg_walk_graph(irg, entity_copy_walker, NULL, NULL);
}

Sebastian Hack's avatar
Sebastian Hack committed
750
ir_node *be_spill(const arch_env_t *arch_env, ir_node *irn, ir_node *ctx)
Sebastian Hack's avatar
Sebastian Hack committed
751
{
Christian Würdig's avatar
Christian Würdig committed
752
753
	ir_node *bl    = get_nodes_block(irn);
	ir_graph *irg  = get_irn_irg(bl);
Sebastian Hack's avatar
Sebastian Hack committed
754
755
	ir_node *frame = get_irg_frame(irg);
	ir_node *spill;
Sebastian Hack's avatar
Sebastian Hack committed
756
757
	ir_node *insert;

Sebastian Hack's avatar
Sebastian Hack committed
758
759
760
761
762
	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
763
764
765
	/*
	 * 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
766
767
	 * 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
768
769
	 */
	insert = sched_next(irn);
Sebastian Hack's avatar
Sebastian Hack committed
770
	while((is_Phi(insert) || is_Proj(insert)) && !sched_is_end(insert))
Sebastian Hack's avatar
Sebastian Hack committed
771
772
		insert = sched_next(insert);

Sebastian Hack's avatar
Sebastian Hack committed
773
774
775
776
777
778
779
780
	/*
	 * 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
781
	sched_add_before(insert, spill);
Christian Würdig's avatar
Christian Würdig committed
782
	return spill;
Sebastian Hack's avatar
Sebastian Hack committed
783
784
}

Sebastian Hack's avatar
Sebastian Hack committed
785
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
786
787
788
{
	ir_node *reload;

Daniel Grund's avatar
Bugfix    
Daniel Grund committed
789
	ir_node *bl    = is_Block(reloader) ? reloader : get_nodes_block(reloader);
Sebastian Hack's avatar
Sebastian Hack committed
790
791
792
	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
793

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

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

Sebastian Hack's avatar
Sebastian Hack committed
798
	sched_add_before(reloader, reload);
Christian Würdig's avatar
Christian Würdig committed
799
	return reload;
Sebastian Hack's avatar
Sebastian Hack committed
800
}
Sebastian Hack's avatar
Sebastian Hack committed
801

Sebastian Hack's avatar
Sebastian Hack committed
802
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
803
{
Sebastian Hack's avatar
Sebastian Hack committed
804
	const be_node_attr_t *a = get_irn_attr(irn);
Daniel Grund's avatar
Daniel Grund committed
805

Sebastian Hack's avatar
Sebastian Hack committed
806
	if(out_pos < a->max_reg_data)
Sebastian Hack's avatar
Sebastian Hack committed
807
808
809
810
		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
811
	}
Sebastian Hack's avatar
Sebastian Hack committed
812

Sebastian Hack's avatar
Sebastian Hack committed
813
	return req;
Sebastian Hack's avatar
Sebastian Hack committed
814
815
}

Sebastian Hack's avatar
Sebastian Hack committed
816
static void *put_in_reg_req(arch_register_req_t *req, const ir_node *irn, int pos)
817
{
Sebastian Hack's avatar
Sebastian Hack committed
818
819
820
	const be_node_attr_t *a = get_irn_attr(irn);
	int n                   = get_irn_arity(irn);

Sebastian Hack's avatar
Sebastian Hack committed
821
	if(pos < get_irn_arity(irn) && pos < a->max_reg_data)
Sebastian Hack's avatar
Sebastian Hack committed
822
823
824
825
		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
826
827
828
	}

	return req;
829
830
}

Sebastian Hack's avatar
Sebastian Hack committed
831
static const arch_register_req_t *
832
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
833
{
Sebastian Hack's avatar
Sebastian Hack committed
834
	int out_pos = pos;
Sebastian Hack's avatar
Sebastian Hack committed
835

Sebastian Hack's avatar
Sebastian Hack committed
836
837
838
	if(pos < 0) {
		if(get_irn_mode(irn) == mode_T)
			return NULL;
Daniel Grund's avatar
Daniel Grund committed
839

Sebastian Hack's avatar
Sebastian Hack committed
840
841
842
843
		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
844

Sebastian Hack's avatar
Sebastian Hack committed
845
846
847
	else {
		return is_be_node(irn) ? put_in_reg_req(req, irn, pos) : NULL;
	}
Daniel Grund's avatar
Daniel Grund committed
848

Sebastian Hack's avatar
Sebastian Hack committed
849
	return req;
Sebastian Hack's avatar
Sebastian Hack committed
850
851
}

Sebastian Hack's avatar
Sebastian Hack committed
852
const arch_register_t *
853
be_node_get_irn_reg(const void *_self, const ir_node *irn)
Sebastian Hack's avatar
Sebastian Hack committed
854
855
856
{
	int out_pos;
	be_node_attr_t *a;
Daniel Grund's avatar
Daniel Grund committed
857

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

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

Sebastian Hack's avatar
Sebastian Hack committed
864
	return a->reg_data[out_pos].reg;
Sebastian Hack's avatar
Sebastian Hack committed
865
866
}

Sebastian Hack's avatar
Sebastian Hack committed
867
static arch_irn_class_t be_node_classify(const void *_self, const ir_node *irn)
Sebastian Hack's avatar
Sebastian Hack committed
868
{
Christian Würdig's avatar
Christian Würdig committed
869
	redir_proj((const ir_node **) &irn, -1);
Sebastian Hack's avatar
Sebastian Hack committed
870

Sebastian Hack's avatar
Sebastian Hack committed
871
	switch(be_get_irn_opcode(irn)) {
Sebastian Hack's avatar
Sebastian Hack committed
872
873
874
875
876
#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
877
#undef XXX
Sebastian Hack's avatar
Sebastian Hack committed
878
879
		default:
		return 0;
Sebastian Hack's avatar
Sebastian Hack committed
880
881
	}

Christian Würdig's avatar
Christian Würdig committed
882
	return 0;
Sebastian Hack's avatar
Sebastian Hack committed
883
884
}

Sebastian Hack's avatar
Sebastian Hack committed
885
static arch_irn_flags_t be_node_get_flags(const void *_self, const ir_node *irn)
Sebastian Hack's avatar
Sebastian Hack committed
886
{
Sebastian Hack's avatar
Sebastian Hack committed
887
	int out_pos;
Sebastian Hack's avatar
Sebastian Hack committed
888
889
	be_node_attr_t *a;

Sebastian Hack's avatar
Sebastian Hack committed
890
891
892
	out_pos = redir_proj((const ir_node **) &irn, -1);
	a       = get_irn_attr(irn);

Sebastian Hack's avatar
Sebastian Hack committed
893
	assert(is_be_node(irn));
Sebastian Hack's avatar
Sebastian Hack committed
894
895
896
	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
897
898
}

899
900
901
902
903
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
904
static void be_node_set_frame_offset(const void *self, ir_node *irn, int offset)
905
{
Sebastian Hack's avatar
Sebastian Hack committed
906
907
908
909
	if(be_has_frame_entity(irn)) {
		be_frame_attr_t *a = get_irn_attr(irn);
		a->offset = offset;
	}
910
911
912
}


913
static const arch_irn_ops_if_t be_node_irn_ops_if = {
Sebastian Hack's avatar
Sebastian Hack committed
914
915
916
917
918
	be_node_get_irn_reg_req,
	be_node_set_irn_reg,
	be_node_get_irn_reg,
	be_node_classify,
	be_node_get_flags,
919
	be_node_get_frame_entity,
Sebastian Hack's avatar
Sebastian Hack committed
920
	be_node_set_frame_offset
Sebastian Hack's avatar
Sebastian Hack committed
921
};
922

923
924
925
926
927
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)
928
{
Sebastian Hack's avatar
Sebastian Hack committed
929
930
	redir_proj((const ir_node **) &irn, -1);
	return is_be_node(irn) ? &be_node_irn_ops : NULL;
Sebastian Hack's avatar
Sebastian Hack committed
931
932
}

Sebastian Hack's avatar
Sebastian Hack committed
933
934
935
const arch_irn_handler_t be_node_irn_handler = {
	be_node_get_arch_ops
};
Sebastian Hack's avatar
Sebastian Hack committed
936

Sebastian Hack's avatar
Sebastian Hack committed
937
938
939

static void dump_node_req(FILE *f, be_req_t *req)
{
Sebastian Hack's avatar
Sebastian Hack committed
940
	unsigned i;
Sebastian Hack's avatar
Sebastian Hack committed
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
	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);
	}
}

991
992
static int dump_node(ir_node *irn, FILE *f, dump_reason_t reason)
{
Sebastian Hack's avatar
Sebastian Hack committed
993
	be_node_attr_t *at = get_irn_attr(irn);
994

995
996
	assert(is_be_node(irn));

997
998
	switch(reason) {
		case dump_node_opcode_txt:
Sebastian Hack's avatar
Sebastian Hack committed
999
			fprintf(f, get_op_name(get_irn_op(irn)));
1000
1001
1002
1003
1004
1005
1006
			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
1007
			dump_node_reqs(f, irn);