benode.c 38.6 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
/*
Michael Beck's avatar
Michael Beck committed
2
 * Copyright (C) 1995-2011 University of Karlsruhe.  All right reserved.
Christian Würdig's avatar
Christian Würdig committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 *
 * This file is part of libFirm.
 *
 * This file may be distributed and/or modified under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation and appearing in the file LICENSE.GPL included in the
 * packaging of this file.
 *
 * Licensees holding valid libFirm Professional Edition licenses may use
 * this file in accordance with the libFirm Commercial License.
 * Agreement provided with the Software.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE.
 */

Sebastian Hack's avatar
Sebastian Hack committed
20
/**
Christian Würdig's avatar
Christian Würdig committed
21
22
23
24
25
 * @file
 * @brief       Backend node support for generic backend nodes.
 * @author      Sebastian Hack
 * @date        17.05.2005
 * @version     $Id$
Sebastian Hack's avatar
Sebastian Hack committed
26
 *
27
 * Backend node support for generic backend nodes.
Michael Beck's avatar
Michael Beck committed
28
 * This file provides Perm, Copy, Spill and Reload nodes.
Sebastian Hack's avatar
Sebastian Hack committed
29
 */
30
#include "config.h"
Sebastian Hack's avatar
Sebastian Hack committed
31
32
33
34
35
36

#include <stdlib.h>

#include "obst.h"
#include "set.h"
#include "pmap.h"
37
#include "util.h"
Sebastian Hack's avatar
Sebastian Hack committed
38
#include "debug.h"
39
#include "fourcc.h"
Sebastian Hack's avatar
Sebastian Hack committed
40
#include "bitfiddle.h"
Matthias Braun's avatar
Matthias Braun committed
41
#include "raw_bitset.h"
42
#include "error.h"
43
#include "array_t.h"
Sebastian Hack's avatar
Sebastian Hack committed
44
45
46
47

#include "irop_t.h"
#include "irmode_t.h"
#include "irnode_t.h"
48
#include "ircons_t.h"
49
#include "irprintf.h"
Sebastian Hack's avatar
Sebastian Hack committed
50
#include "irgwalk.h"
Michael Beck's avatar
Michael Beck committed
51
#include "iropt_t.h"
Sebastian Hack's avatar
Sebastian Hack committed
52

53
54
#include "be_t.h"
#include "belive_t.h"
55
#include "besched.h"
56
#include "benode.h"
57
#include "bearch.h"
Sebastian Hack's avatar
Sebastian Hack committed
58

59
60
#include "beirgmod.h"

61
62
63
64
typedef struct be_node_attr_t {
	except_attr  exc;
} be_node_attr_t;

65
66
/** The be_Return nodes attribute type. */
typedef struct {
67
	be_node_attr_t base;
Matthias Braun's avatar
Matthias Braun committed
68
69
70
	int            num_ret_vals; /**< number of return values */
	unsigned       pop;          /**< number of bytes that should be popped */
	int            emit_pop;     /**< if set, emit pop bytes, even if pop = 0 */
71
72
} be_return_attr_t;

Michael Beck's avatar
Michael Beck committed
73
/** The be_IncSP attribute type. */
Sebastian Hack's avatar
Sebastian Hack committed
74
typedef struct {
75
	be_node_attr_t base;
Matthias Braun's avatar
Matthias Braun committed
76
77
78
79
	int            offset;    /**< The offset by which the stack shall be
	                               expanded/shrinked. */
	int            align;     /**< whether stack should be aligned after the
	                               IncSP */
Michael Beck's avatar
Michael Beck committed
80
} be_incsp_attr_t;
Sebastian Hack's avatar
Sebastian Hack committed
81

82
/** The be_Frame attribute type. */
83
typedef struct {
84
	be_node_attr_t  base;
85
86
	ir_entity      *ent;
	int             offset;
87
88
} be_frame_attr_t;

89
/** The be_Call attribute type. */
90
typedef struct {
91
	be_node_attr_t  base;
Matthias Braun's avatar
Matthias Braun committed
92
	ir_entity      *ent;        /**< called entity if this is a static call. */
93
	unsigned        pop;
Matthias Braun's avatar
Matthias Braun committed
94
	ir_type        *call_tp;    /**< call type, copied from the original Call */
95
96
} be_call_attr_t;

97
typedef struct {
98
99
100
	be_node_attr_t base;
	ir_entity    **in_entities;
	ir_entity    **out_entities;
Matthias Braun's avatar
Matthias Braun committed
101
} be_memperm_attr_t;
102

103
104
105
ir_op *op_be_Spill;
ir_op *op_be_Reload;
ir_op *op_be_Perm;
Matthias Braun's avatar
Matthias Braun committed
106
ir_op *op_be_MemPerm;
107
108
ir_op *op_be_Copy;
ir_op *op_be_Keep;
Sebastian Hack's avatar
Sebastian Hack committed
109
ir_op *op_be_CopyKeep;
110
111
112
ir_op *op_be_Call;
ir_op *op_be_Return;
ir_op *op_be_IncSP;
Sebastian Hack's avatar
Sebastian Hack committed
113
ir_op *op_be_AddSP;
Michael Beck's avatar
Michael Beck committed
114
ir_op *op_be_SubSP;
115
ir_op *op_be_Start;
116
ir_op *op_be_FrameAddr;
Sebastian Hack's avatar
Sebastian Hack committed
117

