irnode.c 44.3 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
/*
Michael Beck's avatar
Michael Beck committed
2
 * Copyright (C) 1995-2008 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.
 */

Matthias Braun's avatar
Matthias Braun committed
20
21
22
23
24
/**
 * @file
 * @brief   Representation of an intermediate operation.
 * @author  Martin Trapp, Christian Schaefer, Goetz Lindenmaier, Michael Beck
 * @version $Id$
Götz Lindenmaier's avatar
Götz Lindenmaier committed
25
 */
Matthias Braun's avatar
Matthias Braun committed
26
#include "config.h"
Michael Beck's avatar
Michael Beck committed
27

28
#include <string.h>
Boris Boesler's avatar
added    
Boris Boesler committed
29

30
#include "pset_new.h"
31
#include "ident.h"
Götz Lindenmaier's avatar
Götz Lindenmaier committed
32
#include "irnode_t.h"
Götz Lindenmaier's avatar
Götz Lindenmaier committed
33
#include "irgraph_t.h"
Götz Lindenmaier's avatar
Götz Lindenmaier committed
34
#include "irmode_t.h"
35
#include "irbackedge_t.h"
36
#include "irdump.h"
37
#include "irop_t.h"
38
#include "irprog_t.h"
Sebastian Hack's avatar
Sebastian Hack committed
39
#include "iredgekinds.h"
Sebastian Hack's avatar
Sebastian Hack committed
40
#include "iredges_t.h"
Matthias Braun's avatar
Matthias Braun committed
41
#include "ircons.h"
42
#include "error.h"
Götz Lindenmaier's avatar
Götz Lindenmaier committed
43

44
#include "irhooks.h"
45
#include "irtools.h"
Michael Beck's avatar
Michael Beck committed
46

47
48
#include "beinfo.h"

Götz Lindenmaier's avatar
Götz Lindenmaier committed
49
50
/* some constants fixing the positions of nodes predecessors
   in the in array */
Michael Beck's avatar
Michael Beck committed
51
#define CALL_PARAM_OFFSET     2
52
#define BUILDIN_PARAM_OFFSET  1
Michael Beck's avatar
Michael Beck committed
53
54
55
#define SEL_INDEX_OFFSET      2
#define RETURN_RESULT_OFFSET  1  /* mem is not a result */
#define END_KEEPALIVE_OFFSET  0
Götz Lindenmaier's avatar
Götz Lindenmaier committed
56

57
static const char *pnc_name_arr [] = {
58
59
60
61
	"pn_Cmp_False", "pn_Cmp_Eq", "pn_Cmp_Lt", "pn_Cmp_Le",
	"pn_Cmp_Gt", "pn_Cmp_Ge", "pn_Cmp_Lg", "pn_Cmp_Leg",
	"pn_Cmp_Uo", "pn_Cmp_Ue", "pn_Cmp_Ul", "pn_Cmp_Ule",
	"pn_Cmp_Ug", "pn_Cmp_Uge", "pn_Cmp_Ne", "pn_Cmp_True"
62
};
Christian Schäfer's avatar
Christian Schäfer committed
63

Michael Beck's avatar
Michael Beck committed
64
65
66
/**
 * returns the pnc name from an pnc constant
 */
67
68
const char *get_pnc_string(int pnc)
{
69
70
	assert(pnc >= 0 && pnc <
			(int) (sizeof(pnc_name_arr)/sizeof(pnc_name_arr[0])));
71
	return pnc_name_arr[pnc];
Christian Schäfer's avatar
Christian Schäfer committed
72
73
}

Michael Beck's avatar
Michael Beck committed
74
/*
75
 * Calculates the negated (Complement(R)) pnc condition.
Michael Beck's avatar
Michael Beck committed
76
 */
77
78
pn_Cmp get_negated_pnc(long pnc, ir_mode *mode)
{
79
	pnc ^= pn_Cmp_True;
80

81
82
83
	/* do NOT add the Uo bit for non-floating point values */
	if (! mode_is_float(mode))
		pnc &= ~pn_Cmp_Uo;
84

85
	return (pn_Cmp) pnc;
Christian Schäfer's avatar
Christian Schäfer committed
86
87
}

88
/* Calculates the inversed (R^-1) pnc condition, i.e., "<" --> ">" */
89
90
pn_Cmp get_inversed_pnc(long pnc)
{
91
92
93
	long code    = pnc & ~(pn_Cmp_Lt|pn_Cmp_Gt);
	long lesser  = pnc & pn_Cmp_Lt;
	long greater = pnc & pn_Cmp_Gt;
Michael Beck's avatar
Michael Beck committed
94

95
	code |= (lesser ? pn_Cmp_Gt : 0) | (greater ? pn_Cmp_Lt : 0);
Michael Beck's avatar
Michael Beck committed
96

97
	return (pn_Cmp) code;
Michael Beck's avatar
Michael Beck committed
98
99
}

