benode.c 21 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

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

51
typedef struct {
52
53
54
	be_node_attr_t base;
	ir_entity    **in_entities;
	ir_entity    **out_entities;
55
	int            offset;
Matthias Braun's avatar
Matthias Braun committed
56
} be_memperm_attr_t;
57

Matthias Braun's avatar
Matthias Braun committed
58
ir_op *op_be_AnyVal;
59
ir_op *op_be_Asm;
60
ir_op *op_be_Copy;
Sebastian Hack's avatar
Sebastian Hack committed
61
ir_op *op_be_CopyKeep;
62
ir_op *op_be_IncSP;
Matthias Braun's avatar
Matthias Braun committed
63
64
65
ir_op *op_be_Keep;
ir_op *op_be_MemPerm;
ir_op *op_be_Perm;
Sebastian Hack's avatar
Sebastian Hack committed
66

67
68
#define be_op_tag FOURCC('B', 'E', '\0', '\0')

69
70
71
72
73
74
75
static int be_asm_attr_equal(ir_node const *const a, ir_node const *const b)
{
	be_asm_attr_t const *const attr_a = get_be_asm_attr_const(a);
	be_asm_attr_t const *const attr_b = get_be_asm_attr_const(b);
	return attr_a->text == attr_b->text && attr_a->operands == attr_b->operands;
}

Michael Beck's avatar
Michael Beck committed
76
77
78
/**
 * Compare the attributes of two be_IncSP nodes.
 */
79
static int be_incsp_attrs_equal(const ir_node *a, const ir_node *b)
80
{
Matthias Braun's avatar
Matthias Braun committed
81
82
83
84
	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);
85
	return attr_a->offset == attr_b->offset && attrs_equal_be_node(a, b);
86
87
}

88
static arch_register_req_t *allocate_reg_req(ir_graph *const irg)
Matthias Braun's avatar
Matthias Braun committed
89
{
90
	struct obstack *obst = be_get_be_obst(irg);
91
	arch_register_req_t *req = OALLOCZ(obst, arch_register_req_t);
92
93
	return req;
}
Matthias Braun's avatar
Matthias Braun committed
94

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

103
/**
104
 * Initializes the generic attribute of all be nodes and return it.
105
 */
106
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
107
{
108
	ir_graph       *irg  = get_irn_irg(node);
109
	struct obstack *obst = be_get_be_obst(irg);
110
	backend_info_t *info = be_get_info(node);
Sebastian Hack's avatar
Sebastian Hack committed
111

112
	unsigned                    const arity   = get_irn_arity(node);
113
114
115
116
117
118
	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;
119
	}
120
	info->in_reqs = in_reqs;
121

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

Matthias Braun's avatar
Matthias Braun committed
129
130
131
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
132
{
133
	ir_graph *irg = get_irn_irg(block);
Matthias Braun's avatar
Matthias Braun committed
134
	ir_node  *irn = new_ir_node(NULL, irg, block, op_be_Perm, mode_T, n, in);
135
	init_node_attr(irn, n, arch_irn_flags_none);
Matthias Braun's avatar
Matthias Braun committed
136
	be_node_attr_t *attr = (be_node_attr_t*)get_irn_generic_attr(irn);
137
	attr->exc.pin_state = op_pin_state_pinned;
Matthias Braun's avatar
Matthias Braun committed
138
	for (int i = 0; i < n; ++i) {
139
140
141
		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
142
143
			be_node_set_register_req_in(irn, i, cls->class_req);
			arch_set_irn_register_req_out(irn, i, cls->class_req);
144
		} else {
145
			arch_register_req_t *const new_req = allocate_reg_req(irg);
146
147
148
			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
149
150
			be_node_set_register_req_in(irn, i, new_req);
			arch_set_irn_register_req_out(irn, i, new_req);
151
		}
Sebastian Hack's avatar
Sebastian Hack committed
152
153
	}

Sebastian Hack's avatar
Sebastian Hack committed
154
155
	return irn;
}
156

157
ir_node *be_new_MemPerm(ir_node *const block, int n, ir_node *const *const in)
Matthias Braun's avatar
Matthias Braun committed
158
{
159
160
	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
161

162
	init_node_attr(irn, n, arch_irn_flags_none);
Matthias Braun's avatar
Matthias Braun committed
163

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

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

	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
183
184
	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
185

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

196
197
ir_node *be_get_Copy_op(const ir_node *cpy)
{
198
	return get_irn_n(cpy, n_be_Copy_op);
199
200
}

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

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

219
220
221
222
223
224
225
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);
}

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

	/* Set output constraint to stack register. */
Matthias Braun's avatar
Matthias Braun committed
240
	be_node_set_register_req_in(irn, 0, sp->cls->class_req);
241
242
	arch_copy_irn_out_info(irn, 0, old_sp);
	assert(arch_register_req_is(arch_get_irn_register_req(irn), produces_sp));
