benode.c 21.8 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
#include "belive.h"
#include "benode.h"
#include "bitfiddle.h"
23
#include "fourcc.h"
Matthias Braun's avatar
Matthias Braun committed
24
#include "irbackedge_t.h"
25
#include "ircons_t.h"
Matthias Braun's avatar
Matthias Braun committed
26
#include "irgopt.h"
Sebastian Hack's avatar
Sebastian Hack committed
27
#include "irgwalk.h"
Matthias Braun's avatar
Matthias Braun committed
28
29
30
#include "irmode_t.h"
#include "irnode_t.h"
#include "irop_t.h"
Michael Beck's avatar
Michael Beck committed
31
#include "iropt_t.h"
Matthias Braun's avatar
Matthias Braun committed
32
#include "irprintf.h"
33
#include "irverify_t.h"
Matthias Braun's avatar
Matthias Braun committed
34
35
36
37
38
39
#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
40

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

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

56
57
58
59
60
typedef struct be_relocation_attr_t {
	ir_entity *entity;
	unsigned   kind;
} be_relocation_attr_t;

61
ir_op *op_be_Asm;
62
ir_op *op_be_Copy;
Sebastian Hack's avatar
Sebastian Hack committed
63
ir_op *op_be_CopyKeep;
64
ir_op *op_be_IncSP;
Matthias Braun's avatar
Matthias Braun committed
65
66
67
ir_op *op_be_Keep;
ir_op *op_be_MemPerm;
ir_op *op_be_Perm;
68
ir_op *op_be_Relocation;
Christoph Mallon's avatar
Christoph Mallon committed
69
ir_op *op_be_Start;
Sebastian Hack's avatar
Sebastian Hack committed
70

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

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

92
93
94
95
96
97
98
99
100
static int be_relocation_attrs_equal(ir_node const *a, ir_node const *b)
{
	be_relocation_attr_t const *attr_a
		= (be_relocation_attr_t const*)get_irn_generic_attr_const(a);
	be_relocation_attr_t const *attr_b
		= (be_relocation_attr_t const*)get_irn_generic_attr_const(b);
	return attr_a->entity == attr_b->entity && attr_a->kind == attr_b->kind;
}

101
102
103
104
105
106
arch_register_req_t const **be_allocate_in_reqs(ir_graph *const irg, unsigned const n)
{
	struct obstack *const obst = be_get_be_obst(irg);
	return OALLOCN(obst, arch_register_req_t const*, n);
}

107
static arch_register_req_t *allocate_reg_req(ir_graph *const irg)
Matthias Braun's avatar
Matthias Braun committed
108
{
109
	struct obstack *obst = be_get_be_obst(irg);
110
	arch_register_req_t *req = OALLOCZ(obst, arch_register_req_t);
111
112
	return req;
}
Matthias Braun's avatar
Matthias Braun committed
113

Matthias Braun's avatar
Matthias Braun committed
114
115
static void be_node_set_register_req_in(ir_node *const node, int const pos,
                                        arch_register_req_t const *const req)
116
{
117
118
119
	backend_info_t *info = be_get_info(node);
	assert(pos < get_irn_arity(node));
	info->in_reqs[pos] = req;
120
}
Matthias Braun's avatar
Matthias Braun committed
121

122
/**
123
 * Initializes the generic attribute of all be nodes and return it.
124
 */
125
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
126
{
127
128
	ir_graph       *irg  = get_irn_irg(node);
	backend_info_t *info = be_get_info(node);
Sebastian Hack's avatar
Sebastian Hack committed
129

130
	unsigned                    const arity   = get_irn_arity(node);
131
132
	arch_register_req_t const **const in_reqs =
		is_irn_dynamic(node) ? NEW_ARR_F(arch_register_req_t const*, arity) :
133
		arity != 0           ? be_allocate_in_reqs(irg, arity) :
134
135
136
		NULL;
	for (unsigned i = 0; i < arity; ++i) {
		in_reqs[i] = arch_no_register_req;
137
	}
138
	info->in_reqs = in_reqs;
139

140
	struct obstack *const obst = be_get_be_obst(irg);
141
	info->out_infos = NEW_ARR_DZ(reg_out_info_t, obst, n_outputs);
Matthias Braun's avatar
Matthias Braun committed
142
	for (unsigned i = 0; i < n_outputs; ++i) {
143
		info->out_infos[i].req = arch_no_register_req;
Sebastian Hack's avatar
Sebastian Hack committed
144
	}
Matthias Braun's avatar
Matthias Braun committed
145
	info->flags = flags;
Sebastian Hack's avatar
Sebastian Hack committed
146
}
147