100
101
102
103
104
105
106
107
108
109
/**
 * Indicates, whether additional data can be registered to ir nodes.
 * If set to 1, this is not possible anymore.
 */
static int forbid_new_data = 0;

/**
 * The amount of additional space for custom data to be allocated upon
 * creating a new node.
 */
110
unsigned firm_add_node_size = 0;
111
112


113
/* register new space for every node */
114
115
unsigned firm_register_additional_node_data(unsigned size)
{
116
	assert(!forbid_new_data && "Too late to register additional node data");
117

118
119
	if (forbid_new_data)
		return 0;
120

121
	return firm_add_node_size += size;
122
123
124
}


125
126
void init_irnode(void)
{
127
128
	/* Forbid the addition of new data to an ir node. */
	forbid_new_data = 1;
Christian Schäfer's avatar
Christian Schäfer committed
129
130
}

131
132
133
134
135
136
137
138
139
struct struct_align {
	char c;
	struct s {
		int i;
		float f;
		double d;
	} s;
};

140
/*
141
142
143
 * irnode constructor.
 * Create a new irnode in irg, with an op, mode, arity and
 * some incoming irnodes.
144
145
 * If arity is negative, a node with a dynamic array is created.
 */
146
147
ir_node *new_ir_node(dbg_info *db, ir_graph *irg, ir_node *block, ir_op *op,
                     ir_mode *mode, int arity, ir_node **in)
Christian Schäfer's avatar
Christian Schäfer committed
148
{
149
	ir_node *res;
150
151
152
	unsigned align = offsetof(struct struct_align, s) - 1;
	unsigned add_node_size = (firm_add_node_size + align) & ~align;
	size_t node_size = offsetof(ir_node, attr) + op->attr_size + add_node_size;
153
	char *p;
154
	int i;
155

Christoph Mallon's avatar
Christoph Mallon committed
156
157
158
	assert(irg);
	assert(op);
	assert(mode);
159
	p = obstack_alloc(irg->obst, node_size);
160
	memset(p, 0, node_size);
161
	res = (ir_node *)(p + add_node_size);
162
163
164
165
166
167
168
169
170
171

	res->kind     = k_ir_node;
	res->op       = op;
	res->mode     = mode;
	res->visited  = 0;
	res->node_idx = irg_register_node_idx(irg, res);
	res->link     = NULL;
	res->deps     = NULL;

	if (arity < 0) {
172
		res->in = NEW_ARR_F(ir_node *, 1);  /* 1: space for block */
173
	} else {
174
175
		/* not nice but necessary: End and Sync must always have a flexible array */
		if (op == op_End || op == op_Sync)
176
177
178
			res->in = NEW_ARR_F(ir_node *, (arity+1));
		else
			res->in = NEW_ARR_D(ir_node *, irg->obst, (arity+1));
179
		memcpy(&res->in[1], in, sizeof(ir_node *) * arity);
180
181
	}

182
	res->in[0]   = block;
183
	set_irn_dbg_info(res, db);
184
	res->out     = NULL;
185
	res->node_nr = get_irp_new_node_nr();
Götz Lindenmaier's avatar
Götz Lindenmaier committed
186

Michael Beck's avatar
Michael Beck committed
187
	for (i = 0; i < EDGE_KIND_LAST; ++i) {
188
		INIT_LIST_HEAD(&res->edge_info[i].outs_head);
Michael Beck's avatar
Michael Beck committed
189
190
191
192
		/* edges will be build immediately */
		res->edge_info[i].edges_built = 1;
		res->edge_info[i].out_count = 0;
	}
193

194
	/* don't put this into the for loop, arity is -1 for some nodes! */
195
196
	edges_notify_edge(res, -1, res->in[0], NULL, irg);
	for (i = 1; i <= arity; ++i)
197
		edges_notify_edge(res, i - 1, res->in[i], NULL, irg);
Sebastian Hack's avatar
Sebastian Hack committed
198

199
	hook_new_node(irg, res);
200
201
202
	if (get_irg_phase_state(irg) == phase_backend) {
		be_info_new_node(res);
	}
Michael Beck's avatar
Michael Beck committed
203

204
	return res;
Christian Schäfer's avatar
Christian Schäfer committed
205
206
}

Michael Beck's avatar
Michael Beck committed
207
/*-- getting some parameters from ir_nodes --*/
Christian Schäfer's avatar
Christian Schäfer committed
208