Michael Beck's avatar
Michael Beck committed
118
/**
Michael Beck's avatar
Michael Beck committed
119
 * Compare the attributes of two be_FrameAddr nodes.
Michael Beck's avatar
Michael Beck committed
120
 *
Michael Beck's avatar
Michael Beck committed
121
 * @return zero if both nodes have identically attributes
Michael Beck's avatar
Michael Beck committed
122
 */
Michael Beck's avatar
Michael Beck committed
123
static int FrameAddr_cmp_attr(const ir_node *a, const ir_node *b)
124
{
125
126
	const be_frame_attr_t *a_attr = (const be_frame_attr_t*)get_irn_generic_attr_const(a);
	const be_frame_attr_t *b_attr = (const be_frame_attr_t*)get_irn_generic_attr_const(b);
Michael Beck's avatar
Michael Beck committed
127

128
129
130
	if (a_attr->ent != b_attr->ent || a_attr->offset != b_attr->offset)
		return 1;

131
	return be_nodes_equal(a, b);
132
133
}

Michael Beck's avatar
Michael Beck committed
134
135
136
137
138
/**
 * Compare the attributes of two be_Return nodes.
 *
 * @return zero if both nodes have identically attributes
 */
Michael Beck's avatar
Michael Beck committed
139
static int Return_cmp_attr(const ir_node *a, const ir_node *b)
140
{
141
142
	const be_return_attr_t *a_attr = (const be_return_attr_t*)get_irn_generic_attr_const(a);
	const be_return_attr_t *b_attr = (const be_return_attr_t*)get_irn_generic_attr_const(b);
143
144
145

	if (a_attr->num_ret_vals != b_attr->num_ret_vals)
		return 1;
146
147
	if (a_attr->pop != b_attr->pop)
		return 1;
148
149
	if (a_attr->emit_pop != b_attr->emit_pop)
		return 1;
150

151
	return be_nodes_equal(a, b);
152
153
}

Michael Beck's avatar
Michael Beck committed
154
155
156
157
158
/**
 * Compare the attributes of two be_IncSP nodes.
 *
 * @return zero if both nodes have identically attributes
 */
Michael Beck's avatar
Michael Beck committed
159
static int IncSP_cmp_attr(const ir_node *a, const ir_node *b)
160
{
161
162
	const be_incsp_attr_t *a_attr = (const be_incsp_attr_t*)get_irn_generic_attr_const(a);
	const be_incsp_attr_t *b_attr = (const be_incsp_attr_t*)get_irn_generic_attr_const(b);
163
164
165
166

	if (a_attr->offset != b_attr->offset)
		return 1;

167
	return be_nodes_equal(a, b);
168
169
}

Michael Beck's avatar
Michael Beck committed
170
171
172
173
174
/**
 * Compare the attributes of two be_Call nodes.
 *
 * @return zero if both nodes have identically attributes
 */
Michael Beck's avatar
Michael Beck committed
175
static int Call_cmp_attr(const ir_node *a, const ir_node *b)
176
{
177
178
	const be_call_attr_t *a_attr = (const be_call_attr_t*)get_irn_generic_attr_const(a);
	const be_call_attr_t *b_attr = (const be_call_attr_t*)get_irn_generic_attr_const(b);
179
180

	if (a_attr->ent != b_attr->ent ||
181
		a_attr->call_tp != b_attr->call_tp)
182
183
		return 1;

184
	return be_nodes_equal(a, b);
Michael Beck's avatar
Michael Beck committed
185
186
}

187
static arch_register_req_t *allocate_reg_req(const ir_node *node)
Matthias Braun's avatar
Matthias Braun committed
188
{
189
	ir_graph       *irg  = get_irn_irg(node);
190
	struct obstack *obst = be_get_be_obst(irg);
Matthias Braun's avatar
Matthias Braun committed
191

192
	arch_register_req_t *req = OALLOCZ(obst, arch_register_req_t);
193
194
	return req;
}
Matthias Braun's avatar
Matthias Braun committed
195

196
197
void be_set_constr_in(ir_node *node, int pos, const arch_register_req_t *req)
{
198
199
200
	backend_info_t *info = be_get_info(node);
	assert(pos < get_irn_arity(node));
	info->in_reqs[pos] = req;
201
}
Matthias Braun's avatar
Matthias Braun committed
202

203
204
205
206
void be_set_constr_out(ir_node *node, int pos, const arch_register_req_t *req)
{
	backend_info_t *info = be_get_info(node);
	info->out_infos[pos].req = req;
Matthias Braun's avatar
Matthias Braun committed
207
208
}