Matthias Braun's avatar
Matthias Braun committed
148
149
150
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
151
{
152
	ir_graph *irg = get_irn_irg(block);
Matthias Braun's avatar
Matthias Braun committed
153
	ir_node  *irn = new_ir_node(NULL, irg, block, op_be_Perm, mode_T, n, in);
154
	init_node_attr(irn, n, arch_irn_flags_none);
Matthias Braun's avatar
Matthias Braun committed
155
	be_node_attr_t *attr = (be_node_attr_t*)get_irn_generic_attr(irn);
156
	attr->exc.pinned = true;
Matthias Braun's avatar
Matthias Braun committed
157
	for (int i = 0; i < n; ++i) {
158
159
160
		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
161
162
			be_node_set_register_req_in(irn, i, cls->class_req);
			arch_set_irn_register_req_out(irn, i, cls->class_req);
163
		} else {
164
			arch_register_req_t *const new_req = allocate_reg_req(irg);
165
166
167
			new_req->cls     = cls;
			new_req->width   = req->width;
			new_req->aligned = req->aligned;
Matthias Braun's avatar
Matthias Braun committed
168
169
			be_node_set_register_req_in(irn, i, new_req);
			arch_set_irn_register_req_out(irn, i, new_req);
170
		}
Sebastian Hack's avatar
Sebastian Hack committed
171
172
	}

Sebastian Hack's avatar
Sebastian Hack committed
173
174
	return irn;
}
175

176
ir_node *be_new_MemPerm(ir_node *const block, int n, ir_node *const *const in)
Matthias Braun's avatar
Matthias Braun committed
177
{
178
179
	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
180

181
	init_node_attr(irn, n, arch_irn_flags_none);
182
183
184
185
	for (int i = 0; i < n; ++i) {
		be_node_set_register_req_in(  irn, i, arch_memory_req);
		arch_set_irn_register_req_out(irn, i, arch_memory_req);
	}
Matthias Braun's avatar
Matthias Braun committed
186

Matthias Braun's avatar
Matthias Braun committed
187
	be_memperm_attr_t *attr = (be_memperm_attr_t*)get_irn_generic_attr(irn);
188
189
	attr->in_entities  = OALLOCNZ(get_irg_obstack(irg), ir_entity*, n);
	attr->out_entities = OALLOCNZ(get_irg_obstack(irg), ir_entity*, n);
190
	attr->offset       = 0;
Matthias Braun's avatar
Matthias Braun committed
191
192
193
	return irn;
}

194
195
196
197
static void set_copy_info(ir_node *const irn, ir_graph *const irg, ir_node *const op, arch_irn_flags_t const flags)
{
	init_node_attr(irn, 1, flags);
	be_node_attr_t *const attr = (be_node_attr_t*)get_irn_generic_attr(irn);
198
	attr->exc.pinned = false;
199
200
201
202
203
204
205
206
207
208
209
210
211
212

	arch_register_req_t   const *const op_req = arch_get_irn_register_req(op);
	arch_register_class_t const *const cls    = op_req->cls;

	be_node_set_register_req_in(irn, 0, cls->class_req);

	arch_register_req_t *const out_req = allocate_reg_req(irg);
	out_req->cls            = cls;
	out_req->should_be_same = 1U << 0;
	out_req->aligned        = op_req->aligned;
	out_req->width          = op_req->width;
	arch_set_irn_register_req_out(irn, 0, out_req);
}

