benode.c 20.7 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
2
/*
 * This file is part of libFirm.
3
 * Copyright (C) 2012 University of Karlsruhe.
Christian Würdig's avatar
Christian Würdig committed
4
5
 */

Sebastian Hack's avatar
Sebastian Hack committed
6
/**
Christian Würdig's avatar
Christian Würdig committed
7
8
9
 * @file
 * @brief       Backend node support for generic backend nodes.
 * @author      Sebastian Hack
Sebastian Hack's avatar
Sebastian Hack committed
10
 *
11
 * Backend node support for generic backend nodes.
Sebastian Hack's avatar
Sebastian Hack committed
12
13
14
 */
#include <stdlib.h>

Matthias Braun's avatar
Matthias Braun committed
15
16
17
18
#include "array.h"
#include "be_t.h"
#include "bearch.h"
#include "bedump.h"
19
#include "beirg.h"
Matthias Braun's avatar
Matthias Braun committed
20
21
22
23
#include "belive.h"
#include "benode.h"
#include "besched.h"
#include "bitfiddle.h"
Sebastian Hack's avatar
Sebastian Hack committed
24
#include "debug.h"
25
#include "fourcc.h"
Matthias Braun's avatar
Matthias Braun committed
26
#include "irbackedge_t.h"
27
#include "ircons_t.h"
Matthias Braun's avatar
Matthias Braun committed
28
#include "irgopt.h"
Sebastian Hack's avatar
Sebastian Hack committed
29
#include "irgwalk.h"
Matthias Braun's avatar
Matthias Braun committed
30
31
32
#include "irmode_t.h"
#include "irnode_t.h"
#include "irop_t.h"
Michael Beck's avatar
Michael Beck committed
33
#include "iropt_t.h"
Matthias Braun's avatar
Matthias Braun committed
34
#include "irprintf.h"
35
#include "irverify_t.h"
Matthias Braun's avatar
Matthias Braun committed
36
37
38
39
40
41
#include "obst.h"
#include "panic.h"
#include "pmap.h"
#include "raw_bitset.h"
#include "set.h"
#include "util.h"
Sebastian Hack's avatar
Sebastian Hack committed
42

43
typedef struct be_node_attr_t {
Matthias Braun's avatar
Matthias Braun committed
44
	except_attr exc;
45
46
} be_node_attr_t;

Michael Beck's avatar
Michael Beck committed
47
/** The be_IncSP attribute type. */
Sebastian Hack's avatar
Sebastian Hack committed
48
typedef struct {
49
	be_node_attr_t base;
Matthias Braun's avatar
Matthias Braun committed
50
51
	int            offset; /**< The offset by which the stack shall be
	                            expanded/shrinked. */
52
	unsigned       align;  /**< alignment after the IncSP (0=no alignment) */
Michael Beck's avatar
Michael Beck committed
53
} be_incsp_attr_t;
Sebastian Hack's avatar
Sebastian Hack committed
54

55
typedef struct {
56
57
58
	be_node_attr_t base;
	ir_entity    **in_entities;
	ir_entity    **out_entities;
59
	int            offset;
Matthias Braun's avatar
Matthias Braun committed
60
} be_memperm_attr_t;
61

Matthias Braun's avatar
Matthias Braun committed
62
ir_op *op_be_AnyVal;
63
ir_op *op_be_Copy;
Sebastian Hack's avatar
Sebastian Hack committed
64
ir_op *op_be_CopyKeep;
65
ir_op *op_be_IncSP;
Matthias Braun's avatar
Matthias Braun committed
66
67
68
ir_op *op_be_Keep;
ir_op *op_be_MemPerm;
ir_op *op_be_Perm;
Sebastian Hack's avatar
Sebastian Hack committed
69

70
71
#define be_op_tag FOURCC('B', 'E', '\0', '\0')

Michael Beck's avatar
Michael Beck committed
72
73
74
/**
 * Compare the attributes of two be_IncSP nodes.
 */
75
static int be_incsp_attrs_equal(const ir_node *a, const ir_node *b)
76
{
Matthias Braun's avatar
Matthias Braun committed
77
78
79
80
	const be_incsp_attr_t *attr_a
		= (const be_incsp_attr_t*)get_irn_generic_attr_const(a);
	const be_incsp_attr_t *attr_b
		= (const be_incsp_attr_t*)get_irn_generic_attr_const(b);
81
	return attr_a->offset == attr_b->offset && attrs_equal_be_node(a, b);
82
83
}

84
static arch_register_req_t *allocate_reg_req(ir_graph *const irg)
Matthias Braun's avatar
Matthias Braun committed
85
{
86
	struct obstack *obst = be_get_be_obst(irg);
87
	arch_register_req_t *req = OALLOCZ(obst, arch_register_req_t);
88
89
	return req;
}
Matthias Braun's avatar
Matthias Braun committed
90

Matthias Braun's avatar
Matthias Braun committed
91
92
static void be_node_set_register_req_in(ir_node *const node, int const pos,
                                        arch_register_req_t const *const req)