Sebastian Hack's avatar
Sebastian Hack committed
243
	return irn;
Sebastian Hack's avatar
Sebastian Hack committed
244
}
Sebastian Hack's avatar
Sebastian Hack committed
245

246
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
247
{
Matthias Braun's avatar
Matthias Braun committed
248
	ir_mode  *mode  = get_irn_mode(src);
249
	ir_graph *irg   = get_irn_irg(bl);
Matthias Braun's avatar
Matthias Braun committed
250
251
	int       arity = n+1;
	ir_node **in    = ALLOCAN(ir_node*, arity);
Sebastian Hack's avatar
Sebastian Hack committed
252
	in[0] = src;
Christoph Mallon's avatar
Christoph Mallon committed
253
	MEMCPY(&in[1], in_keep, n);
Matthias Braun's avatar
Matthias Braun committed
254
	ir_node *irn = new_ir_node(NULL, irg, bl, op_be_CopyKeep, mode, arity, in);
255
	init_node_attr(irn, 1, arch_irn_flag_schedule_first);
Matthias Braun's avatar
Matthias Braun committed
256
	be_node_attr_t *attr = (be_node_attr_t*)get_irn_generic_attr(irn);
257
	attr->exc.pin_state = op_pin_state_floats;
Matthias Braun's avatar
Matthias Braun committed
258
259
	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
260
261
	be_node_set_register_req_in(irn, 0, cls->class_req);
	arch_set_irn_register_req_out(irn, 0, cls->class_req);
262
263
264
265
	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
266
		be_node_set_register_req_in(irn, i+1, req);
267
	}
Sebastian Hack's avatar
Sebastian Hack committed
268
269
270
	return irn;
}

271
272
ir_node *be_get_CopyKeep_op(const ir_node *cpy)
{
273
	return get_irn_n(cpy, n_be_CopyKeep_op);
274
275
}

276
void be_set_MemPerm_in_entity(const ir_node *irn, unsigned n, ir_entity *ent)
Matthias Braun's avatar
Matthias Braun committed
277
{
278
	assert(n < be_get_MemPerm_entity_arity(irn));
Matthias Braun's avatar
Matthias Braun committed
279
280
	const be_memperm_attr_t *attr
		= (const be_memperm_attr_t*)get_irn_generic_attr_const(irn);
Matthias Braun's avatar
Matthias Braun committed
281
282
283
	attr->in_entities[n] = ent;
}

284
ir_entity* be_get_MemPerm_in_entity(const ir_node* irn, unsigned n)
Matthias Braun's avatar
Matthias Braun committed
285
{
286
	assert(n < be_get_MemPerm_entity_arity(irn));
Matthias Braun's avatar
Matthias Braun committed
287
288
	const be_memperm_attr_t *attr
		= (const be_memperm_attr_t*)get_irn_generic_attr_const(irn);
Matthias Braun's avatar
Matthias Braun committed
289
290
291
	return attr->in_entities[n];
}

292
void be_set_MemPerm_out_entity(const ir_node *irn, unsigned n, ir_entity *ent)
Matthias Braun's avatar
Matthias Braun committed
293
{
294
	assert(n < be_get_MemPerm_entity_arity(irn));
Matthias Braun's avatar
Matthias Braun committed
295
296
	const be_memperm_attr_t *attr
		= (const be_memperm_attr_t*)get_irn_generic_attr_const(irn);
Matthias Braun's avatar
Matthias Braun committed
297
298
299
	attr->out_entities[n] = ent;
}

300
ir_entity* be_get_MemPerm_out_entity(const ir_node* irn, unsigned n)
Matthias Braun's avatar
Matthias Braun committed
301
{
302
	assert(n < be_get_MemPerm_entity_arity(irn));
Matthias Braun's avatar
Matthias Braun committed
303
304
	const be_memperm_attr_t *attr
		= (const be_memperm_attr_t*)get_irn_generic_attr_const(irn);
Matthias Braun's avatar
Matthias Braun committed
305
306
307
	return attr->out_entities[n];
}

308
309
310
void be_set_MemPerm_offset(ir_node *irn, int offset)
{
	assert(be_is_MemPerm(irn));
Matthias Braun's avatar
Matthias Braun committed
311
	be_memperm_attr_t *attr = (be_memperm_attr_t*)get_irn_generic_attr(irn);
312
313
314
315
316
317
	attr->offset = offset;
}

int be_get_MemPerm_offset(const ir_node *irn)
{
	assert(be_is_MemPerm(irn));
Matthias Braun's avatar
Matthias Braun committed
318
319
	const be_memperm_attr_t *attr
		= (const be_memperm_attr_t*)get_irn_generic_attr_const(irn);
320
321
322
	return attr->offset;
}