209
/**
210
 * Initializes the generic attribute of all be nodes and return it.
211
 */
212
static void init_node_attr(ir_node *node, int n_inputs, int n_outputs)
Sebastian Hack's avatar
Sebastian Hack committed
213
{
214
	ir_graph       *irg  = get_irn_irg(node);
215
	struct obstack *obst = be_get_be_obst(irg);
216
	backend_info_t *info = be_get_info(node);
217
	const arch_register_req_t **in_reqs;
Sebastian Hack's avatar
Sebastian Hack committed
218

219
220
	if (n_inputs >= 0) {
		int i;
221
222
		assert(n_inputs == get_irn_arity(node));
		in_reqs = OALLOCN(obst, const arch_register_req_t*, n_inputs);
223
		for (i = 0; i < n_inputs; ++i) {
224
			in_reqs[i] = arch_no_register_req;
225
226
		}
	} else {
227
		in_reqs = NEW_ARR_F(const arch_register_req_t*, 0);
228
	}
229
	info->in_reqs = in_reqs;
230

231
232
233
234
235
236
237
	if (n_outputs >= 0) {
		int i;
		info->out_infos = NEW_ARR_D(reg_out_info_t, obst, n_outputs);
		memset(info->out_infos, 0, n_outputs * sizeof(info->out_infos[0]));
		for (i = 0; i < n_outputs; ++i) {
			info->out_infos[i].req = arch_no_register_req;
		}
238
	} else {
239
		info->out_infos = NEW_ARR_F(reg_out_info_t, 0);
Sebastian Hack's avatar
Sebastian Hack committed
240
241
	}
}
242

243
static void add_register_req_out(ir_node *node)
244
{
245
	backend_info_t *info = be_get_info(node);
246
247
248
249
250
251
252
253
	reg_out_info_t  out_info;
	memset(&out_info, 0, sizeof(out_info));
	out_info.req = arch_no_register_req;
	ARR_APP1(reg_out_info_t, info->out_infos, out_info);
}

static void add_register_req_in(ir_node *node)
{
254
255
	backend_info_t *info = be_get_info(node);
	ARR_APP1(const arch_register_req_t*, info->in_reqs, arch_no_register_req);
256
257
}

258
259
260
ir_node *be_new_Spill(const arch_register_class_t *cls,
		const arch_register_class_t *cls_frame, ir_node *bl,
		ir_node *frame, ir_node *to_spill)
261
{
Matthias Braun's avatar
Matthias Braun committed
262
	be_frame_attr_t *a;
263
	ir_node         *in[2];
264
	ir_node         *res;
265
	ir_graph        *irg = get_Block_irg(bl);
266

267
268
269
	in[0]     = frame;
	in[1]     = to_spill;
	res       = new_ir_node(NULL, irg, bl, op_be_Spill, mode_M, 2, in);
270
271
	init_node_attr(res, 2, 1);
	a         = (be_frame_attr_t*) get_irn_generic_attr(res);
272
	a->ent    = NULL;
Matthias Braun's avatar
Matthias Braun committed
273
	a->offset = 0;
274
	a->base.exc.pin_state = op_pin_state_pinned;
Sebastian Hack's avatar
Sebastian Hack committed
275

276
277
	be_node_set_reg_class_in(res, be_pos_Spill_frame, cls_frame);
	be_node_set_reg_class_in(res, be_pos_Spill_val, cls);
278
279
	/*
	 * For spills and reloads, we return "none" as requirement for frame
280
	 * pointer, so every input is ok. Some backends need this (STA).
281
282
283
	 * Matze: we should investigate if this is really needed, this solution
	 *        looks very hacky to me
	 */
284
	be_set_constr_in(res, be_pos_Spill_frame, arch_no_register_req);
285

286
287
	arch_set_out_register_req(res, 0, arch_no_register_req);

Sebastian Hack's avatar
Sebastian Hack committed
288
289
	return res;
}
290

291
ir_node *be_new_Reload(const arch_register_class_t *cls,
292
		const arch_register_class_t *cls_frame, ir_node *block,
293
		ir_node *frame, ir_node *mem, ir_mode *mode)
294
{
295
296
297
	ir_node  *in[2];
	ir_node  *res;
	ir_graph *irg = get_Block_irg(block);
298
	be_frame_attr_t *a;
299
300
301

	in[0] = frame;
	in[1] = mem;
302
	res   = new_ir_node(NULL, irg, block, op_be_Reload, mode, 2, in);
303

304
	init_node_attr(res, 2, 1);
305
	be_node_set_reg_class_out(res, 0, cls);
306

307
308
	be_node_set_reg_class_in(res, be_pos_Reload_frame, cls_frame);
	arch_irn_set_flags(res, arch_irn_flags_rematerializable);
309

310
311
312
313
314
	a         = (be_frame_attr_t*) get_irn_generic_attr(res);
	a->ent    = NULL;
	a->offset = 0;
	a->base.exc.pin_state = op_pin_state_pinned;

315
316
317
318
319
320
	/*
	 * For spills and reloads, we return "none" as requirement for frame
	 * pointer, so every input is ok. Some backends need this (e.g. STA).
	 * Matze: we should investigate if this is really needed, this solution
	 *        looks very hacky to me
	 */
321
	be_set_constr_in(res, be_pos_Reload_frame, arch_no_register_req);
322

Sebastian Hack's avatar
Sebastian Hack committed
323
324
	return res;
}
325