93
{
94
95
96
	backend_info_t *info = be_get_info(node);
	assert(pos < get_irn_arity(node));
	info->in_reqs[pos] = req;
97
}
Matthias Braun's avatar
Matthias Braun committed
98

99
/**
100
 * Initializes the generic attribute of all be nodes and return it.
101
 */
102
static void init_node_attr(ir_node *const node, unsigned const n_outputs, arch_irn_flags_t const flags)
Sebastian Hack's avatar
Sebastian Hack committed
103
{
104
	ir_graph       *irg  = get_irn_irg(node);
105
	struct obstack *obst = be_get_be_obst(irg);
106
	backend_info_t *info = be_get_info(node);
Sebastian Hack's avatar
Sebastian Hack committed
107

108
	unsigned                    const arity   = get_irn_arity(node);
109
110
111
112
113
114
	arch_register_req_t const **const in_reqs =
		is_irn_dynamic(node) ? NEW_ARR_F(arch_register_req_t const*, arity) :
		arity != 0           ? OALLOCN(obst, arch_register_req_t const*, arity) :
		NULL;
	for (unsigned i = 0; i < arity; ++i) {
		in_reqs[i] = arch_no_register_req;
115
	}
116
	info->in_reqs = in_reqs;
117

118
	info->out_infos = NEW_ARR_DZ(reg_out_info_t, obst, n_outputs);
Matthias Braun's avatar
Matthias Braun committed
119
	for (unsigned i = 0; i < n_outputs; ++i) {
120
		info->out_infos[i].req = arch_no_register_req;
Sebastian Hack's avatar
Sebastian Hack committed
121
	}
Matthias Braun's avatar
Matthias Braun committed
122
	info->flags = flags;
Sebastian Hack's avatar
Sebastian Hack committed
123
}
124

Matthias Braun's avatar
Matthias Braun committed
125
126
127
ir_node *be_new_Perm(arch_register_class_t const *const cls,
                     ir_node *const block, int const n,
                     ir_node *const *const in)
Sebastian Hack's avatar
Sebastian Hack committed
128
{
129
	ir_graph *irg = get_irn_irg(block);
Matthias Braun's avatar
Matthias Braun committed
130
	ir_node  *irn = new_ir_node(NULL, irg, block, op_be_Perm, mode_T, n, in);
131
	init_node_attr(irn, n, arch_irn_flags_none);
Matthias Braun's avatar
Matthias Braun committed
132
	be_node_attr_t *attr = (be_node_attr_t*)get_irn_generic_attr(irn);
133
	attr->exc.pin_state = op_pin_state_pinned;
Matthias Braun's avatar
Matthias Braun committed
134
	for (int i = 0; i < n; ++i) {
135
136
137
		const ir_node             *input = in[i];
		const arch_register_req_t *req   = arch_get_irn_register_req(input);
		if (req->width == 1) {
Matthias Braun's avatar
Matthias Braun committed
138
139
			be_node_set_register_req_in(irn, i, cls->class_req);
			arch_set_irn_register_req_out(irn, i, cls->class_req);
140
		} else {
141
			arch_register_req_t *const new_req = allocate_reg_req(irg);
142
143
144
			new_req->cls   = cls;
			new_req->type  = (req->type & arch_register_req_type_aligned);
			new_req->width = req->width;
Matthias Braun's avatar
Matthias Braun committed
145
146
			be_node_set_register_req_in(irn, i, new_req);
			arch_set_irn_register_req_out(irn, i, new_req);
147
		}
Sebastian Hack's avatar
Sebastian Hack committed
148
149
	}

Sebastian Hack's avatar
Sebastian Hack committed
150
151
	return irn;
}
152

153
ir_node *be_new_MemPerm(ir_node *const block, int n, ir_node *const *const in)
Matthias Braun's avatar
Matthias Braun committed
154
{
155
156
	ir_graph *const irg = get_irn_irg(block);
	ir_node  *const irn = new_ir_node(NULL, irg, block, op_be_MemPerm, mode_T, n, in);
Matthias Braun's avatar
Matthias Braun committed
157

158
	init_node_attr(irn, n, arch_irn_flags_none);
Matthias Braun's avatar
Matthias Braun committed
159

Matthias Braun's avatar
Matthias Braun committed
160
	be_memperm_attr_t *attr = (be_memperm_attr_t*)get_irn_generic_attr(irn);
161
162
	attr->in_entities  = OALLOCNZ(get_irg_obstack(irg), ir_entity*, n);
	attr->out_entities = OALLOCNZ(get_irg_obstack(irg), ir_entity*, n);
163
	attr->offset       = 0;
Matthias Braun's avatar
Matthias Braun committed
164
165
166
	return irn;
}