323
unsigned be_get_MemPerm_entity_arity(const ir_node *irn)
324
{
Matthias Braun's avatar
Matthias Braun committed
325
	assert(be_is_MemPerm(irn));
326
	return get_irn_arity(irn);
327
328
}

Matthias Braun's avatar
Matthias Braun committed
329
330
331
332
333
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);
334
	init_node_attr(res, 1, arch_irn_flags_none);
Matthias Braun's avatar
Matthias Braun committed
335
336
337
338
339
340
	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;
}

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

356
357
ir_node *be_get_IncSP_pred(ir_node *irn)
{
Michael Beck's avatar
BugFix:    
Michael Beck committed
358
359
360
361
	assert(be_is_IncSP(irn));
	return get_irn_n(irn, 0);
}

362
363
void be_set_IncSP_pred(ir_node *incsp, ir_node *pred)
{
364
365
366
367
	assert(be_is_IncSP(incsp));
	set_irn_n(incsp, 0, pred);
}

368
void be_set_IncSP_offset(ir_node *irn, int offset)
Sebastian Hack's avatar
Sebastian Hack committed
369
370
{
	assert(be_is_IncSP(irn));
Matthias Braun's avatar
Matthias Braun committed
371
	be_incsp_attr_t *a = (be_incsp_attr_t*)get_irn_generic_attr(irn);
Sebastian Hack's avatar
Sebastian Hack committed
372
373
	a->offset = offset;
}
374

375
int be_get_IncSP_offset(const ir_node *irn)
Sebastian Hack's avatar
Sebastian Hack committed
376
{
Sebastian Hack's avatar
Sebastian Hack committed
377
	assert(be_is_IncSP(irn));
Matthias Braun's avatar
Matthias Braun committed
378
379
	const be_incsp_attr_t *a
		= (const be_incsp_attr_t*)get_irn_generic_attr_const(irn);
Sebastian Hack's avatar
Sebastian Hack committed
380
381
	return a->offset;
}
Sebastian Hack's avatar
Sebastian Hack committed
382

383
unsigned be_get_IncSP_align(const ir_node *irn)
384
385
{
	assert(be_is_IncSP(irn));
Matthias Braun's avatar
Matthias Braun committed
386
387
	const be_incsp_attr_t *a
		= (const be_incsp_attr_t*)get_irn_generic_attr_const(irn);
388
389
390
	return a->align;
}

391
static unsigned get_start_reg_index(ir_graph *irg, const arch_register_t *reg)
392
393
{
	/* do a naive linear search... */
Matthias Braun's avatar
Matthias Braun committed
394
	ir_node *start  = get_irg_start(irg);
395
	be_foreach_out(start, i) {
Matthias Braun's avatar
Matthias Braun committed
396
397
		arch_register_req_t const *const out_req
			= arch_get_irn_register_req_out(start, i);
398
		if (!arch_register_req_is(out_req, limited))
399
			continue;
400
		if (out_req->cls != reg->cls)
401
402
403
404
405
			continue;
		if (!rbitset_is_set(out_req->limited, reg->index))
			continue;
		return i;
	}
406
	panic("tried querying undefined register '%s' at Start", reg->name);
407
408
409
410
}

ir_node *be_get_initial_reg_value(ir_graph *irg, const arch_register_t *reg)
{
411
412
413
414
	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);
415
416
}

417
ir_node *be_new_Phi(ir_node *block, int n_ins, ir_node **ins, ir_mode *mode,
418
                    const arch_register_req_t *req)
419
{
Matthias Braun's avatar
Matthias Braun committed
420
421
	ir_graph *irg  = get_irn_irg(block);
	ir_node  *phi = new_ir_node(NULL, irg, block, op_Phi, mode, n_ins, ins);
422
	phi->attr.phi.u.backedge = new_backedge_arr(get_irg_obstack(irg), n_ins);
Matthias Braun's avatar
Matthias Braun committed
423
424
	struct obstack *obst = be_get_be_obst(irg);
	backend_info_t *info = be_get_info(phi);
425
426
	info->out_infos = NEW_ARR_DZ(reg_out_info_t, obst, 1);
	info->in_reqs   = OALLOCN(obst, const arch_register_req_t*, n_ins);
427
428

	info->out_infos[0].req = req;
Matthias Braun's avatar
Matthias Braun committed
429
	for (int i = 0; i < n_ins; ++i) {
430
		info->in_reqs[i] = req;
431
	}
Matthias Braun's avatar
Matthias Braun committed
432
	verify_new_node(irg, phi);
433
	phi = optimize_node(phi);
434
435
436
	return phi;
}

437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
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);
}