213
ir_node *be_new_Copy(ir_node *bl, ir_node *op)
Sebastian Hack's avatar
Sebastian Hack committed
214
{
215
	ir_graph *irg  = get_irn_irg(bl);
Matthias Braun's avatar
Matthias Braun committed
216
217
218
	ir_node  *in[] = { op };
	ir_node  *res  = new_ir_node(NULL, irg, bl, op_be_Copy, get_irn_mode(op),
	                             ARRAY_SIZE(in), in);
219
	set_copy_info(res, irg, op, arch_irn_flags_none);
Sebastian Hack's avatar
Sebastian Hack committed
220
	return res;
221
222
}

223
224
ir_node *be_get_Copy_op(const ir_node *cpy)
{
225
	return get_irn_n(cpy, n_be_Copy_op);
226
227
}

Matthias Braun's avatar
Matthias Braun committed
228
229
ir_node *be_new_Keep(ir_node *const block, int const n,
                     ir_node *const *const in)
Sebastian Hack's avatar
Sebastian Hack committed
230
{
231
	ir_graph *irg = get_irn_irg(block);
232
	ir_node  *res = new_ir_node(NULL, irg, block, op_be_Keep, mode_ANY, n, in);
233
	init_node_attr(res, 1, arch_irn_flag_schedule_first);
Matthias Braun's avatar
Matthias Braun committed
234
	be_node_attr_t *attr = (be_node_attr_t*) get_irn_generic_attr(res);
235
	attr->exc.pinned = true;
Sebastian Hack's avatar
Sebastian Hack committed
236

Matthias Braun's avatar
Matthias Braun committed
237
	for (int i = 0; i < n; ++i) {
238
239
		arch_register_req_t const *const req = arch_get_irn_register_req(in[i]);
		be_node_set_register_req_in(res, i, req->cls->class_req);
Sebastian Hack's avatar
Sebastian Hack committed
240
	}
241
242
243
244
	keep_alive(res);
	return res;
}

245
246
247
248
249
250
251
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);
}

252
ir_node *be_new_IncSP(const arch_register_t *sp, ir_node *bl,
253
                      ir_node *old_sp, int offset, unsigned align)
Sebastian Hack's avatar
Sebastian Hack committed
254
{
255
	ir_graph *irg = get_irn_irg(bl);
Matthias Braun's avatar
Matthias Braun committed
256
	ir_node  *in[] = { old_sp };
Matthias Braun's avatar
Matthias Braun committed
257
258
	ir_node  *irn  = new_ir_node(NULL, irg, bl, op_be_IncSP, sp->cls->mode,
	                             ARRAY_SIZE(in), in);
259
	init_node_attr(irn, 1, arch_irn_flags_none);
260
261
262
263
	be_incsp_attr_t *a = (be_incsp_attr_t*)get_irn_generic_attr(irn);
	a->offset          = offset;
	a->align           = align;
	a->base.exc.pinned = true;
Sebastian Hack's avatar
Sebastian Hack committed
264
265

	/* Set output constraint to stack register. */
Matthias Braun's avatar
Matthias Braun committed
266
	be_node_set_register_req_in(irn, 0, sp->cls->class_req);
267
	arch_copy_irn_out_info(irn, 0, old_sp);
Sebastian Hack's avatar
Sebastian Hack committed
268
	return irn;
Sebastian Hack's avatar
Sebastian Hack committed
269
}
Sebastian Hack's avatar
Sebastian Hack committed
270

271
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
272
{
Matthias Braun's avatar
Matthias Braun committed
273
	ir_mode  *mode  = get_irn_mode(src);
274
	ir_graph *irg   = get_irn_irg(bl);
Matthias Braun's avatar
Matthias Braun committed
275
276
	int       arity = n+1;
	ir_node **in    = ALLOCAN(ir_node*, arity);
Sebastian Hack's avatar
Sebastian Hack committed
277
	in[0] = src;
Christoph Mallon's avatar
Christoph Mallon committed
278
	MEMCPY(&in[1], in_keep, n);
Matthias Braun's avatar
Matthias Braun committed
279
	ir_node *irn = new_ir_node(NULL, irg, bl, op_be_CopyKeep, mode, arity, in);
280
	set_copy_info(irn, irg, src, arch_irn_flag_schedule_first);
281
282
	for (int i = 0; i < n; ++i) {
		ir_node *pred = in_keep[i];
283
284
		arch_register_req_t const *const req = arch_get_irn_register_req(pred);
		be_node_set_register_req_in(irn, i + 1, req->cls->class_req);
285
	}
Sebastian Hack's avatar
Sebastian Hack committed
286
287
288
	return irn;
}