167
ir_node *be_new_Copy(ir_node *bl, ir_node *op)
Sebastian Hack's avatar
Sebastian Hack committed
168
{
169
	ir_graph *irg  = get_irn_irg(bl);
Matthias Braun's avatar
Matthias Braun committed
170
171
172
	ir_node  *in[] = { op };
	ir_node  *res  = new_ir_node(NULL, irg, bl, op_be_Copy, get_irn_mode(op),
	                             ARRAY_SIZE(in), in);
173
	init_node_attr(res, 1, arch_irn_flags_none);
Matthias Braun's avatar
Matthias Braun committed
174
	be_node_attr_t *attr = (be_node_attr_t*) get_irn_generic_attr(res);
175
	attr->exc.pin_state = op_pin_state_floats;
Matthias Braun's avatar
Matthias Braun committed
176
177
178

	const arch_register_req_t   *in_req = arch_get_irn_register_req(op);
	const arch_register_class_t *cls    = in_req->cls;
Matthias Braun's avatar
Matthias Braun committed
179
180
	be_node_set_register_req_in(res, 0, cls->class_req);
	arch_set_irn_register_req_out(res, 0, cls->class_req);
Matthias Braun's avatar
Matthias Braun committed
181

182
	arch_register_req_t *const req = allocate_reg_req(irg);
Matthias Braun's avatar
Matthias Braun committed
183
184
185
	req->cls  = cls;
	req->type = arch_register_req_type_should_be_same
	            | (in_req->type & arch_register_req_type_aligned);
186
	req->other_same = 1U << 0;
187
	req->width      = in_req->width;
Matthias Braun's avatar
Matthias Braun committed
188
	arch_set_irn_register_req_out(res, 0, req);
Sebastian Hack's avatar
Sebastian Hack committed
189
	return res;
190
191
}

192
193
ir_node *be_get_Copy_op(const ir_node *cpy)
{
194
	return get_irn_n(cpy, n_be_Copy_op);
195
196
}

Matthias Braun's avatar
Matthias Braun committed
197
198
ir_node *be_new_Keep(ir_node *const block, int const n,
                     ir_node *const *const in)
Sebastian Hack's avatar
Sebastian Hack committed
199
{
200
	ir_graph *irg = get_irn_irg(block);
201
	ir_node  *res = new_ir_node(NULL, irg, block, op_be_Keep, mode_ANY, n, in);
202
	init_node_attr(res, 1, arch_irn_flag_schedule_first);
Matthias Braun's avatar
Matthias Braun committed
203
	be_node_attr_t *attr = (be_node_attr_t*) get_irn_generic_attr(res);
204
	attr->exc.pin_state = op_pin_state_pinned;
Sebastian Hack's avatar
Sebastian Hack committed
205

Matthias Braun's avatar
Matthias Braun committed
206
	for (int i = 0; i < n; ++i) {
207
		arch_register_req_t const *req = arch_get_irn_register_req(in[i]);
208
		req = req->cls != NULL ? req->cls->class_req : arch_no_register_req;
209
		be_node_set_register_req_in(res, i, req);
Sebastian Hack's avatar
Sebastian Hack committed
210
	}
211
212
213
214
	keep_alive(res);
	return res;
}

215
216
217
218
219
220
221
ir_node *be_new_Keep_one(ir_node *const kept)
{
	ir_node *const in[]  = { kept };
	ir_node *const block = get_nodes_block(kept);
	return be_new_Keep(block, ARRAY_SIZE(in), in);
}

222
ir_node *be_new_IncSP(const arch_register_t *sp, ir_node *bl,
223
                      ir_node *old_sp, int offset, unsigned align)
Sebastian Hack's avatar
Sebastian Hack committed
224
{
225
	ir_graph *irg = get_irn_irg(bl);
Matthias Braun's avatar
Matthias Braun committed
226
	ir_node  *in[] = { old_sp };
Matthias Braun's avatar
Matthias Braun committed
227
228
	ir_node  *irn  = new_ir_node(NULL, irg, bl, op_be_IncSP, sp->cls->mode,
	                             ARRAY_SIZE(in), in);
229
	init_node_attr(irn, 1, arch_irn_flags_none);
Matthias Braun's avatar
Matthias Braun committed
230
	be_incsp_attr_t *a    = (be_incsp_attr_t*)get_irn_generic_attr(irn);
231
232
233
	a->offset             = offset;
	a->align              = align;
	a->base.exc.pin_state = op_pin_state_pinned;
Sebastian Hack's avatar
Sebastian Hack committed
234
235

	/* Set output constraint to stack register. */
Matthias Braun's avatar
Matthias Braun committed
236
	be_node_set_register_req_in(irn, 0, sp->cls->class_req);
237
	be_set_constr_single_reg_out(irn, 0, sp, arch_register_req_type_produces_sp);
Sebastian Hack's avatar
Sebastian Hack committed
238
	return irn;
Sebastian Hack's avatar
Sebastian Hack committed
239
}
Sebastian Hack's avatar
Sebastian Hack committed
240