209
210
int (is_ir_node)(const void *thing)
{
211
	return _is_ir_node(thing);
Sebastian Felis's avatar
Sebastian Felis committed
212
213
}

214
215
int (get_irn_arity)(const ir_node *node)
{
216
	return _get_irn_arity(node);
217
218
}

219
220
221
222
223
224
/* Returns the array with ins. This array is shifted with respect to the
   array accessed by get_irn_n: The block operand is at position 0 not -1.
   (@@@ This should be changed.)
   The order of the predecessors in this array is not guaranteed, except that
   lists of operands as predecessors of Block or arguments of a Call are
   consecutive. */
225
226
ir_node **get_irn_in(const ir_node *node)
{
227
228
229
	return node->in;
}

230
231
void set_irn_in(ir_node *node, int arity, ir_node **in)
{
232
	int i;
Michael Beck's avatar
Michael Beck committed
233
	ir_node *** pOld_in;
234
	ir_graph *irg = get_irn_irg(node);
235

236
	pOld_in = &node->in;
237

238
239

	for (i = 0; i < arity; i++) {
Michael Beck's avatar
Michael Beck committed
240
241
		if (i < ARR_LEN(*pOld_in)-1)
			edges_notify_edge(node, i, in[i], (*pOld_in)[i+1], irg);
242
		else
Michael Beck's avatar
Michael Beck committed
243
			edges_notify_edge(node, i, in[i], NULL,            irg);
244
	}
Michael Beck's avatar
Michael Beck committed
245
246
	for (;i < ARR_LEN(*pOld_in)-1; i++) {
		edges_notify_edge(node, i, NULL, (*pOld_in)[i+1], irg);
247
248
	}

Michael Beck's avatar
Michael Beck committed
249
250
251
252
	if (arity != ARR_LEN(*pOld_in) - 1) {
		ir_node * block = (*pOld_in)[0];
		*pOld_in = NEW_ARR_D(ir_node *, irg->obst, arity + 1);
		(*pOld_in)[0] = block;
253
254
255
	}
	fix_backedges(irg->obst, node);

Michael Beck's avatar
Michael Beck committed
256
	memcpy((*pOld_in) + 1, in, sizeof(ir_node *) * arity);
257
258
}

259
260
ir_node *(get_irn_n)(const ir_node *node, int n)
{
261
	return _get_irn_n(node, n);
Christian Schäfer's avatar
Christian Schäfer committed
262
263
}

264
265
void set_irn_n(ir_node *node, int n, ir_node *in)
{
266
267
268
269
270
271
272
273
274
275
276
277
	assert(node && node->kind == k_ir_node);
	assert(-1 <= n);
	assert(n < get_irn_arity(node));
	assert(in && in->kind == k_ir_node);

	/* Call the hook */
	hook_set_irn_n(node, n, in, node->in[n + 1]);

	/* Here, we rely on src and tgt being in the current ir graph */
	edges_notify_edge(node, n, in, node->in[n + 1], current_ir_graph);

	node->in[n + 1] = in;
Christian Schäfer's avatar
Christian Schäfer committed
278
279
}

280
281
int add_irn_n(ir_node *node, ir_node *in)
{
282
283
284
285
286
287
288
289
	int pos;
	ir_graph *irg = get_irn_irg(node);

	assert(node->op->opar == oparity_dynamic);
	pos = ARR_LEN(node->in) - 1;
	ARR_APP1(ir_node *, node->in, in);
	edges_notify_edge(node, pos, node->in[pos + 1], NULL, irg);

290
291
292
	/* Call the hook */
	hook_set_irn_n(node, pos, node->in[pos + 1], NULL);

293
294
295
	return pos;
}

Christoph Mallon's avatar
Christoph Mallon committed
296
297
298
299
300
301
302
303
304
void del_Sync_n(ir_node *n, int i)
{
	int      arity     = get_Sync_n_preds(n);
	ir_node *last_pred = get_Sync_pred(n, arity - 1);
	set_Sync_pred(n, i, last_pred);
	edges_notify_edge(n, arity - 1, NULL, last_pred, get_irn_irg(n));
	ARR_SHRINKLEN(get_irn_in(n), arity);
}

305
306
int (get_irn_deps)(const ir_node *node)
{
Sebastian Hack's avatar
Sebastian Hack committed
307
308
309
	return _get_irn_deps(node);
}

310
311
ir_node *(get_irn_dep)(const ir_node *node, int pos)
{
Sebastian Hack's avatar
Sebastian Hack committed
312
313
314
	return _get_irn_dep(node, pos);
}