289
290
ir_node *be_get_CopyKeep_op(const ir_node *cpy)
{
291
	return get_irn_n(cpy, n_be_CopyKeep_op);
292
293
}

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

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

310
void be_set_MemPerm_out_entity(const ir_node *irn, unsigned n, ir_entity *ent)
Matthias Braun's avatar
Matthias Braun committed
311
{
312
	assert(n < be_get_MemPerm_entity_arity(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);
Matthias Braun's avatar
Matthias Braun committed
315
316
317
	attr->out_entities[n] = ent;
}

318
ir_entity* be_get_MemPerm_out_entity(const ir_node* irn, unsigned n)
Matthias Braun's avatar
Matthias Braun committed
319
{
320
	assert(n < be_get_MemPerm_entity_arity(irn));
Matthias Braun's avatar
Matthias Braun committed
321
322
	const be_memperm_attr_t *attr
		= (const be_memperm_attr_t*)get_irn_generic_attr_const(irn);
Matthias Braun's avatar
Matthias Braun committed
323
324
325
	return attr->out_entities[n];
}

326
327
328
void be_set_MemPerm_offset(ir_node *irn, int offset)
{
	assert(be_is_MemPerm(irn));
Matthias Braun's avatar
Matthias Braun committed
329
	be_memperm_attr_t *attr = (be_memperm_attr_t*)get_irn_generic_attr(irn);
330
331
332
333
334
335
	attr->offset = offset;
}

int be_get_MemPerm_offset(const ir_node *irn)
{
	assert(be_is_MemPerm(irn));
Matthias Braun's avatar
Matthias Braun committed
336
337
	const be_memperm_attr_t *attr
		= (const be_memperm_attr_t*)get_irn_generic_attr_const(irn);
338
339
340
	return attr->offset;
}

341
unsigned be_get_MemPerm_entity_arity(const ir_node *irn)
342
{
Matthias Braun's avatar
Matthias Braun committed
343
	assert(be_is_MemPerm(irn));
344
	return get_irn_arity(irn);
345
346
}

347
const arch_register_req_t *be_create_reg_req(struct obstack *obst,
348
349
                                             const arch_register_t *reg,
                                             bool ignore)
Sebastian Hack's avatar
Sebastian Hack committed
350
{
351
	arch_register_class_t const *cls     = reg->cls;
Matthias Braun's avatar
Matthias Braun committed
352
353
	unsigned                    *limited
		= rbitset_obstack_alloc(obst, cls->n_regs);
Matthias Braun's avatar
Matthias Braun committed
354
	rbitset_set(limited, reg->index);
355
	arch_register_req_t *req = OALLOCZ(obst, arch_register_req_t);
356
	req->cls     = cls;
Matthias Braun's avatar
Matthias Braun committed
357
	req->limited = limited;
358
	req->width   = 1;
359
	req->ignore  = ignore;
360
	return req;
361
362
}

363
364
ir_node *be_get_IncSP_pred(ir_node *irn)
{
Michael Beck's avatar
BugFix:    
Michael Beck committed
365
366
367
368
	assert(be_is_IncSP(irn));
	return get_irn_n(irn, 0);
}

369
370
void be_set_IncSP_pred(ir_node *incsp, ir_node *pred)
{
371
372
373
374
	assert(be_is_IncSP(incsp));
	set_irn_n(incsp, 0, pred);
}

375
void be_set_IncSP_offset(ir_node *irn, int offset)
Sebastian Hack's avatar
Sebastian Hack committed
376
377
{
	assert(be_is_IncSP(irn));
Matthias Braun's avatar
Matthias Braun committed
378
	be_incsp_attr_t *a = (be_incsp_attr_t*)get_irn_generic_attr(irn);
Sebastian Hack's avatar
Sebastian Hack committed
379
380
	a->offset = offset;
}
381

382
int be_get_IncSP_offset(const ir_node *irn)
Sebastian Hack's avatar
Sebastian Hack committed
383
{
Sebastian Hack's avatar
Sebastian Hack committed
384
	assert(be_is_IncSP(irn));
Matthias Braun's avatar
Matthias Braun committed
385
386
	const be_incsp_attr_t *a
		= (const be_incsp_attr_t*)get_irn_generic_attr_const(irn);
Sebastian Hack's avatar
Sebastian Hack committed
387
388
	return a->offset;
}
Sebastian Hack's avatar
Sebastian Hack committed
389

390
unsigned be_get_IncSP_align(const ir_node *irn)
391
392
{
	assert(be_is_IncSP(irn));
Matthias Braun's avatar
Matthias Braun committed
393
394
	const be_incsp_attr_t *a
		= (const be_incsp_attr_t*)get_irn_generic_attr_const(irn);
395
396
397
	return a->align;
}

398
ir_node *be_new_Phi(ir_node *block, int n_ins, ir_node **ins, ir_mode *mode,
399
                    const arch_register_req_t *req)
400
{
Matthias Braun's avatar
Matthias Braun committed
401
402
	ir_graph *irg  = get_irn_irg(block);
	ir_node  *phi = new_ir_node(NULL, irg, block, op_Phi, mode, n_ins, ins);
403
	phi->attr.phi.u.backedge = new_backedge_arr(get_irg_obstack(irg), n_ins);
Matthias Braun's avatar
Matthias Braun committed
404
405
	struct obstack *obst = be_get_be_obst(irg);
	backend_info_t *info = be_get_info(phi);
406
	info->out_infos = NEW_ARR_DZ(reg_out_info_t, obst, 1);
407
	info->in_reqs   = be_allocate_in_reqs(irg, n_ins);
408
409

	info->out_infos[0].req = req;
Matthias Braun's avatar
Matthias Braun committed
410
	for (int i = 0; i < n_ins; ++i) {
411
		info->in_reqs[i] = req;
412
	}
413
	verify_new_node(phi);
414
	phi = optimize_node(phi);
415
416
417
	return phi;
}

418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
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);