241
ir_node *be_new_CopyKeep(ir_node *const bl, ir_node *const src, int const n, ir_node *const *const in_keep)
Sebastian Hack's avatar
Sebastian Hack committed
242
{
Matthias Braun's avatar
Matthias Braun committed
243
	ir_mode  *mode  = get_irn_mode(src);
244
	ir_graph *irg   = get_irn_irg(bl);
Matthias Braun's avatar
Matthias Braun committed
245
246
	int       arity = n+1;
	ir_node **in    = ALLOCAN(ir_node*, arity);
Sebastian Hack's avatar
Sebastian Hack committed
247
	in[0] = src;
Christoph Mallon's avatar
Christoph Mallon committed
248
	MEMCPY(&in[1], in_keep, n);
Matthias Braun's avatar
Matthias Braun committed
249
	ir_node *irn = new_ir_node(NULL, irg, bl, op_be_CopyKeep, mode, arity, in);
250
	init_node_attr(irn, 1, arch_irn_flag_schedule_first);
Matthias Braun's avatar
Matthias Braun committed
251
	be_node_attr_t *attr = (be_node_attr_t*)get_irn_generic_attr(irn);
252
	attr->exc.pin_state = op_pin_state_floats;
Matthias Braun's avatar
Matthias Braun committed
253
254
	const arch_register_req_t   *req  = arch_get_irn_register_req(src);
	const arch_register_class_t *cls  = req->cls;
Matthias Braun's avatar
Matthias Braun committed
255
256
	be_node_set_register_req_in(irn, 0, cls->class_req);
	arch_set_irn_register_req_out(irn, 0, cls->class_req);
257
258
259
260
	for (int i = 0; i < n; ++i) {
		ir_node *pred = in_keep[i];
		const arch_register_req_t *req = arch_get_irn_register_req(pred);
		req = req->cls != NULL ? req->cls->class_req : arch_no_register_req;
Matthias Braun's avatar
Matthias Braun committed
261
		be_node_set_register_req_in(irn, i+1, req);
262
	}
Sebastian Hack's avatar
Sebastian Hack committed
263
264
265
	return irn;
}

266
267
ir_node *be_get_CopyKeep_op(const ir_node *cpy)
{
268
	return get_irn_n(cpy, n_be_CopyKeep_op);
269
270
}

271
void be_set_MemPerm_in_entity(const ir_node *irn, unsigned n, ir_entity *ent)
Matthias Braun's avatar
Matthias Braun committed
272
{
273
	assert(n < be_get_MemPerm_entity_arity(irn));
Matthias Braun's avatar
Matthias Braun committed
274
275
	const be_memperm_attr_t *attr
		= (const be_memperm_attr_t*)get_irn_generic_attr_const(irn);
Matthias Braun's avatar
Matthias Braun committed
276
277
278
	attr->in_entities[n] = ent;
}

279
ir_entity* be_get_MemPerm_in_entity(const ir_node* irn, unsigned n)
Matthias Braun's avatar
Matthias Braun committed
280
{
281
	assert(n < be_get_MemPerm_entity_arity(irn));
Matthias Braun's avatar
Matthias Braun committed
282
283
	const be_memperm_attr_t *attr
		= (const be_memperm_attr_t*)get_irn_generic_attr_const(irn);
Matthias Braun's avatar
Matthias Braun committed
284
285
286
	return attr->in_entities[n];
}

287
void be_set_MemPerm_out_entity(const ir_node *irn, unsigned n, ir_entity *ent)
Matthias Braun's avatar
Matthias Braun committed
288
{
289
	assert(n < be_get_MemPerm_entity_arity(irn));
Matthias Braun's avatar
Matthias Braun committed
290
291
	const be_memperm_attr_t *attr
		= (const be_memperm_attr_t*)get_irn_generic_attr_const(irn);
Matthias Braun's avatar
Matthias Braun committed
292
293
294
	attr->out_entities[n] = ent;
}

295
ir_entity* be_get_MemPerm_out_entity(const ir_node* irn, unsigned n)
Matthias Braun's avatar
Matthias Braun committed
296
{
297
	assert(n < be_get_MemPerm_entity_arity(irn));
Matthias Braun's avatar
Matthias Braun committed
298
299
	const be_memperm_attr_t *attr
		= (const be_memperm_attr_t*)get_irn_generic_attr_const(irn);
Matthias Braun's avatar
Matthias Braun committed
300
301
302
	return attr->out_entities[n];
}

303
304
305
void be_set_MemPerm_offset(ir_node *irn, int offset)
{
	assert(be_is_MemPerm(irn));
Matthias Braun's avatar
Matthias Braun committed
306
	be_memperm_attr_t *attr = (be_memperm_attr_t*)get_irn_generic_attr(irn);
307
308
309
310
311
312
	attr->offset = offset;
}

int be_get_MemPerm_offset(const ir_node *irn)
{
	assert(be_is_MemPerm(irn));
Matthias Braun's avatar
Matthias Braun committed
313
314
	const be_memperm_attr_t *attr
		= (const be_memperm_attr_t*)get_irn_generic_attr_const(irn);
315
316
317
	return attr->offset;
}