315
316
void (set_irn_dep)(ir_node *node, int pos, ir_node *dep)
{
Sebastian Hack's avatar
Sebastian Hack committed
317
318
319
	_set_irn_dep(node, pos, dep);
}

320
321
int add_irn_dep(ir_node *node, ir_node *dep)
{
Sebastian Hack's avatar
Sebastian Hack committed
322
323
	int res = 0;

324
325
	/* DEP edges are only allowed in backend phase */
	assert(get_irg_phase_state(get_irn_irg(node)) == phase_backend);
Sebastian Hack's avatar
Sebastian Hack committed
326
327
328
	if (node->deps == NULL) {
		node->deps = NEW_ARR_F(ir_node *, 1);
		node->deps[0] = dep;
329
	} else {
Sebastian Hack's avatar
Sebastian Hack committed
330
331
332
		int i, n;
		int first_zero = -1;

333
334
		for (i = 0, n = ARR_LEN(node->deps); i < n; ++i) {
			if (node->deps[i] == NULL)
Sebastian Hack's avatar
Sebastian Hack committed
335
336
				first_zero = i;

337
			if (node->deps[i] == dep)
Sebastian Hack's avatar
Sebastian Hack committed
338
339
340
				return i;
		}

341
		if (first_zero >= 0) {
Sebastian Hack's avatar
Sebastian Hack committed
342
343
			node->deps[first_zero] = dep;
			res = first_zero;
344
		} else {
Sebastian Hack's avatar
Sebastian Hack committed
345
346
347
348
349
350
351
352
353
354
			ARR_APP1(ir_node *, node->deps, dep);
			res = n;
		}
	}

	edges_notify_edge_kind(node, res, dep, NULL, EDGE_KIND_DEP, get_irn_irg(node));

	return res;
}

355
356
void add_irn_deps(ir_node *tgt, ir_node *src)
{
Sebastian Hack's avatar
Sebastian Hack committed
357
358
	int i, n;

359
	for (i = 0, n = get_irn_deps(src); i < n; ++i)
Sebastian Hack's avatar
Sebastian Hack committed
360
361
362
363
		add_irn_dep(tgt, get_irn_dep(src, i));
}


364
365
ir_mode *(get_irn_mode)(const ir_node *node)
{
366
	return _get_irn_mode(node);
Christian Schäfer's avatar
Christian Schäfer committed
367
368
}

369
370
void (set_irn_mode)(ir_node *node, ir_mode *mode)
{
371
	_set_irn_mode(node, mode);
Till Riedel's avatar
Till Riedel committed
372
373
}