469
void be_set_phi_reg_req(ir_node *node, const arch_register_req_t *req)
470
{
Matthias Braun's avatar
Matthias Braun committed
471
	assert(mode_is_data(get_irn_mode(node)));
472
473
	backend_info_t *info = be_get_info(node);
	info->out_infos[0].req = req;
Matthias Braun's avatar
Matthias Braun committed
474
	for (int i = 0, arity = get_irn_arity(node); i < arity; ++i) {
475
476
		info->in_reqs[i] = req;
	}
477
478
}

479
void be_dump_phi_reg_reqs(FILE *F, const ir_node *node, dump_reason_t reason)
480
{
481
	switch (reason) {
482
	case dump_node_opcode_txt:
483
		fputs(get_irn_opname(node), F);
484
485
486
487
488
489
		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
490
	case dump_node_info_txt: {
491
492
		ir_graph *irg = get_irn_irg(node);
		if (irg_is_constrained(irg, IR_GRAPH_CONSTRAINT_BACKEND)) {
493
			be_dump_reqs_and_registers(F, node);
494
		}
495
		break;
496
	}
497
	}
498
499
}

500
501
502
503
504
505
506
507
508
509
510
511
512
ir_node *be_new_Asm(dbg_info *const dbgi, ir_node *const block, int const n_ins, ir_node **const ins, int const n_outs, ident *const text, void *const operands)
{
	ir_graph *const irg  = get_irn_irg(block);
	ir_node  *const asmn = new_ir_node(dbgi, irg, block, op_be_Asm, mode_T, n_ins, ins);
	be_info_init_irn(asmn, arch_irn_flags_none, NULL, n_outs);

	be_asm_attr_t *const attr = (be_asm_attr_t*)get_irn_generic_attr(asmn);
	attr->text     = text;
	attr->operands = operands;

	return asmn;
}

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

520
	switch (reason) {
Matthias Braun's avatar
Matthias Braun committed
521
522
523
524
525
526
527
528
	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:
529
		if (be_is_IncSP(irn)) {
Matthias Braun's avatar
Matthias Braun committed
530
531
			const be_incsp_attr_t *attr
				= (const be_incsp_attr_t*)get_irn_generic_attr_const(irn);
Matthias Braun's avatar
Matthias Braun committed
532
533
534
535
			fprintf(f, " [%d] ", attr->offset);
		}
		break;
	case dump_node_info_txt:
536
		be_dump_reqs_and_registers(f, irn);
Matthias Braun's avatar
Matthias Braun committed
537

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

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

566
567
	const void     *old_attr = get_irn_generic_attr_const(old_node);
	void           *new_attr = get_irn_generic_attr(new_node);
568
	struct obstack *obst     = be_get_be_obst(irg);
569
570
	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
571
	memcpy(new_attr, old_attr, get_op_attr_size(get_irn_op(old_node)));
572
	new_info->flags     = old_info->flags;
Matthias Braun's avatar
Matthias Braun committed
573
574
575
	new_info->out_infos = old_info->out_infos
	                    ? DUP_ARR_D(reg_out_info_t, obst, old_info->out_infos)
	                    : NULL;
576

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

592
593
594
595
596
bool is_be_node(const ir_node *irn)
{
	return get_op_tag(get_irn_op(irn)) == be_op_tag;
}

597
arch_irn_ops_t const be_null_ops = {
Matthias Braun's avatar
Matthias Braun committed
598
599
600
	.get_op_estimated_cost  = NULL,
};

601
602
603
604
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
605
606
	set_op_dump(res, dump_node);
	set_op_copy_attr(res, copy_attr);
607
	res->ops.be_ops = &be_null_ops;
608
	set_op_tag(res, be_op_tag);
609
610
611
	return res;
}

612
613
void be_init_op(void)
{
614
	assert(op_be_Perm == NULL);
Matthias Braun's avatar
Matthias Braun committed
615

Matthias Braun's avatar
Matthias Braun committed
616
	/* Acquire all needed opcodes. */
617
	unsigned const o = get_next_ir_opcodes(beo_last + 1);
Matthias Braun's avatar
Matthias Braun committed
618
	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));
619
	op_be_Asm      = new_be_op(o+beo_Asm,      "be_Asm",      op_pin_state_exc_pinned, irop_flag_none,                            oparity_any,      sizeof(be_asm_attr_t));
Matthias Braun's avatar
Matthias Braun committed
620
621
622
	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));
623
	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
624
625
626
	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));

627
	set_op_attrs_equal(op_be_Asm,      be_asm_attr_equal);
Matthias Braun's avatar
Matthias Braun committed
628
	set_op_attrs_equal(op_be_AnyVal,   attrs_equal_be_node);
629
630
631
	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
632
633
634
	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);
635
636

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

void be_finish_op(void)
{
Matthias Braun's avatar
Matthias Braun committed
646
	free_ir_op(op_be_AnyVal);   op_be_AnyVal   = NULL;
Matthias Braun's avatar
Matthias Braun committed
647
648
649
	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
650
651
652
	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
653
}