318
unsigned be_get_MemPerm_entity_arity(const ir_node *irn)
319
{
Matthias Braun's avatar
Matthias Braun committed
320
	assert(be_is_MemPerm(irn));
321
	return get_irn_arity(irn);
322
323
}

Matthias Braun's avatar
Matthias Braun committed
324
325
326
327
328
ir_node *be_new_AnyVal(ir_node *block, const arch_register_class_t *cls)
{
	ir_graph *irg  = get_irn_irg(block);
	ir_mode  *mode = cls->mode;
	ir_node  *res  = new_ir_node(NULL, irg, block, op_be_AnyVal, mode, 0, NULL);
329
	init_node_attr(res, 1, arch_irn_flags_none);
Matthias Braun's avatar
Matthias Braun committed
330
331
332
333
334
335
	arch_set_irn_register_req_out(res, 0, cls->class_req);
	be_node_attr_t *attr = (be_node_attr_t*)get_irn_generic_attr(res);
	attr->exc.pin_state = op_pin_state_floats;
	return res;
}

336
const arch_register_req_t *be_create_reg_req(struct obstack *obst,
337
		const arch_register_t *reg, arch_register_req_type_t additional_types)
Sebastian Hack's avatar
Sebastian Hack committed
338
{
339
	arch_register_class_t const *cls     = reg->cls;
Matthias Braun's avatar
Matthias Braun committed
340
341
	unsigned                    *limited
		= rbitset_obstack_alloc(obst, cls->n_regs);
Matthias Braun's avatar
Matthias Braun committed
342
343
	rbitset_set(limited, reg->index);
	arch_register_req_t *req = OALLOC(obst, arch_register_req_t);
344
345
	req->type    = arch_register_req_type_limited | additional_types;
	req->cls     = cls;
Matthias Braun's avatar
Matthias Braun committed
346
	req->limited = limited;
347
	req->width   = 1;
348
	return req;
349
350
351
352
353
}

void be_set_constr_single_reg_out(ir_node *node, int pos,
		const arch_register_t *reg, arch_register_req_type_t additional_types)
{
Matthias Braun's avatar
Matthias Braun committed
354
355
	ir_graph *irg  = get_irn_irg(node);
	be_irg_t *birg = be_birg_from_irg(irg);
356
357

	/* if we have an ignore register, add ignore flag and just assign it */
Matthias Braun's avatar
Matthias Braun committed
358
	if (!rbitset_is_set(birg->allocatable_regs, reg->global_index))
359
360
		additional_types |= arch_register_req_type_ignore;

Matthias Braun's avatar
Matthias Braun committed
361
	const arch_register_req_t *req;
362
363
364
	if (additional_types == 0) {
		req = reg->single_req;
	} else {
365
		struct obstack *obst = be_get_be_obst(irg);
366
		req = be_create_reg_req(obst, reg, additional_types);
367
368
	}

369
	arch_set_irn_register_out(node, pos, reg);
Matthias Braun's avatar
Matthias Braun committed
370
	arch_set_irn_register_req_out(node, pos, req);
Sebastian Hack's avatar
Sebastian Hack committed
371
372
}

373
374
ir_node *be_get_IncSP_pred(ir_node *irn)
{
Michael Beck's avatar
BugFix:    
Michael Beck committed
375
376
377
378
	assert(be_is_IncSP(irn));
	return get_irn_n(irn, 0);
}

379
380
void be_set_IncSP_pred(ir_node *incsp, ir_node *pred)
{
381
382
383
384
	assert(be_is_IncSP(incsp));
	set_irn_n(incsp, 0, pred);
}

385
void be_set_IncSP_offset(ir_node *irn, int offset)
Sebastian Hack's avatar
Sebastian Hack committed
386
387
{
	assert(be_is_IncSP(irn));
Matthias Braun's avatar
Matthias Braun committed
388
	be_incsp_attr_t *a = (be_incsp_attr_t*)get_irn_generic_attr(irn);
Sebastian Hack's avatar
Sebastian Hack committed
389
390
	a->offset = offset;
}
391

392
int be_get_IncSP_offset(const ir_node *irn)
Sebastian Hack's avatar
Sebastian Hack committed
393
{
Sebastian Hack's avatar
Sebastian Hack committed
394
	assert(be_is_IncSP(irn));
Matthias Braun's avatar
Matthias Braun committed
395
396
	const be_incsp_attr_t *a
		= (const be_incsp_attr_t*)get_irn_generic_attr_const(irn);
Sebastian Hack's avatar
Sebastian Hack committed
397
398
	return a->offset;
}
Sebastian Hack's avatar
Sebastian Hack committed
399

400
unsigned be_get_IncSP_align(const ir_node *irn)
401
402
{
	assert(be_is_IncSP(irn));
Matthias Braun's avatar
Matthias Braun committed
403
404
	const be_incsp_attr_t *a
		= (const be_incsp_attr_t*)get_irn_generic_attr_const(irn);
405
406
407
	return a->align;
}