326
ir_node *be_get_Reload_mem(const ir_node *irn)
Sebastian Hack's avatar
Sebastian Hack committed
327
328
{
	assert(be_is_Reload(irn));
Daniel Grund's avatar
Daniel Grund committed
329
	return get_irn_n(irn, be_pos_Reload_mem);
Sebastian Hack's avatar
Sebastian Hack committed
330
331
}

332
333
334
335
336
337
ir_node *be_get_Reload_frame(const ir_node *irn)
{
	assert(be_is_Reload(irn));
	return get_irn_n(irn, be_pos_Reload_frame);
}

338
339
340
341
342
ir_node *be_get_Spill_val(const ir_node *irn)
{
	assert(be_is_Spill(irn));
	return get_irn_n(irn, be_pos_Spill_val);
}
Matthias Braun's avatar
Matthias Braun committed
343

344
345
346
347
348
ir_node *be_get_Spill_frame(const ir_node *irn)
{
	assert(be_is_Spill(irn));
	return get_irn_n(irn, be_pos_Spill_frame);
}
349

350
351
ir_node *be_new_Perm(const arch_register_class_t *cls, ir_node *block,
                     int n, ir_node *in[])
Sebastian Hack's avatar
Sebastian Hack committed
352
{
353
354
355
	int            i;
	ir_graph       *irg = get_Block_irg(block);
	be_node_attr_t *attr;
356

357
	ir_node *irn = new_ir_node(NULL, irg, block, op_be_Perm, mode_T, n, in);
358
	init_node_attr(irn, n, n);
359
360
	attr                = (be_node_attr_t*) get_irn_generic_attr(irn);
	attr->exc.pin_state = op_pin_state_pinned;
361
	for (i = 0; i < n; ++i) {
362
363
		be_node_set_reg_class_in(irn, i, cls);
		be_node_set_reg_class_out(irn, i, cls);
Sebastian Hack's avatar
Sebastian Hack committed
364
365
	}

Sebastian Hack's avatar
Sebastian Hack committed
366
367
	return irn;
}
368

369
370
void be_Perm_reduce(ir_node *perm, int new_size, int *map)
{
371
372
373
374
375
	int             arity      = get_irn_arity(perm);
	const arch_register_req_t **old_in_reqs
		= ALLOCAN(const arch_register_req_t*, arity);
	reg_out_info_t  *old_infos = ALLOCAN(reg_out_info_t, arity);
	backend_info_t  *info      = be_get_info(perm);
376
	ir_node        **new_in;
377
	int              i;
378
379

	assert(be_is_Perm(perm));
380
	assert(new_size <= arity);
381

382
	new_in = ALLOCAN(ir_node*, new_size);
383

384
	/* save the old register data */
385
	memcpy(old_in_reqs, info->in_reqs, arity * sizeof(old_in_reqs[0]));
386
	memcpy(old_infos, info->out_infos, arity * sizeof(old_infos[0]));
387

Matthias Braun's avatar
Matthias Braun committed
388
	/* compose the new in array and set the new register data directly */
389
	for (i = 0; i < new_size; ++i) {
390
		int idx = map[i];
391
		new_in[i]          = get_irn_n(perm, idx);
392
		info->in_reqs[i]   = old_in_reqs[idx];
393
		info->out_infos[i] = old_infos[idx];
394
395
396
397
398
	}

	set_irn_in(perm, new_size, new_in);
}

399
ir_node *be_new_MemPerm(ir_node *block, int n, ir_node *in[])
Matthias Braun's avatar
Matthias Braun committed
400
{
401
402
	ir_graph                     *irg       = get_Block_irg(block);
	const arch_env_t             *arch_env  = be_get_irg_arch_env(irg);
403
404
405
406
407
	ir_node                      *frame     = get_irg_frame(irg);
	const arch_register_t        *sp        = arch_env->sp;
	ir_node                      *irn;
	be_memperm_attr_t            *attr;
	ir_node                     **real_in;
Matthias Braun's avatar
Matthias Braun committed
408

409
	real_in = ALLOCAN(ir_node*, n + 1);
410
411
412
	real_in[0] = frame;
	memcpy(&real_in[1], in, n * sizeof(real_in[0]));

413
	irn = new_ir_node(NULL, irg, block, op_be_MemPerm, mode_T, n+1, real_in);
414

415
	init_node_attr(irn, n + 1, n);
416
	be_node_set_reg_class_in(irn, 0, sp->reg_class);
Matthias Braun's avatar
Matthias Braun committed
417

418
	attr               = (be_memperm_attr_t*)get_irn_generic_attr(irn);
419
420
	attr->in_entities  = OALLOCNZ(irg->obst, ir_entity*, n);
	attr->out_entities = OALLOCNZ(irg->obst, ir_entity*, n);
Matthias Braun's avatar
Matthias Braun committed
421
422
423
424

	return irn;
}