374
/** Gets the string representation of the mode .*/
375
376
const char *get_irn_modename(const ir_node *node)
{
377
378
	assert(node);
	return get_mode_name(node->mode);
379
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
380

381
382
ident *get_irn_modeident(const ir_node *node)
{
383
384
	assert(node);
	return get_mode_ident(node->mode);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
385
386
}

387
388
ir_op *(get_irn_op)(const ir_node *node)
{
389
	return _get_irn_op(node);
Christian Schäfer's avatar
Christian Schäfer committed
390
391
392
}

/* should be private to the library: */
393
394
void (set_irn_op)(ir_node *node, ir_op *op)
{
395
	_set_irn_op(node, op);
Christian Schäfer's avatar
Christian Schäfer committed
396
397
}

398
399
unsigned (get_irn_opcode)(const ir_node *node)
{
400
	return _get_irn_opcode(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
401
402
}

403
404
const char *get_irn_opname(const ir_node *node)
{
405
	assert(node);
406
	if (is_Phi0(node)) return "Phi0";
407
	return get_id_str(node->op->name);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
408
409
}

410
411
ident *get_irn_opident(const ir_node *node)
{
412
413
	assert(node);
	return node->op->name;
414
415
}

416
417
ir_visited_t (get_irn_visited)(const ir_node *node)
{
418
	return _get_irn_visited(node);
419
420
}

421
422
void (set_irn_visited)(ir_node *node, ir_visited_t visited)
{
423
	_set_irn_visited(node, visited);
Christian Schäfer's avatar
Christian Schäfer committed
424
}
425

426
427
void (mark_irn_visited)(ir_node *node)
{
428
	_mark_irn_visited(node);
429
430
}

431
432
int (irn_visited)(const ir_node *node)
{
433
	return _irn_visited(node);
434
435
}

436
437
int (irn_visited_else_mark)(ir_node *node)
{
438
439
440
	return _irn_visited_else_mark(node);
}

441
442
void (set_irn_link)(ir_node *node, void *link)
{
443
	_set_irn_link(node, link);
Christian Schäfer's avatar
Christian Schäfer committed
444
445
}

446
447
void *(get_irn_link)(const ir_node *node)
{
448
	return _get_irn_link(node);
Christian Schäfer's avatar
Christian Schäfer committed
449
450
}

451
452
op_pin_state (get_irn_pinned)(const ir_node *node)
{
453
	return _get_irn_pinned(node);
454
455
}

456
457
op_pin_state (is_irn_pinned_in_irg) (const ir_node *node)
{
458
	return _is_irn_pinned_in_irg(node);
459
460
}

461
462
void set_irn_pinned(ir_node *node, op_pin_state state)
{
463
	/* due to optimization an opt may be turned into a Tuple */
464
	if (is_Tuple(node))
465
		return;
Michael Beck's avatar
Michael Beck committed
466

467
468
	assert(node && get_op_pinned(get_irn_op(node)) >= op_pin_state_exc_pinned);
	assert(state == op_pin_state_pinned || state == op_pin_state_floats);
Michael Beck's avatar
Michael Beck committed
469

470
	node->attr.except.pin_state = state;
Michael Beck's avatar
Michael Beck committed
471
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
472

Götz Lindenmaier's avatar
Götz Lindenmaier committed
473
/* Outputs a unique number for this node */
474
475
long get_irn_node_nr(const ir_node *node)
{
476
477
	assert(node);
	return node->node_nr;
478
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
479

480
481
void *(get_irn_generic_attr)(ir_node *node)
{
482
483
	assert(is_ir_node(node));
	return _get_irn_generic_attr(node);
484
485
}

486
487
const void *(get_irn_generic_attr_const)(const ir_node *node)
{
488
489
490
491
	assert(is_ir_node(node));
	return _get_irn_generic_attr_const(node);
}

492
493
unsigned (get_irn_idx)(const ir_node *node)
{
494
495
	assert(is_ir_node(node));
	return _get_irn_idx(node);
496
497
}

498
499
int get_irn_pred_pos(ir_node *node, ir_node *arg)
{
500
501
502
503
504
505
	int i;
	for (i = get_irn_arity(node) - 1; i >= 0; i--) {
		if (get_irn_n(node, i) == arg)
			return i;
	}
	return -1;
506
507
}

Christian Schäfer's avatar
Christian Schäfer committed
508
509
/** manipulate fields of individual nodes **/

510
/* this works for all except Block */
511
512
ir_node *get_nodes_block(const ir_node *node)
{
513
514
	assert(node->op != op_Block);
	return get_irn_n(node, -1);
Christian Schäfer's avatar
Christian Schäfer committed
515
516
}

517
518
void set_nodes_block(ir_node *node, ir_node *block)
{
519
520
	assert(node->op != op_Block);
	set_irn_n(node, -1, block);
Christian Schäfer's avatar
Christian Schäfer committed
521
522
}

Michael Beck's avatar
Michael Beck committed
523
/* this works for all except Block */
524
525
ir_node *get_nodes_MacroBlock(const ir_node *node)
{
Michael Beck's avatar
Michael Beck committed
526
527
528
529
	assert(node->op != op_Block);
	return get_Block_MacroBlock(get_irn_n(node, -1));
}

530
531
/* Test whether arbitrary node is frame pointer, i.e. Proj(pn_Start_P_frame_base)
 * from Start.  If so returns frame type, else Null. */
532
533
ir_type *is_frame_pointer(const ir_node *n)
{
534
535
	if (is_Proj(n) && (get_Proj_proj(n) == pn_Start_P_frame_base)) {
		ir_node *start = get_Proj_pred(n);
536
		if (is_Start(start)) {
537
538
539
540
			return get_irg_frame_type(get_irn_irg(start));
		}
	}
	return NULL;
541
542
}

543
544
/* Test whether arbitrary node is tls pointer, i.e. Proj(pn_Start_P_tls)
 * from Start.  If so returns tls type, else Null. */
545
546
ir_type *is_tls_pointer(const ir_node *n)
{
547
	if (is_Proj(n) && (get_Proj_proj(n) == pn_Start_P_tls)) {
548
		ir_node *start = get_Proj_pred(n);
549
		if (is_Start(start)) {
550
551
552
553
			return get_tls_type();
		}
	}
	return NULL;
554
555
}

556
557
ir_node **get_Block_cfgpred_arr(ir_node *node)
{
558
	assert(is_Block(node));
559
	return (ir_node **)&(get_irn_in(node)[1]);
560
561
}

562
563
int (get_Block_n_cfgpreds)(const ir_node *node)
{
564
	return _get_Block_n_cfgpreds(node);
Christian Schäfer's avatar
Christian Schäfer committed
565
566
}

567
568
ir_node *(get_Block_cfgpred)(const ir_node *node, int pos)
{
569
	return _get_Block_cfgpred(node, pos);
Christian Schäfer's avatar
Christian Schäfer committed
570
571
}

572
573
void set_Block_cfgpred(ir_node *node, int pos, ir_node *pred)
{
574
	assert(is_Block(node));
575
	set_irn_n(node, pos, pred);
Christian Schäfer's avatar
Christian Schäfer committed
576
577
}

578
579
int get_Block_cfgpred_pos(const ir_node *block, const ir_node *pred)
{
580
581
582
583
584
585
586
587
588
	int i;

	for (i = get_Block_n_cfgpreds(block) - 1; i >= 0; --i) {
		if (get_Block_cfgpred_block(block, i) == pred)
			return i;
	}
	return -1;
}

589
590
ir_node *(get_Block_cfgpred_block)(const ir_node *node, int pos)
{
591
	return _get_Block_cfgpred_block(node, pos);
592
593
}

594
595
int get_Block_matured(const ir_node *node)
{
596
	assert(is_Block(node));
Michael Beck's avatar
Michael Beck committed
597
	return (int)node->attr.block.is_matured;
Christian Schäfer's avatar
Christian Schäfer committed
598
599
}

600
601
void set_Block_matured(ir_node *node, int matured)
{
602
	assert(is_Block(node));
Michael Beck's avatar
Michael Beck committed
603
	node->attr.block.is_matured = matured;
Christian Schäfer's avatar
Christian Schäfer committed
604
}
Michael Beck's avatar
Michael Beck committed
605

606
607
ir_visited_t (get_Block_block_visited)(const ir_node *node)
{
608
	return _get_Block_block_visited(node);
Christian Schäfer's avatar
Christian Schäfer committed
609
610
}

611
612
void (set_Block_block_visited)(ir_node *node, ir_visited_t visit)
{
613
	_set_Block_block_visited(node, visit);
Christian Schäfer's avatar
Christian Schäfer committed
614
615
}

Götz Lindenmaier's avatar
Götz Lindenmaier committed
616
/* For this current_ir_graph must be set. */
617
618
void (mark_Block_block_visited)(ir_node *node)
{
619
	_mark_Block_block_visited(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
620
621
}

622
623
int (Block_block_visited)(const ir_node *node)
{
Matthias Braun's avatar
Matthias Braun committed
624
625
626
	return _Block_block_visited(node);
}

627
628
ir_node *(set_Block_dead)(ir_node *block)
{
629
	return _set_Block_dead(block);
630
631
}

632
633
int (is_Block_dead)(const ir_node *block)
{
634
	return _is_Block_dead(block);
635
636
}

637
638
ir_extblk *get_Block_extbb(const ir_node *block)
{
Michael Beck's avatar
Michael Beck committed
639
	ir_extblk *res;
640
	assert(is_Block(block));
Michael Beck's avatar
Michael Beck committed
641
642
	res = block->attr.block.extblk;
	assert(res == NULL || is_ir_extbb(res));
643
	return res;
644
645
}

646
647
void set_Block_extbb(ir_node *block, ir_extblk *extblk)
{
648
	assert(is_Block(block));
Michael Beck's avatar
Michael Beck committed
649
	assert(extblk == NULL || is_ir_extbb(extblk));
650
	block->attr.block.extblk = extblk;
651
652
}

Michael Beck's avatar
Michael Beck committed
653
/* Returns the macro block header of a block.*/
654
655
ir_node *get_Block_MacroBlock(const ir_node *block)
{
656
	ir_node *mbh;
Michael Beck's avatar
Michael Beck committed
657
	assert(is_Block(block));
658
659
660
661
662
	mbh = get_irn_n(block, -1);
	/* once macro block header is respected by all optimizations,
	   this assert can be removed */
	assert(mbh != NULL);
	return mbh;
Michael Beck's avatar
Michael Beck committed
663
664
}

Michael Beck's avatar
Michael Beck committed
665
/* Sets the macro block header of a block. */
666
667
void set_Block_MacroBlock(ir_node *block, ir_node *mbh)
{
Michael Beck's avatar
Michael Beck committed
668
	assert(is_Block(block));
669
	mbh = skip_Id(mbh);
Michael Beck's avatar
Michael Beck committed
670
671
672
673
	assert(is_Block(mbh));
	set_irn_n(block, -1, mbh);
}

Michael Beck's avatar
Michael Beck committed
674
/* returns the macro block header of a node. */
675
676
ir_node *get_irn_MacroBlock(const ir_node *n)
{
677
	if (! is_Block(n)) {
Michael Beck's avatar
Michael Beck committed
678
		n = get_nodes_block(n);
679
680
		/* if the Block is Bad, do NOT try to get it's MB, it will fail. */
		if (is_Bad(n))
681
			return (ir_node *)n;
682
	}
Michael Beck's avatar
Michael Beck committed
683
684
685
	return get_Block_MacroBlock(n);
}

686
/* returns the graph of a Block. */
687
688
ir_graph *(get_Block_irg)(const ir_node *block)
{
689
	return _get_Block_irg(block);
690
691
}

692
693
ir_entity *create_Block_entity(ir_node *block)
{
694
	ir_entity *entity;
Michael Beck's avatar
Michael Beck committed
695
	assert(is_Block(block));
696
697
698
699
700
701
702
703

	entity = block->attr.block.entity;
	if (entity == NULL) {
		ir_label_t  nr;
		ir_type   *glob;

		glob = get_glob_type();
		entity = new_entity(glob, id_unique("block_%u"), get_code_type());
704
705
		set_entity_visibility(entity, ir_visibility_local);
		set_entity_linkage(entity, IR_LINKAGE_CONSTANT);
706
707
708
709
710
711
712
		nr = get_irp_next_label_nr();
		set_entity_label(entity, nr);
		set_entity_compiler_generated(entity, 1);

		block->attr.block.entity = entity;
	}
	return entity;
Michael Beck's avatar
Michael Beck committed
713
714
}

715
716
ir_entity *get_Block_entity(const ir_node *block)
{
Michael Beck's avatar
Michael Beck committed
717
	assert(is_Block(block));
718
	return block->attr.block.entity;
Michael Beck's avatar
Michael Beck committed
719
720
}

721
722
void set_Block_entity(ir_node *block, ir_entity *entity)
{
Michael Beck's avatar
Michael Beck committed
723
	assert(is_Block(block));
724
725
726
727
728
729
730
	assert(get_entity_type(entity) == get_code_type());
	block->attr.block.entity = entity;
}

int has_Block_entity(const ir_node *block)
{
	return block->attr.block.entity != NULL;
Michael Beck's avatar
Michael Beck committed
731
732
}

733
734
ir_node *(get_Block_phis)(const ir_node *block)
{
735
736
737
	return _get_Block_phis(block);
}

738
739
void (set_Block_phis)(ir_node *block, ir_node *phi)
{
740
741
742
	_set_Block_phis(block, phi);
}

743
744
void (add_Block_phi)(ir_node *block, ir_node *phi)
{
Michael Beck's avatar
Michael Beck committed
745
746
747
748
	_add_Block_phi(block, phi);
}

/* Get the Block mark (single bit). */
749
750
unsigned (get_Block_mark)(const ir_node *block)
{
Michael Beck's avatar
Michael Beck committed
751
752
753
754
	return _get_Block_mark(block);
}

/* Set the Block mark (single bit). */
755
756
void (set_Block_mark)(ir_node *block, unsigned mark)
{
Michael Beck's avatar
Michael Beck committed
757
758
759
	_set_Block_mark(block, mark);
}

760
761
int get_End_n_keepalives(const ir_node *end)
{
762
	assert(is_End(end));
763
	return (get_irn_arity(end) - END_KEEPALIVE_OFFSET);
764
765
}

766
767
ir_node *get_End_keepalive(const ir_node *end, int pos)
{
768
	assert(is_End(end));
769
	return get_irn_n(end, pos + END_KEEPALIVE_OFFSET);
770
771
}

772
773
void add_End_keepalive(ir_node *end, ir_node *ka)
{
774
	assert(is_End(end));
775
	add_irn_n(end, ka);
776
777
}

778
779
void set_End_keepalive(ir_node *end, int pos, ir_node *ka)
{
780
	assert(is_End(end));
781
	set_irn_n(end, pos + END_KEEPALIVE_OFFSET, ka);
782
783
}

784
/* Set new keep-alives */
785
786
void set_End_keepalives(ir_node *end, int n, ir_node *in[])
{
787
788
	int i;
	ir_graph *irg = get_irn_irg(end);
789

790
	/* notify that edges are deleted */
791
792
	for (i = END_KEEPALIVE_OFFSET; i < ARR_LEN(end->in) - 1; ++i) {
		edges_notify_edge(end, i, NULL, end->in[i + 1], irg);
793
794
	}
	ARR_RESIZE(ir_node *, end->in, n + 1 + END_KEEPALIVE_OFFSET);
795

796
797
	for (i = 0; i < n; ++i) {
		end->in[1 + END_KEEPALIVE_OFFSET + i] = in[i];
798
		edges_notify_edge(end, END_KEEPALIVE_OFFSET + i, end->in[1 + END_KEEPALIVE_OFFSET + i], NULL, irg);
799
	}
800
}
801

802
/* Set new keep-alives from old keep-alives, skipping irn */
803
804
void remove_End_keepalive(ir_node *end, ir_node *irn)
{
805
806
807
808
809
810
811
812
813
814
815
816
817
	int      n = get_End_n_keepalives(end);
	int      i, idx;
	ir_graph *irg;

	idx = -1;
	for (i = n -1; i >= 0; --i) {
		ir_node *old_ka = end->in[1 + END_KEEPALIVE_OFFSET + i];

		/* find irn */
		if (old_ka == irn) {
			idx = i;
			goto found;
		}
818
	}
819
820
821
822
823
824
825
826
827
828
829
830
831
832
	return;
found:
	irg = get_irn_irg(end);

	/* remove the edge */
	edges_notify_edge(end, idx, NULL, irn, irg);

	if (idx != n - 1) {
		/* exchange with the last one */
		ir_node *old = end->in[1 + END_KEEPALIVE_OFFSET + n - 1];
		edges_notify_edge(end, n - 1, NULL, old, irg);
		end->in[1 + END_KEEPALIVE_OFFSET + idx] = old;
		edges_notify_edge(end, idx, old, NULL, irg);
	}
833
	/* now n - 1 keeps, 1 block input */
834
	ARR_RESIZE(ir_node *, end->in, (n - 1) + 1 + END_KEEPALIVE_OFFSET);
835
}
836

Michael Beck's avatar
Michael Beck committed
837
/* remove Bads, NoMems and doublets from the keep-alive set */
838
839
void remove_End_Bads_and_doublets(ir_node *end)
{
840
841
842
843
844
845
846
847
848
849
850
851
852
	pset_new_t keeps;
	int        idx, n = get_End_n_keepalives(end);
	ir_graph   *irg;

	if (n <= 0)
		return;

	irg = get_irn_irg(end);
	pset_new_init(&keeps);

	for (idx = n - 1; idx >= 0; --idx) {
		ir_node *ka = get_End_keepalive(end, idx);

Michael Beck's avatar
Michael Beck committed
853
		if (is_Bad(ka) || is_NoMem(ka) || pset_new_contains(&keeps, ka)) {
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
			/* remove the edge */
			edges_notify_edge(end, idx, NULL, ka, irg);

			if (idx != n - 1) {
				/* exchange with the last one */
				ir_node *old = end->in[1 + END_KEEPALIVE_OFFSET + n - 1];
				edges_notify_edge(end, n - 1, NULL, old, irg);
				end->in[1 + END_KEEPALIVE_OFFSET + idx] = old;
				edges_notify_edge(end, idx, old, NULL, irg);
			}
			--n;
		} else {
			pset_new_insert(&keeps, ka);
		}
	}
	/* n keeps, 1 block input */
	ARR_RESIZE(ir_node *, end->in, n + 1 + END_KEEPALIVE_OFFSET);

	pset_new_destroy(&keeps);
}

875
876
void free_End(ir_node *end)
{
877
	assert(is_End(end));
878
879
880
881
	end->kind = k_BAD;
	DEL_ARR_F(end->in);
	end->in = NULL;   /* @@@ make sure we get an error if we use the
	                     in array afterwards ... */
882
883
}

884
int get_Return_n_ress(const ir_node *node)
885
{
886
	assert(is_Return(node));
887
	return (get_irn_arity(node) - RETURN_RESULT_OFFSET);
888
889
}

890
ir_node **get_Return_res_arr(ir_node *node)
891
{
892
	assert(is_Return(node));
893
894
895
896
	if (get_Return_n_ress(node) > 0)
		return (ir_node **)&(get_irn_in(node)[1 + RETURN_RESULT_OFFSET]);
	else
		return NULL;
897
898
}

Christian Schäfer's avatar
Christian Schäfer committed
899
/*
900
void set_Return_n_res(ir_node *node, int results)
901
{
902
	assert(is_Return(node));
Christian Schäfer's avatar
Christian Schäfer committed
903
904
905
}
*/

906
ir_node *get_Return_res(const ir_node *node, int pos)
907
{
908
	assert(is_Return(node));
909
910
	assert(get_Return_n_ress(node) > pos);
	return get_irn_n(node, pos + RETURN_RESULT_OFFSET);
Christian Schäfer's avatar
Christian Schäfer committed
911
912
}