408
static unsigned get_start_reg_index(ir_graph *irg, const arch_register_t *reg)
409
410
{
	/* do a naive linear search... */
Matthias Braun's avatar
Matthias Braun committed
411
	ir_node *start  = get_irg_start(irg);
412
	be_foreach_out(start, i) {
Matthias Braun's avatar
Matthias Braun committed
413
414
		arch_register_req_t const *const out_req
			= arch_get_irn_register_req_out(start, i);
415
		if (!arch_register_req_is(out_req, limited))
416
			continue;
417
		if (out_req->cls != reg->cls)
418
419
420
421
422
			continue;
		if (!rbitset_is_set(out_req->limited, reg->index))
			continue;
		return i;
	}
423
	panic("tried querying undefined register '%s' at Start", reg->name);
424
425
426
427
}

ir_node *be_get_initial_reg_value(ir_graph *irg, const arch_register_t *reg)
{
428
429
430
431
	unsigned const i     = get_start_reg_index(irg, reg);
	ir_node *const start = get_irg_start(irg);
	ir_node *const proj  = get_Proj_for_pn(start, i);
	return proj ? proj : new_r_Proj(start, reg->cls->mode, i);
432
433
}

434
ir_node *be_new_Phi(ir_node *block, int n_ins, ir_node **ins, ir_mode *mode,
435
                    const arch_register_req_t *req)
436
{
Matthias Braun's avatar
Matthias Braun committed
437
438
	ir_graph *irg  = get_irn_irg(block);
	ir_node  *phi = new_ir_node(NULL, irg, block, op_Phi, mode, n_ins, ins);
439
	phi->attr.phi.u.backedge = new_backedge_arr(get_irg_obstack(irg), n_ins);
Matthias Braun's avatar
Matthias Braun committed
440
441
	struct obstack *obst = be_get_be_obst(irg);
	backend_info_t *info = be_get_info(phi);
442
443
	info->out_infos = NEW_ARR_DZ(reg_out_info_t, obst, 1);
	info->in_reqs   = OALLOCN(obst, const arch_register_req_t*, n_ins);
444
445

	info->out_infos[0].req = req;
Matthias Braun's avatar
Matthias Braun committed
446
	for (int i = 0; i < n_ins; ++i) {
447
		info->in_reqs[i] = req;
448
	}
Matthias Braun's avatar
Matthias Braun committed
449
	verify_new_node(irg, phi);
450
	phi = optimize_node(phi);
451
452
453
	return phi;
}

454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
ir_node *be_new_Phi0(ir_node *const block, ir_mode *const mode, arch_register_req_t const *const req)
{
	ir_graph *const irg = get_irn_irg(block);
	ir_node  *const phi = new_ir_node(NULL, irg, block, op_Phi, mode, 0, NULL);
	struct obstack *const obst = be_get_be_obst(irg);
	backend_info_t *const info = be_get_info(phi);
	info->out_infos = NEW_ARR_DZ(reg_out_info_t, obst, 1);
	info->out_infos[0].req = req;
	return phi;
}

ir_node *be_complete_Phi(ir_node *const phi, unsigned const n_ins, ir_node **const ins)
{
	assert(is_Phi(phi) && get_Phi_n_preds(phi) == 0);

	ir_graph *const irg = get_irn_irg(phi);
	phi->attr.phi.u.backedge = new_backedge_arr(get_irg_obstack(irg), n_ins);
	set_irn_in(phi, n_ins, ins);

	struct obstack             *const obst    = be_get_be_obst(irg);
	arch_register_req_t const **const in_reqs = OALLOCN(obst, arch_register_req_t const*, n_ins);
	arch_register_req_t const  *const req     = arch_get_irn_register_req(phi);
	for (unsigned i = 0; i < n_ins; ++i) {
		in_reqs[i] = req;
	}
	backend_info_t *const info = be_get_info(phi);
	info->in_reqs = in_reqs;

	verify_new_node(irg, phi);
	return optimize_node(phi);
}

486
void be_set_phi_reg_req(ir_node *node, const arch_register_req_t *req)
487
{
Matthias Braun's avatar
Matthias Braun committed
488
	assert(mode_is_data(get_irn_mode(node)));
489
490
	backend_info_t *info = be_get_info(node);
	info->out_infos[0].req = req;
Matthias Braun's avatar
Matthias Braun committed
491
	for (int i = 0, arity = get_irn_arity(node); i < arity; ++i) {
492
493
		info->in_reqs[i] = req;
	}
494
495
}

496
void be_dump_phi_reg_reqs(FILE *F, const ir_node *node, dump_reason_t reason)
497
{
498
	switch (reason) {
499
	case dump_node_opcode_txt:
500
		fputs(get_irn_opname(node), F);
501
502
503
504
505
506
		break;
	case dump_node_mode_txt:
		fprintf(F, "%s", get_mode_name(get_irn_mode(node)));
		break;
	case dump_node_nodeattr_txt:
		break;
Matthias Braun's avatar
Matthias Braun committed
507
	case dump_node_info_txt: {
508
509
		ir_graph *irg = get_irn_irg(node);
		if (irg_is_constrained(irg, IR_GRAPH_CONSTRAINT_BACKEND)) {
510
			be_dump_reqs_and_registers(F, node);
511
		}
512
		break;
513
	}
514
	}
515
516
}