425
ir_node *be_new_Copy(const arch_register_class_t *cls, ir_node *bl, ir_node *op)
Sebastian Hack's avatar
Sebastian Hack committed
426
427
428
{
	ir_node *in[1];
	ir_node *res;
Matthias Braun's avatar
Matthias Braun committed
429
	arch_register_req_t *req;
430
	be_node_attr_t *attr;
431
	ir_graph *irg = get_Block_irg(bl);
432

Sebastian Hack's avatar
Sebastian Hack committed
433
	in[0] = op;
434
	res   = new_ir_node(NULL, irg, bl, op_be_Copy, get_irn_mode(op), 1, in);
435
	init_node_attr(res, 1, 1);
436
437
	attr = (be_node_attr_t*) get_irn_generic_attr(res);
	attr->exc.pin_state = op_pin_state_floats;
438
439
	be_node_set_reg_class_in(res, 0, cls);
	be_node_set_reg_class_out(res, 0, cls);
Matthias Braun's avatar
Matthias Braun committed
440

441
442
443
	req = allocate_reg_req(res);
	req->cls        = cls;
	req->type       = arch_register_req_type_should_be_same;
444
	req->other_same = 1U << 0;
445
	req->width      = 1;
446
	be_set_constr_out(res, 0, req);
Matthias Braun's avatar
Matthias Braun committed
447

Sebastian Hack's avatar
Sebastian Hack committed
448
	return res;
449
450
}

451
452
ir_node *be_get_Copy_op(const ir_node *cpy)
{
453
454
455
	return get_irn_n(cpy, be_pos_Copy_op);
}

456
457
void be_set_Copy_op(ir_node *cpy, ir_node *op)
{
458
459
460
	set_irn_n(cpy, be_pos_Copy_op, op);
}

461
ir_node *be_new_Keep(ir_node *block, int n, ir_node *in[])
Sebastian Hack's avatar
Sebastian Hack committed
462
{
Sebastian Hack's avatar
Sebastian Hack committed
463
	int i;
464
	ir_node *res;
465
	ir_graph *irg = get_Block_irg(block);
466
	be_node_attr_t *attr;
467

468
469
	res = new_ir_node(NULL, irg, block, op_be_Keep, mode_ANY, -1, NULL);
	init_node_attr(res, -1, 1);
470
471
	attr = (be_node_attr_t*) get_irn_generic_attr(res);
	attr->exc.pin_state = op_pin_state_pinned;
Sebastian Hack's avatar
Sebastian Hack committed
472

473
	for (i = 0; i < n; ++i) {
474
		add_irn_n(res, in[i]);
475
		add_register_req_in(res);
Sebastian Hack's avatar
Sebastian Hack committed
476
	}
477
478
479
480
481
482
483
484
485
486
487
	keep_alive(res);

	return res;
}

void be_Keep_add_node(ir_node *keep, const arch_register_class_t *cls, ir_node *node)
{
	int n;

	assert(be_is_Keep(keep));
	n = add_irn_n(keep, node);
488
	add_register_req_in(keep);
489
	be_node_set_reg_class_in(keep, n, cls);
Sebastian Hack's avatar
Sebastian Hack committed
490
491
}

492
493
494
ir_node *be_new_Call(dbg_info *dbg, ir_graph *irg, ir_node *bl, ir_node *mem,
		ir_node *sp, ir_node *ptr, int n_outs, int n, ir_node *in[],
		ir_type *call_tp)
Sebastian Hack's avatar
Sebastian Hack committed
495
{
496
497
	be_call_attr_t *a;
	int real_n = be_pos_Call_first_arg + n;
Sebastian Hack's avatar
Sebastian Hack committed
498
499
	ir_node *irn;
	ir_node **real_in;
Sebastian Hack's avatar
Sebastian Hack committed
500

501
502
503
504
505
	NEW_ARR_A(ir_node *, real_in, real_n);
	real_in[be_pos_Call_mem] = mem;
	real_in[be_pos_Call_sp]  = sp;
	real_in[be_pos_Call_ptr] = ptr;
	memcpy(&real_in[be_pos_Call_first_arg], in, n * sizeof(in[0]));
Sebastian Hack's avatar
Sebastian Hack committed
506

507
	irn = new_ir_node(dbg, irg, bl, op_be_Call, mode_T, real_n, real_in);
508
	init_node_attr(irn, real_n, n_outs);
509
510
511
512
513
	a                     = (be_call_attr_t*)get_irn_generic_attr(irn);
	a->ent                = NULL;
	a->call_tp            = call_tp;
	a->pop                = 0;
	a->base.exc.pin_state = op_pin_state_pinned;
Sebastian Hack's avatar
Sebastian Hack committed
514
	return irn;
Sebastian Hack's avatar
Sebastian Hack committed
515
516
}