437
	arch_register_req_t const **const in_reqs = be_allocate_in_reqs(irg, n_ins);
438
439
440
441
442
443
444
	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;

445
	verify_new_node(phi);
446
447
448
	return optimize_node(phi);
}

449
void be_set_phi_reg_req(ir_node *node, const arch_register_req_t *req)
450
{
Matthias Braun's avatar
Matthias Braun committed
451
	assert(mode_is_data(get_irn_mode(node)));
452
453
	backend_info_t *info = be_get_info(node);
	info->out_infos[0].req = req;
Matthias Braun's avatar
Matthias Braun committed
454
	for (int i = 0, arity = get_irn_arity(node); i < arity; ++i) {
455
456
		info->in_reqs[i] = req;
	}
457
458
}

459
460
461
462
463
464
465
466
467
468
469
470
471
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;
}

472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
ir_node *be_new_Relocation(ir_graph *irg, unsigned kind, ir_entity *entity)
{
	ir_node *const block = get_irg_start_block(irg);
	ir_node *const node  = new_ir_node(NULL, irg, block, op_be_Relocation,
	                                   mode_P, 0, NULL);
	be_relocation_attr_t *const attr
		= (be_relocation_attr_t*)get_irn_generic_attr(node);
	attr->entity = entity;
	attr->kind   = kind;
	ir_node *const optimized = optimize_node(node);
	return optimized;
}

unsigned be_get_Relocation_kind(ir_node const* const node)
{
	assert(be_is_Relocation(node));
	be_relocation_attr_t const *const attr
		= (be_relocation_attr_t const*)get_irn_generic_attr_const(node);
	return attr->kind;
}

ir_entity *be_get_Relocation_entity(ir_node const* const node)
{
	assert(be_is_Relocation(node));
	be_relocation_attr_t const *const attr
		= (be_relocation_attr_t const*)get_irn_generic_attr_const(node);
	return attr->entity;
}