517
518
519
/**
 * ir_op-Operation: dump a be node to file
 */
520
static void dump_node(FILE *f, const ir_node *irn, dump_reason_t reason)
521
{
522
523
	assert(is_be_node(irn));

524
	switch (reason) {
Matthias Braun's avatar
Matthias Braun committed
525
526
527
528
529
530
531
532
	case dump_node_opcode_txt:
		fputs(get_irn_opname(irn), f);
		break;
	case dump_node_mode_txt:
		if (be_is_Copy(irn) || be_is_CopyKeep(irn))
			fprintf(f, "%s", get_mode_name(get_irn_mode(irn)));
		break;
	case dump_node_nodeattr_txt:
533
		if (be_is_IncSP(irn)) {
Matthias Braun's avatar
Matthias Braun committed
534
535
			const be_incsp_attr_t *attr
				= (const be_incsp_attr_t*)get_irn_generic_attr_const(irn);
Matthias Braun's avatar
Matthias Braun committed
536
537
538
539
			fprintf(f, " [%d] ", attr->offset);
		}
		break;
	case dump_node_info_txt:
540
		be_dump_reqs_and_registers(f, irn);
Matthias Braun's avatar
Matthias Braun committed
541

542
		if (be_is_IncSP(irn)) {
Matthias Braun's avatar
Matthias Braun committed
543
544
			const be_incsp_attr_t *a
				= (const be_incsp_attr_t*)get_irn_generic_attr_const(irn);
545
			fprintf(f, "align: %u\n", a->align);
Matthias Braun's avatar
Matthias Braun committed
546
			fprintf(f, "offset: %d\n", a->offset);
547
		} else if (be_is_MemPerm(irn)) {
548
			for (unsigned i = 0; i < be_get_MemPerm_entity_arity(irn); ++i) {
Matthias Braun's avatar
Matthias Braun committed
549
550
551
				ir_entity *in  = be_get_MemPerm_in_entity(irn, i);
				ir_entity *out = be_get_MemPerm_out_entity(irn, i);
				if (in != NULL)
552
					fprintf(f, "\nin[%u]: %s\n", i, get_entity_name(in));
Matthias Braun's avatar
Matthias Braun committed
553
				if (out != NULL)
554
					fprintf(f, "\nout[%u]: %s\n", i, get_entity_name(out));
555
			}
Matthias Braun's avatar
Matthias Braun committed
556
		}
557
		break;
558
559
560
	}
}

Sebastian Hack's avatar
Sebastian Hack committed
561
/**
562
 * ir_op-Operation:
Sebastian Hack's avatar
Sebastian Hack committed
563
564
 * Copies the backend specific attributes from old node to new node.
 */
565
static void copy_attr(ir_graph *irg, const ir_node *old_node, ir_node *new_node)
Sebastian Hack's avatar
Sebastian Hack committed
566
{
Matthias Braun's avatar
Matthias Braun committed
567
568
569
	assert(is_be_node(old_node));
	assert(is_be_node(new_node));

570
571
	const void     *old_attr = get_irn_generic_attr_const(old_node);
	void           *new_attr = get_irn_generic_attr(new_node);
572
	struct obstack *obst     = be_get_be_obst(irg);
573
574
	backend_info_t *old_info = be_get_info(old_node);
	backend_info_t *new_info = be_get_info(new_node);
Sebastian Hack's avatar
Sebastian Hack committed
575
	memcpy(new_attr, old_attr, get_op_attr_size(get_irn_op(old_node)));
576
	new_info->flags     = old_info->flags;
Matthias Braun's avatar
Matthias Braun committed
577
578
579
	new_info->out_infos = old_info->out_infos
	                    ? DUP_ARR_D(reg_out_info_t, obst, old_info->out_infos)
	                    : NULL;
580

581
	/* input infos */
582
583
	if (old_info->in_reqs != NULL) {
		unsigned n_ins = get_irn_arity(old_node);
584
		/* need dynamic in infos? */
585
		if (is_irn_dynamic(old_node)) {
586
			new_info->in_reqs = NEW_ARR_F(const arch_register_req_t*, n_ins);
587
		} else {
588
			new_info->in_reqs = OALLOCN(obst,const arch_register_req_t*, n_ins);
Sebastian Hack's avatar
Sebastian Hack committed
589
		}
Christoph Mallon's avatar
Christoph Mallon committed
590
		MEMCPY(new_info->in_reqs, old_info->in_reqs, n_ins);
591
	} else {
592
		new_info->in_reqs = NULL;
Sebastian Hack's avatar
Sebastian Hack committed
593
	}
Sebastian Hack's avatar
Sebastian Hack committed
594
595
}