517
518
ir_entity *be_Call_get_entity(const ir_node *call)
{
519
	const be_call_attr_t *a = (const be_call_attr_t*)get_irn_generic_attr_const(call);
520
521
522
523
	assert(be_is_Call(call));
	return a->ent;
}

524
525
void be_Call_set_entity(ir_node *call, ir_entity *ent)
{
526
	be_call_attr_t *a = (be_call_attr_t*)get_irn_generic_attr(call);
527
528
529
530
	assert(be_is_Call(call));
	a->ent = ent;
}

531
532
ir_type *be_Call_get_type(ir_node *call)
{
533
	const be_call_attr_t *a = (const be_call_attr_t*)get_irn_generic_attr_const(call);
534
535
536
537
	assert(be_is_Call(call));
	return a->call_tp;
}

538
539
void be_Call_set_type(ir_node *call, ir_type *call_tp)
{
540
	be_call_attr_t *a = (be_call_attr_t*)get_irn_generic_attr(call);
541
542
543
544
	assert(be_is_Call(call));
	a->call_tp = call_tp;
}

545
546
void be_Call_set_pop(ir_node *call, unsigned pop)
{
547
	be_call_attr_t *a = (be_call_attr_t*)get_irn_generic_attr(call);
Matthias Braun's avatar
Matthias Braun committed
548
549
550
	a->pop = pop;
}

551
552
unsigned be_Call_get_pop(const ir_node *call)
{
553
	const be_call_attr_t *a = (const be_call_attr_t*)get_irn_generic_attr_const(call);
Matthias Braun's avatar
Matthias Braun committed
554
555
556
	return a->pop;
}

557
ir_node *be_new_Return(dbg_info *dbg, ir_graph *irg, ir_node *block, int n_res,
558
                       unsigned pop, int n, ir_node *in[])
Sebastian Hack's avatar
Sebastian Hack committed
559
{
560
	be_return_attr_t *a;
561
562
563
564
	ir_node *res;
	int i;

	res = new_ir_node(dbg, irg, block, op_be_Return, mode_X, -1, NULL);
565
566
	init_node_attr(res, -1, 1);
	for (i = 0; i < n; ++i) {
567
		add_irn_n(res, in[i]);
568
		add_register_req_in(res);
569
	}
570
	be_set_constr_out(res, 0, arch_no_register_req);
571

572
	a = (be_return_attr_t*)get_irn_generic_attr(res);
573
574
575
576
	a->num_ret_vals       = n_res;
	a->pop                = pop;
	a->emit_pop           = 0;
	a->base.exc.pin_state = op_pin_state_pinned;
Sebastian Hack's avatar
Sebastian Hack committed
577

578
	return res;
Sebastian Hack's avatar
Sebastian Hack committed
579
580
}

581
582
int be_Return_get_n_rets(const ir_node *ret)
{
583
	const be_return_attr_t *a = (const be_return_attr_t*)get_irn_generic_attr_const(ret);
584
585
586
	return a->num_ret_vals;
}

587
588
unsigned be_Return_get_pop(const ir_node *ret)
{
589
	const be_return_attr_t *a = (const be_return_attr_t*)get_irn_generic_attr_const(ret);
590
591
592
	return a->pop;
}

593
594
int be_Return_get_emit_pop(const ir_node *ret)
{
595
	const be_return_attr_t *a = (const be_return_attr_t*)get_irn_generic_attr_const(ret);
596
597
598
	return a->emit_pop;
}

599
600
void be_Return_set_emit_pop(ir_node *ret, int emit_pop)
{
601
	be_return_attr_t *a = (be_return_attr_t*)get_irn_generic_attr(ret);
602
603
604
	a->emit_pop = emit_pop;
}

605
606
int be_Return_append_node(ir_node *ret, ir_node *node)
{
607
608
609
	int pos;

	pos = add_irn_n(ret, node);
610
	add_register_req_in(ret);
611
612
613
614

	return pos;
}

615
ir_node *be_new_IncSP(const arch_register_t *sp, ir_node *bl,
616
                      ir_node *old_sp, int offset, int align)
Sebastian Hack's avatar
Sebastian Hack committed
617
{
Michael Beck's avatar
Michael Beck committed
618
	be_incsp_attr_t *a;
Sebastian Hack's avatar
Sebastian Hack committed
619
	ir_node *irn;
Sebastian Hack's avatar
Sebastian Hack committed
620
	ir_node *in[1];
621
	ir_graph *irg = get_Block_irg(bl);
Sebastian Hack's avatar
Sebastian Hack committed
622
623

	in[0]     = old_sp;
624
625
	irn       = new_ir_node(NULL, irg, bl, op_be_IncSP, sp->reg_class->mode,
	                        sizeof(in) / sizeof(in[0]), in);
626
	init_node_attr(irn, 1, 1);
627
628
629
630
	a                     = (be_incsp_attr_t*)get_irn_generic_attr(irn);
	a->offset             = offset;
	a->align              = align;
	a->base.exc.pin_state = op_pin_state_pinned;
Sebastian Hack's avatar
Sebastian Hack committed
631
632

	/* Set output constraint to stack register. */
633
634
	be_node_set_reg_class_in(irn, 0, sp->reg_class);
	be_set_constr_single_reg_out(irn, 0, sp, arch_register_req_type_produces_sp);
Sebastian Hack's avatar
Sebastian Hack committed
635
636

	return irn;
Sebastian Hack's avatar
Sebastian Hack committed
637
}
Sebastian Hack's avatar
Sebastian Hack committed
638