Christoph Mallon's avatar
Christoph Mallon committed
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
ir_node *be_new_Start(ir_graph *const irg, be_start_out const *const outs)
{
	ir_node *const block  = get_irg_start_block(irg);
	ir_node *const start  = new_ir_node(NULL, irg, block, op_be_Start, mode_T, 0, NULL);
	unsigned const n_regs = isa_if->n_registers;

	/* Count the number of outsputs. */
	unsigned k = 1; /* +1 for memory */
	for (unsigned i = 0; i != n_regs; ++i) {
		if (outs[i] != BE_START_NO)
			++k;
	}

	be_info_init_irn(start, arch_irn_flag_schedule_first, NULL, k);

	/* Set out requirements and registers. */
	unsigned l = 0;
	arch_set_irn_register_req_out(start, l++, arch_memory_req);
	arch_register_t const *const regs = isa_if->registers;
	for (unsigned i = 0; i != n_regs; ++i) {
		if (outs[i] != BE_START_NO) {
			arch_register_t     const *const reg = &regs[i];
			arch_register_req_t const *const req = outs[i] == BE_START_IGNORE
				? be_create_reg_req(be_get_be_obst(irg), reg, true)
				: reg->single_req;
			arch_set_irn_register_req_out(start, l, req);
			arch_set_irn_register_out(    start, l, reg);
			++l;
		}
	}
	assert(l == k);

	return start;
}

ir_node *be_get_Start_mem(ir_graph *const irg)
{
	ir_node *const start = get_irg_start(irg);
	return be_get_or_make_Proj_for_pn(start, 0);
}

ir_node *be_get_Start_proj(ir_graph *const irg, arch_register_t const *const reg)
{
	ir_node *const start = get_irg_start(irg);
	/* do a naive linear search... */
	be_foreach_out(start, i) {
		arch_register_t const *const out_reg = arch_get_irn_register_out(start, i);
		if (out_reg == reg)
			return be_get_or_make_Proj_for_pn(start, i);
	}
	panic("tried querying undefined register '%s' at Start", reg->name);
}

554
555
556
557
558
559
ir_node *be_new_Proj(ir_node *const pred, unsigned const pos)
{
	arch_register_req_t const *const req = arch_get_irn_register_req_out(pred, pos);
	return new_r_Proj(pred, req->cls->mode, pos);
}

560
561
562
563
564
565
ir_node *be_new_Proj_reg(ir_node *const pred, unsigned const pos, arch_register_t const *const reg)
{
	arch_set_irn_register_out(pred, pos, reg);
	return be_new_Proj(pred, pos);
}

566
567
568
569
570
571
ir_node *be_get_or_make_Proj_for_pn(ir_node *const irn, unsigned const pn)
{
	ir_node *const proj = get_Proj_for_pn(irn, pn);
	return proj ? proj : be_new_Proj(irn, pn);
}

572
573
574
/**
 * ir_op-Operation: dump a be node to file
 */