596
597
598
599
600
bool is_be_node(const ir_node *irn)
{
	return get_op_tag(get_irn_op(irn)) == be_op_tag;
}

601
arch_irn_ops_t const be_null_ops = {
Matthias Braun's avatar
Matthias Braun committed
602
603
604
605
	.get_op_estimated_cost  = NULL,
	.perform_memory_operand = NULL,
};

606
607
608
609
static ir_op *new_be_op(unsigned code, const char *name, op_pin_state p,
                        irop_flags flags, op_arity opar, size_t attr_size)
{
	ir_op *res = new_ir_op(code, name, p, flags, opar, 0, attr_size);
Matthias Braun's avatar
Matthias Braun committed
610
611
	set_op_dump(res, dump_node);
	set_op_copy_attr(res, copy_attr);
612
	res->ops.be_ops = &be_null_ops;
613
	set_op_tag(res, be_op_tag);
614
615
616
	return res;
}

617
618
void be_init_op(void)
{
619
	assert(op_be_Perm == NULL);
Matthias Braun's avatar
Matthias Braun committed
620

Matthias Braun's avatar
Matthias Braun committed
621
	/* Acquire all needed opcodes. */
622
	unsigned const o = get_next_ir_opcodes(beo_last + 1);
Matthias Braun's avatar
Matthias Braun committed
623
624
625
626
	op_be_AnyVal   = new_be_op(o+beo_AnyVal,   "be_AnyVal",   op_pin_state_exc_pinned, irop_flag_constlike|irop_flag_cse_neutral, oparity_any,      sizeof(be_node_attr_t));
	op_be_Copy     = new_be_op(o+beo_Copy,     "be_Copy",     op_pin_state_exc_pinned, irop_flag_none,                            oparity_any,      sizeof(be_node_attr_t));
	op_be_CopyKeep = new_be_op(o+beo_CopyKeep, "be_CopyKeep", op_pin_state_exc_pinned, irop_flag_keep,                            oparity_variable, sizeof(be_node_attr_t));
	op_be_IncSP    = new_be_op(o+beo_IncSP,    "be_IncSP",    op_pin_state_exc_pinned, irop_flag_none,                            oparity_any,      sizeof(be_incsp_attr_t));
627
	op_be_Keep     = new_be_op(o+beo_Keep,     "be_Keep",     op_pin_state_exc_pinned, irop_flag_keep,                            oparity_variable, sizeof(be_node_attr_t));
Matthias Braun's avatar
Matthias Braun committed
628
629
630
631
	op_be_MemPerm  = new_be_op(o+beo_MemPerm,  "be_MemPerm",  op_pin_state_exc_pinned, irop_flag_none,                            oparity_variable, sizeof(be_memperm_attr_t));
	op_be_Perm     = new_be_op(o+beo_Perm,     "be_Perm",     op_pin_state_exc_pinned, irop_flag_none,                            oparity_variable, sizeof(be_node_attr_t));

	set_op_attrs_equal(op_be_AnyVal,   attrs_equal_be_node);
632
633
634
	set_op_attrs_equal(op_be_Copy,     attrs_equal_be_node);
	set_op_attrs_equal(op_be_CopyKeep, attrs_equal_be_node);
	set_op_attrs_equal(op_be_IncSP,    be_incsp_attrs_equal);
Matthias Braun's avatar
Matthias Braun committed
635
636
637
	set_op_attrs_equal(op_be_Keep,     attrs_equal_be_node);
	set_op_attrs_equal(op_be_MemPerm,  attrs_equal_be_node);
	set_op_attrs_equal(op_be_Perm,     attrs_equal_be_node);
638
639

	/* attach out dummy_ops to middle end nodes */
640
	for (unsigned opc = iro_first; opc <= iro_last; ++opc) {
Matthias Braun's avatar
Matthias Braun committed
641
		ir_op *op = ir_get_opcode(opc);
642
		assert(op->ops.be_ops == NULL);
643
		op->ops.be_ops = &be_null_ops;
644
	}
Matthias Braun's avatar
Matthias Braun committed
645
}
Matthias Braun's avatar
Matthias Braun committed
646
647
648

void be_finish_op(void)
{
Matthias Braun's avatar
Matthias Braun committed
649
	free_ir_op(op_be_AnyVal);   op_be_AnyVal   = NULL;
Matthias Braun's avatar
Matthias Braun committed
650
651
652
	free_ir_op(op_be_Copy);     op_be_Copy     = NULL;
	free_ir_op(op_be_CopyKeep); op_be_CopyKeep = NULL;
	free_ir_op(op_be_IncSP);    op_be_IncSP    = NULL;
Matthias Braun's avatar
Matthias Braun committed
653
654
655
	free_ir_op(op_be_Keep);     op_be_Keep     = NULL;
	free_ir_op(op_be_MemPerm);  op_be_MemPerm  = NULL;
	free_ir_op(op_be_Perm);     op_be_Perm     = NULL;
Matthias Braun's avatar
Matthias Braun committed
656
}