639
640
ir_node *be_new_AddSP(const arch_register_t *sp, ir_node *bl, ir_node *old_sp,
		ir_node *sz)
Sebastian Hack's avatar
Sebastian Hack committed
641
{
Sebastian Hack's avatar
Sebastian Hack committed
642
	ir_node *irn;
Sebastian Hack's avatar
Sebastian Hack committed
643
	ir_node *in[be_pos_AddSP_last];
644
	const arch_register_class_t *cls;
645
	ir_graph *irg;
646
	be_node_attr_t *attr;
Sebastian Hack's avatar
Sebastian Hack committed
647

Sebastian Hack's avatar
Sebastian Hack committed
648
649
	in[be_pos_AddSP_old_sp] = old_sp;
	in[be_pos_AddSP_size]   = sz;
Sebastian Hack's avatar
Sebastian Hack committed
650

651
	irg = get_Block_irg(bl);
652
	irn = new_ir_node(NULL, irg, bl, op_be_AddSP, mode_T, be_pos_AddSP_last, in);
653
	init_node_attr(irn, be_pos_AddSP_last, pn_be_AddSP_last);
654
655
	attr = (be_node_attr_t*) get_irn_generic_attr(irn);
	attr->exc.pin_state = op_pin_state_pinned;
Sebastian Hack's avatar
Sebastian Hack committed
656

Sebastian Hack's avatar
Sebastian Hack committed
657
	/* Set output constraint to stack register. */
658
659
	be_set_constr_single_reg_in(irn, be_pos_AddSP_old_sp, sp,
	                            arch_register_req_type_none);
660
	be_node_set_reg_class_in(irn, be_pos_AddSP_size, arch_register_get_class(sp));
Matthias Braun's avatar
Matthias Braun committed
661
662
	be_set_constr_single_reg_out(irn, pn_be_AddSP_sp, sp,
	                             arch_register_req_type_produces_sp);
663

664
	cls = arch_register_get_class(sp);
Sebastian Hack's avatar
Sebastian Hack committed
665
666
667
668

	return irn;
}

669
ir_node *be_new_SubSP(const arch_register_t *sp, ir_node *bl, ir_node *old_sp, ir_node *sz)
Michael Beck's avatar
Michael Beck committed
670
671
672
{
	ir_node *irn;
	ir_node *in[be_pos_SubSP_last];
673
	ir_graph *irg;
674
	be_node_attr_t *attr;
Michael Beck's avatar
Michael Beck committed
675
676
677
678

	in[be_pos_SubSP_old_sp] = old_sp;
	in[be_pos_SubSP_size]   = sz;

679
	irg = get_Block_irg(bl);
Michael Beck's avatar
Michael Beck committed
680
	irn = new_ir_node(NULL, irg, bl, op_be_SubSP, mode_T, be_pos_SubSP_last, in);
681
	init_node_attr(irn, be_pos_SubSP_last, pn_be_SubSP_last);
682
683
	attr = (be_node_attr_t*) get_irn_generic_attr(irn);
	attr->exc.pin_state = op_pin_state_pinned;
Michael Beck's avatar
Michael Beck committed
684
685

	/* Set output constraint to stack register. */
686
687
	be_set_constr_single_reg_in(irn, be_pos_SubSP_old_sp, sp,
	                            arch_register_req_type_none);
688
689
	be_node_set_reg_class_in(irn, be_pos_SubSP_size, arch_register_get_class(sp));
	be_set_constr_single_reg_out(irn, pn_be_SubSP_sp, sp, arch_register_req_type_produces_sp);
Michael Beck's avatar
Michael Beck committed
690
691
692
693

	return irn;
}

694
ir_node *be_new_Start(dbg_info *dbgi, ir_node *bl, int n_outs)
Sebastian Hack's avatar
Sebastian Hack committed
695
{
696
697
	ir_node *res;
	int i;
698
	ir_graph *irg = get_Block_irg(bl);
699
	be_node_attr_t *attr;
Sebastian Hack's avatar
Sebastian Hack committed
700

701
	res = new_ir_node(dbgi, irg, bl, op_be_Start, mode_T, 0, NULL);
702
	init_node_attr(res, 0, -1);
703
704
	attr = (be_node_attr_t*) get_irn_generic_attr(res);
	attr->exc.pin_state = op_pin_state_pinned;
705
706
707
	for (i = 0; i < n_outs; ++i) {
		add_register_req_out(res);
	}
708
709
710
711

	return res;
}