575
static void dump_node(FILE *f, const ir_node *irn, dump_reason_t reason)
576
{
577
578
	assert(is_be_node(irn));

579
	switch (reason) {
Matthias Braun's avatar
Matthias Braun committed
580
581
582
	case dump_node_opcode_txt:
		fputs(get_irn_opname(irn), f);
		break;
583
584
585
586
	case dump_node_mode_txt: {
		ir_mode *const mode = get_irn_mode(irn);
		if (mode != mode_ANY && mode != mode_T)
			fprintf(f, "%s", get_mode_name(mode));
Matthias Braun's avatar
Matthias Braun committed
587
		break;
588
	}
Matthias Braun's avatar
Matthias Braun committed
589
	case dump_node_nodeattr_txt:
590
		if (be_is_IncSP(irn)) {
Matthias Braun's avatar
Matthias Braun committed
591
592
			const be_incsp_attr_t *attr
				= (const be_incsp_attr_t*)get_irn_generic_attr_const(irn);
Matthias Braun's avatar
Matthias Braun committed
593
594
595
596
			fprintf(f, " [%d] ", attr->offset);
		}
		break;
	case dump_node_info_txt:
597
		if (be_is_IncSP(irn)) {
Matthias Braun's avatar
Matthias Braun committed
598
599
			const be_incsp_attr_t *a
				= (const be_incsp_attr_t*)get_irn_generic_attr_const(irn);
600
			fprintf(f, "align: %u\n", a->align);
Matthias Braun's avatar
Matthias Braun committed
601
			fprintf(f, "offset: %d\n", a->offset);
602
		} else if (be_is_MemPerm(irn)) {
603
			for (unsigned i = 0; i < be_get_MemPerm_entity_arity(irn); ++i) {
Matthias Braun's avatar
Matthias Braun committed
604
605
606
				ir_entity *in  = be_get_MemPerm_in_entity(irn, i);
				ir_entity *out = be_get_MemPerm_out_entity(irn, i);
				if (in != NULL)
607
					fprintf(f, "\nin[%u]: %s\n", i, get_entity_name(in));
Matthias Braun's avatar
Matthias Braun committed
608
				if (out != NULL)
609
					fprintf(f, "\nout[%u]: %s\n", i, get_entity_name(out));
610
			}
Matthias Braun's avatar
Matthias Braun committed
611
		}
612
		break;
613
614
615
	}
}

616
void be_copy_attr(ir_graph *const irg, ir_node const *const old_node, ir_node *const new_node)
Sebastian Hack's avatar
Sebastian Hack committed
617
{
618
619
	void const *const old_attr = get_irn_generic_attr_const(old_node);
	void       *const new_attr = get_irn_generic_attr(new_node);
Sebastian Hack's avatar
Sebastian Hack committed
620
	memcpy(new_attr, old_attr, get_op_attr_size(get_irn_op(old_node)));
621
622
623
624
625
626
627
628

	backend_info_t *const old_info = be_get_info(old_node);
	backend_info_t *const new_info = be_get_info(new_node);
	*new_info = *old_info;
	memset(&new_info->sched_info, 0, sizeof(new_info->sched_info));
	if (new_info->out_infos) {
		struct obstack *const obst = be_get_be_obst(irg);
		new_info->out_infos = DUP_ARR_D(reg_out_info_t, obst, new_info->out_infos);
Sebastian Hack's avatar
Sebastian Hack committed
629
	}
Sebastian Hack's avatar
Sebastian Hack committed
630
631
}

632
633
634
635
636
bool is_be_node(const ir_node *irn)
{
	return get_op_tag(get_irn_op(irn)) == be_op_tag;
}

637
638
639
640
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
641
	set_op_dump(res, dump_node);
642
	set_op_copy_attr(res, be_copy_attr);
643
	set_op_tag(res, be_op_tag);
644
645
646
	return res;
}

647
648
void be_init_op(void)
{
649
	assert(op_be_Perm == NULL);
Matthias Braun's avatar
Matthias Braun committed
650

Matthias Braun's avatar
Matthias Braun committed
651
	/* Acquire all needed opcodes. */
652
	unsigned const o = get_next_ir_opcodes(beo_last + 1);
653
654
655
656
657
658
659
660
	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));
	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));
	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));
	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));
	op_be_Relocation = new_be_op(o+beo_Relocation, "be_Relocation", op_pin_state_floats,     irop_flag_constlike|irop_flag_start_block, oparity_any,      sizeof(be_relocation_attr_t));
Christoph Mallon's avatar
Christoph Mallon committed
661
	op_be_Start      = new_be_op(o+beo_Start,      "be_Start",      op_pin_state_pinned,     irop_flag_start_block,                     oparity_variable, sizeof(be_node_attr_t));
662
663
664
665
666
667
668
669
670

	set_op_attrs_equal(op_be_Asm,        be_asm_attr_equal);
	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);
	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);
	set_op_attrs_equal(op_be_Relocation, be_relocation_attrs_equal);
Matthias Braun's avatar
Matthias Braun committed
671
}
Matthias Braun's avatar
Matthias Braun committed
672
673
674

void be_finish_op(void)
{
Matthias Braun's avatar
Matthias Braun committed
675
676
677
	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
678
679
680
	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
681
}