712
ir_node *be_new_FrameAddr(const arch_register_class_t *cls_frame, ir_node *bl, ir_node *frame, ir_entity *ent)
Sebastian Hack's avatar
Sebastian Hack committed
713
{
714
	be_frame_attr_t *a;
Sebastian Hack's avatar
Sebastian Hack committed
715
716
	ir_node *irn;
	ir_node *in[1];
717
	ir_graph *irg = get_Block_irg(bl);
Sebastian Hack's avatar
Sebastian Hack committed
718

719
	in[0]  = frame;
720
	irn    = new_ir_node(NULL, irg, bl, op_be_FrameAddr, get_irn_mode(frame), 1, in);
721
	init_node_attr(irn, 1, 1);
722
723
724
725
	a                     = (be_frame_attr_t*)get_irn_generic_attr(irn);
	a->ent                = ent;
	a->offset             = 0;
	a->base.exc.pin_state = op_pin_state_floats;
726
727
	be_node_set_reg_class_in(irn, 0, cls_frame);
	be_node_set_reg_class_out(irn, 0, cls_frame);
Michael Beck's avatar
Michael Beck committed
728
729

	return optimize_node(irn);
Sebastian Hack's avatar
Sebastian Hack committed
730
731
}

732
733
ir_node *be_get_FrameAddr_frame(const ir_node *node)
{
Michael Beck's avatar
Michael Beck committed
734
735
736
737
	assert(be_is_FrameAddr(node));
	return get_irn_n(node, be_pos_FrameAddr_ptr);
}

Matthias Braun's avatar
Matthias Braun committed
738
739
ir_entity *be_get_FrameAddr_entity(const ir_node *node)
{
740
	const be_frame_attr_t *attr = (const be_frame_attr_t*)get_irn_generic_attr_const(node);
Matthias Braun's avatar
Matthias Braun committed
741
742
743
	return attr->ent;
}

744
ir_node *be_new_CopyKeep(const arch_register_class_t *cls, ir_node *bl, ir_node *src, int n, ir_node *in_keep[], ir_mode *mode)
Sebastian Hack's avatar
Sebastian Hack committed
745
{
746
747
	ir_node  *irn;
	ir_node **in = ALLOCAN(ir_node*, n + 1);
748
	ir_graph *irg = get_Block_irg(bl);
749
	be_node_attr_t *attr;
Sebastian Hack's avatar
Sebastian Hack committed
750
751
752
753

	in[0] = src;
	memcpy(&in[1], in_keep, n * sizeof(in[0]));
	irn   = new_ir_node(NULL, irg, bl, op_be_CopyKeep, mode, n + 1, in);
754
	init_node_attr(irn, n + 1, 1);
755
756
	attr = (be_node_attr_t*) get_irn_generic_attr(irn);
	attr->exc.pin_state = op_pin_state_floats;
757
758
	be_node_set_reg_class_in(irn, 0, cls);
	be_node_set_reg_class_out(irn, 0, cls);
Sebastian Hack's avatar
Sebastian Hack committed
759
760
761
762

	return irn;
}

763
ir_node *be_new_CopyKeep_single(const arch_register_class_t *cls, ir_node *bl, ir_node *src, ir_node *keep, ir_mode *mode)
Sebastian Hack's avatar
Sebastian Hack committed
764
{
765
	return be_new_CopyKeep(cls, bl, src, 1, &keep, mode);
Sebastian Hack's avatar
Sebastian Hack committed
766
767
}

768
769
ir_node *be_get_CopyKeep_op(const ir_node *cpy)
{
770
771
772
	return get_irn_n(cpy, be_pos_CopyKeep_op);
}

773
774
void be_set_CopyKeep_op(ir_node *cpy, ir_node *op)
{
775
776
777
	set_irn_n(cpy, be_pos_CopyKeep_op, op);
}

778
static bool be_has_frame_entity(const ir_node *irn)
779
{
780
	switch (get_irn_opcode(irn)) {
781
	case beo_Spill:
782
	case beo_Reload:
783
	case beo_FrameAddr:
784
		return true;
785
	default:
786
		return false;
787
788
789
	}
}

790
ir_entity *be_get_frame_entity(const ir_node *irn)
791
{
792
	if (be_has_frame_entity(irn)) {
793
		const be_frame_attr_t *a = (const be_frame_attr_t*)get_irn_generic_attr_const(irn);
794
795
796
797
		return a->ent;
	}
	return NULL;
}
Sebastian Hack's avatar
Sebastian Hack committed
798

799
800
801
802
int be_get_frame_offset(const ir_node *irn)
{
	assert(is_be_node(irn));
	if (be_has_frame_entity(irn)) {
803
		const be_frame_attr_t *a = (const be_frame_attr_t*)get_irn_generic_attr_const(irn);
804
805
806
807
808
		return a->offset;
	}
	return 0;
}

809
void be_set_MemPerm_in_entity(const ir_node *irn, int n, ir_entity *ent)
Matthias Braun's avatar
Matthias Braun committed
810
{
811
<