irnode.c 39.4 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
/**
 * @file
 * @brief   Representation of an intermediate operation.
 * @author  Martin Trapp, Christian Schaefer, Goetz Lindenmaier, Michael Beck
Götz Lindenmaier's avatar
Götz Lindenmaier committed
24
 */
Matthias Braun's avatar
Matthias Braun committed
25
#include "config.h"
Michael Beck's avatar
Michael Beck committed
26

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

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

43
#include "irhooks.h"
44
#include "irtools.h"
45
#include "util.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 */
51
52
53
54
#define CALL_PARAM_OFFSET     (n_Call_max+1)
#define BUILTIN_PARAM_OFFSET  (n_Builtin_max+1)
#define SEL_INDEX_OFFSET      (n_Sel_max+1)
#define RETURN_RESULT_OFFSET  (n_Return_max+1)
Michael Beck's avatar
Michael Beck committed
55
#define END_KEEPALIVE_OFFSET  0
Götz Lindenmaier's avatar
Götz Lindenmaier committed
56

57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
static const char *relation_names [] = {
	"false",
	"equal",
	"less",
	"less_equal",
	"greater",
	"greater_equal",
	"less_greater",
	"less_equal_greater",
	"unordered",
	"unordered_equal",
	"unordered_less",
	"unordered_less_equal",
	"unordered_greater",
	"unordered_greater_equal",
	"not_equal",
	"true"
74
};
Christian Schäfer's avatar
Christian Schäfer committed
75

76
const char *get_relation_string(ir_relation relation)
77
{
78
79
	assert(relation < (ir_relation)ARRAY_SIZE(relation_names));
	return relation_names[relation];
Christian Schäfer's avatar
Christian Schäfer committed
80
81
}

82
ir_relation get_negated_relation(ir_relation relation)
83
{
84
	return relation ^ ir_relation_true;
Christian Schäfer's avatar
Christian Schäfer committed
85
86
}

87
ir_relation get_inversed_relation(ir_relation relation)
88
{
89
90
91
92
93
	ir_relation code    = relation & ~(ir_relation_less|ir_relation_greater);
	bool        less    = relation & ir_relation_less;
	bool        greater = relation & ir_relation_greater;
	code |= (less ? ir_relation_greater : 0) | (greater ? ir_relation_less : 0);
	return code;
Michael Beck's avatar
Michael Beck committed
94
95
}

96
97
98
99
100
101
102
103
104
105
/**
 * 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.
 */
106
unsigned firm_add_node_size = 0;
107
108


109
/* register new space for every node */
110
111
unsigned firm_register_additional_node_data(unsigned size)
{
112
	assert(!forbid_new_data && "Too late to register additional node data");
113

114
115
	if (forbid_new_data)
		return 0;
116

117
	return firm_add_node_size += size;
118
119
120
}


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

127
128
129
130
131
132
133
134
135
struct struct_align {
	char c;
	struct s {
		int i;
		float f;
		double d;
	} s;
};

136
/*
137
138
139
 * irnode constructor.
 * Create a new irnode in irg, with an op, mode, arity and
 * some incoming irnodes.
140
141
 * If arity is negative, a node with a dynamic array is created.
 */
142
ir_node *new_ir_node(dbg_info *db, ir_graph *irg, ir_node *block, ir_op *op,
143
                     ir_mode *mode, int arity, ir_node *const *in)
Christian Schäfer's avatar
Christian Schäfer committed
144
{
145
	ir_node *res;
146
147
148
	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;
149
	char *p;
150
	int i;
151

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

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

178
	res->in[0]   = block;
179
	set_irn_dbg_info(res, db);
180
	res->out     = NULL;
181
	res->node_nr = get_irp_new_node_nr();
Götz Lindenmaier's avatar
Götz Lindenmaier committed
182

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

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

195
	hook_new_node(irg, res);
196
197
198
	if (get_irg_phase_state(irg) == phase_backend) {
		be_info_new_node(res);
	}
Michael Beck's avatar
Michael Beck committed
199

200
	return res;
Christian Schäfer's avatar
Christian Schäfer committed
201
202
}

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

205
206
int (is_ir_node)(const void *thing)
{
207
	return is_ir_node_(thing);
Sebastian Felis's avatar
Sebastian Felis committed
208
209
}

210
211
int (get_irn_arity)(const ir_node *node)
{
212
	return get_irn_arity_(node);
213
214
}

215
216
217
218
219
220
/* 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. */
221
222
ir_node **get_irn_in(const ir_node *node)
{
223
224
225
	return node->in;
}

226
227
void set_irn_in(ir_node *node, int arity, ir_node **in)
{
228
	int i;
Michael Beck's avatar
Michael Beck committed
229
	ir_node *** pOld_in;
230
	ir_graph *irg = get_irn_irg(node);
231

232
	pOld_in = &node->in;
233

234
235
236
237
238
239
240
#ifndef NDEBUG
	assert(node != NULL && node->kind == k_ir_node);
	assert(arity >= 0);
	for (i = 0; i < arity; ++i) {
		assert(in[i] != NULL && in[0]->kind == k_ir_node);
	}
#endif
241
242

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

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

Michael Beck's avatar
Michael Beck committed
259
	memcpy((*pOld_in) + 1, in, sizeof(ir_node *) * arity);
260
261

	/* update irg flags */
262
	clear_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_OUTS | IR_GRAPH_STATE_CONSISTENT_LOOPINFO);
263
264
}

265
266
ir_node *(get_irn_n)(const ir_node *node, int n)
{
267
	return get_irn_n_(node, n);
Christian Schäfer's avatar
Christian Schäfer committed
268
269
}

270
271
void set_irn_n(ir_node *node, int n, ir_node *in)
{
272
	ir_graph *irg = get_irn_irg(node);
273
274
275
276
277
278
279
280
281
	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 */
282
	edges_notify_edge(node, n, in, node->in[n + 1], irg);
283
284

	node->in[n + 1] = in;
285
286

	/* update irg flags */
287
	clear_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_OUTS | IR_GRAPH_STATE_CONSISTENT_LOOPINFO);
Christian Schäfer's avatar
Christian Schäfer committed
288
289
}

290
291
int add_irn_n(ir_node *node, ir_node *in)
{
292
293
294
295
296
297
298
299
	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);

300
301
302
	/* Call the hook */
	hook_set_irn_n(node, pos, node->in[pos + 1], NULL);

303
304
305
	return pos;
}

Christoph Mallon's avatar
Christoph Mallon committed
306
307
308
309
310
311
312
313
314
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);
}

315
316
int (get_irn_deps)(const ir_node *node)
{
317
	return get_irn_deps_(node);
Sebastian Hack's avatar
Sebastian Hack committed
318
319
}

320
321
ir_node *(get_irn_dep)(const ir_node *node, int pos)
{
322
	return get_irn_dep_(node, pos);
Sebastian Hack's avatar
Sebastian Hack committed
323
324
}

325
326
void (set_irn_dep)(ir_node *node, int pos, ir_node *dep)
{
327
	set_irn_dep_(node, pos, dep);
Sebastian Hack's avatar
Sebastian Hack committed
328
329
}

330
331
int add_irn_dep(ir_node *node, ir_node *dep)
{
Sebastian Hack's avatar
Sebastian Hack committed
332
333
	int res = 0;

334
335
	/* 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
336
337
338
	if (node->deps == NULL) {
		node->deps = NEW_ARR_F(ir_node *, 1);
		node->deps[0] = dep;
339
	} else {
Sebastian Hack's avatar
Sebastian Hack committed
340
341
342
		int i, n;
		int first_zero = -1;

343
344
		for (i = 0, n = ARR_LEN(node->deps); i < n; ++i) {
			if (node->deps[i] == NULL)
Sebastian Hack's avatar
Sebastian Hack committed
345
346
				first_zero = i;

347
			if (node->deps[i] == dep)
Sebastian Hack's avatar
Sebastian Hack committed
348
349
350
				return i;
		}

351
		if (first_zero >= 0) {
Sebastian Hack's avatar
Sebastian Hack committed
352
353
			node->deps[first_zero] = dep;
			res = first_zero;
354
		} else {
Sebastian Hack's avatar
Sebastian Hack committed
355
356
357
358
359
360
361
362
363
364
			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;
}

365
366
void add_irn_deps(ir_node *tgt, ir_node *src)
{
Sebastian Hack's avatar
Sebastian Hack committed
367
368
	int i, n;

369
	for (i = 0, n = get_irn_deps(src); i < n; ++i)
Sebastian Hack's avatar
Sebastian Hack committed
370
371
372
373
		add_irn_dep(tgt, get_irn_dep(src, i));
}


374
375
ir_mode *(get_irn_mode)(const ir_node *node)
{
376
	return get_irn_mode_(node);
Christian Schäfer's avatar
Christian Schäfer committed
377
378
}

379
380
void (set_irn_mode)(ir_node *node, ir_mode *mode)
{
381
	set_irn_mode_(node, mode);
Till Riedel's avatar
Till Riedel committed
382
383
}

384
385
ir_op *(get_irn_op)(const ir_node *node)
{
386
	return get_irn_op_(node);
Christian Schäfer's avatar
Christian Schäfer committed
387
388
389
}

/* should be private to the library: */
390
391
void (set_irn_op)(ir_node *node, ir_op *op)
{
392
	set_irn_op_(node, op);
Christian Schäfer's avatar
Christian Schäfer committed
393
394
}

395
396
unsigned (get_irn_opcode)(const ir_node *node)
{
397
	return get_irn_opcode_(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
398
399
}

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

407
408
ident *get_irn_opident(const ir_node *node)
{
409
410
	assert(node);
	return node->op->name;
411
412
}

413
414
ir_visited_t (get_irn_visited)(const ir_node *node)
{
415
	return get_irn_visited_(node);
416
417
}

418
419
void (set_irn_visited)(ir_node *node, ir_visited_t visited)
{
420
	set_irn_visited_(node, visited);
Christian Schäfer's avatar
Christian Schäfer committed
421
}
422

423
424
void (mark_irn_visited)(ir_node *node)
{
425
	mark_irn_visited_(node);
426
427
}

428
429
int (irn_visited)(const ir_node *node)
{
430
	return irn_visited_(node);
431
432
}

433
434
int (irn_visited_else_mark)(ir_node *node)
{
435
	return irn_visited_else_mark_(node);
436
437
}

438
439
void (set_irn_link)(ir_node *node, void *link)
{
440
	set_irn_link_(node, link);
Christian Schäfer's avatar
Christian Schäfer committed
441
442
}

443
444
void *(get_irn_link)(const ir_node *node)
{
445
	return get_irn_link_(node);
Christian Schäfer's avatar
Christian Schäfer committed
446
447
}

448
449
op_pin_state (get_irn_pinned)(const ir_node *node)
{
450
	return get_irn_pinned_(node);
451
452
}

453
454
op_pin_state (is_irn_pinned_in_irg) (const ir_node *node)
{
455
	return is_irn_pinned_in_irg_(node);
456
457
}

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

464
465
	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
466

467
	node->attr.except.pin_state = state;
Michael Beck's avatar
Michael Beck committed
468
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
469

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

477
478
void *(get_irn_generic_attr)(ir_node *node)
{
479
	assert(is_ir_node(node));
480
	return get_irn_generic_attr_(node);
481
482
}

483
484
const void *(get_irn_generic_attr_const)(const ir_node *node)
{
485
	assert(is_ir_node(node));
486
	return get_irn_generic_attr_const_(node);
487
488
}

489
490
unsigned (get_irn_idx)(const ir_node *node)
{
491
	assert(is_ir_node(node));
492
	return get_irn_idx_(node);
493
494
}

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

Christian Schäfer's avatar
Christian Schäfer committed
505
506
/** manipulate fields of individual nodes **/

507
ir_node *(get_nodes_block)(const ir_node *node)
508
{
509
	return get_nodes_block_(node);
Christian Schäfer's avatar
Christian Schäfer committed
510
511
}

512
513
void set_nodes_block(ir_node *node, ir_node *block)
{
514
515
	assert(node->op != op_Block);
	set_irn_n(node, -1, block);
Christian Schäfer's avatar
Christian Schäfer committed
516
517
}

518
519
/* Test whether arbitrary node is frame pointer, i.e. Proj(pn_Start_P_frame_base)
 * from Start.  If so returns frame type, else Null. */
520
521
ir_type *is_frame_pointer(const ir_node *n)
{
522
523
	if (is_Proj(n) && (get_Proj_proj(n) == pn_Start_P_frame_base)) {
		ir_node *start = get_Proj_pred(n);
524
		if (is_Start(start)) {
525
526
527
528
			return get_irg_frame_type(get_irn_irg(start));
		}
	}
	return NULL;
529
530
}

531
532
ir_node **get_Block_cfgpred_arr(ir_node *node)
{
533
	assert(is_Block(node));
534
	return (ir_node **)&(get_irn_in(node)[1]);
535
536
}

537
538
int (get_Block_n_cfgpreds)(const ir_node *node)
{
539
	return get_Block_n_cfgpreds_(node);
Christian Schäfer's avatar
Christian Schäfer committed
540
541
}

542
543
ir_node *(get_Block_cfgpred)(const ir_node *node, int pos)
{
544
	return get_Block_cfgpred_(node, pos);
Christian Schäfer's avatar
Christian Schäfer committed
545
546
}

547
548
void set_Block_cfgpred(ir_node *node, int pos, ir_node *pred)
{
549
	assert(is_Block(node));
550
	set_irn_n(node, pos, pred);
Christian Schäfer's avatar
Christian Schäfer committed
551
552
}

553
554
int get_Block_cfgpred_pos(const ir_node *block, const ir_node *pred)
{
555
556
557
558
559
560
561
562
563
	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;
}

564
565
ir_node *(get_Block_cfgpred_block)(const ir_node *node, int pos)
{
566
	return get_Block_cfgpred_block_(node, pos);
567
568
}

569
570
int get_Block_matured(const ir_node *node)
{
571
	assert(is_Block(node));
Michael Beck's avatar
Michael Beck committed
572
	return (int)node->attr.block.is_matured;
Christian Schäfer's avatar
Christian Schäfer committed
573
574
}

575
576
void set_Block_matured(ir_node *node, int matured)
{
577
	assert(is_Block(node));
Michael Beck's avatar
Michael Beck committed
578
	node->attr.block.is_matured = matured;
Christian Schäfer's avatar
Christian Schäfer committed
579
}
Michael Beck's avatar
Michael Beck committed
580

581
582
ir_visited_t (get_Block_block_visited)(const ir_node *node)
{
583
	return get_Block_block_visited_(node);
Christian Schäfer's avatar
Christian Schäfer committed
584
585
}

586
587
void (set_Block_block_visited)(ir_node *node, ir_visited_t visit)
{
588
	set_Block_block_visited_(node, visit);
Christian Schäfer's avatar
Christian Schäfer committed
589
590
}

591
592
void (mark_Block_block_visited)(ir_node *node)
{
593
	mark_Block_block_visited_(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
594
595
}

596
597
int (Block_block_visited)(const ir_node *node)
{
598
	return Block_block_visited_(node);
Matthias Braun's avatar
Matthias Braun committed
599
600
}

601
602
ir_extblk *get_Block_extbb(const ir_node *block)
{
Michael Beck's avatar
Michael Beck committed
603
	ir_extblk *res;
604
	assert(is_Block(block));
Michael Beck's avatar
Michael Beck committed
605
606
	res = block->attr.block.extblk;
	assert(res == NULL || is_ir_extbb(res));
607
	return res;
608
609
}

610
611
void set_Block_extbb(ir_node *block, ir_extblk *extblk)
{
612
	assert(is_Block(block));
Michael Beck's avatar
Michael Beck committed
613
	assert(extblk == NULL || is_ir_extbb(extblk));
614
	block->attr.block.extblk = extblk;
615
616
}

617
/* returns the graph of a Block. */
618
619
ir_graph *(get_Block_irg)(const ir_node *block)
{
620
	return get_Block_irg_(block);
621
622
}

623
624
ir_entity *create_Block_entity(ir_node *block)
{
625
	ir_entity *entity;
Michael Beck's avatar
Michael Beck committed
626
	assert(is_Block(block));
627
628
629

	entity = block->attr.block.entity;
	if (entity == NULL) {
Matthias Braun's avatar
Matthias Braun committed
630
631
		ir_label_t nr = get_irp_next_label_nr();
		entity = new_label_entity(nr);
632
633
		set_entity_visibility(entity, ir_visibility_local);
		set_entity_linkage(entity, IR_LINKAGE_CONSTANT);
634
635
636
637
638
		set_entity_compiler_generated(entity, 1);

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

641
642
ir_node *(get_Block_phis)(const ir_node *block)
{
643
	return get_Block_phis_(block);
644
645
}

646
647
void (set_Block_phis)(ir_node *block, ir_node *phi)
{
648
	set_Block_phis_(block, phi);
649
650
}

651
652
void (add_Block_phi)(ir_node *block, ir_node *phi)
{
653
	add_Block_phi_(block, phi);
Michael Beck's avatar
Michael Beck committed
654
655
656
}

/* Get the Block mark (single bit). */
657
658
unsigned (get_Block_mark)(const ir_node *block)
{
659
	return get_Block_mark_(block);
Michael Beck's avatar
Michael Beck committed
660
661
662
}

/* Set the Block mark (single bit). */
663
664
void (set_Block_mark)(ir_node *block, unsigned mark)
{
665
	set_Block_mark_(block, mark);
Michael Beck's avatar
Michael Beck committed
666
667
}

668
669
int get_End_n_keepalives(const ir_node *end)
{
670
	assert(is_End(end));
671
	return (get_irn_arity(end) - END_KEEPALIVE_OFFSET);
672
673
}

674
675
ir_node *get_End_keepalive(const ir_node *end, int pos)
{
676
	assert(is_End(end));
677
	return get_irn_n(end, pos + END_KEEPALIVE_OFFSET);
678
679
}

680
681
void add_End_keepalive(ir_node *end, ir_node *ka)
{
682
	assert(is_End(end));
683
	add_irn_n(end, ka);
684
685
}

686
687
void set_End_keepalive(ir_node *end, int pos, ir_node *ka)
{
688
	assert(is_End(end));
689
	set_irn_n(end, pos + END_KEEPALIVE_OFFSET, ka);
690
691
}

692
/* Set new keep-alives */
693
694
void set_End_keepalives(ir_node *end, int n, ir_node *in[])
{
695
696
	size_t e;
	int    i;
697
	ir_graph *irg = get_irn_irg(end);
698

699
	/* notify that edges are deleted */
700
701
	for (e = END_KEEPALIVE_OFFSET; e < ARR_LEN(end->in) - 1; ++e) {
		edges_notify_edge(end, e, NULL, end->in[e + 1], irg);
702
703
	}
	ARR_RESIZE(ir_node *, end->in, n + 1 + END_KEEPALIVE_OFFSET);
704

705
706
	for (i = 0; i < n; ++i) {
		end->in[1 + END_KEEPALIVE_OFFSET + i] = in[i];
707
		edges_notify_edge(end, END_KEEPALIVE_OFFSET + i, end->in[1 + END_KEEPALIVE_OFFSET + i], NULL, irg);
708
	}
709
710

	/* update irg flags */
Andreas Zwinkau's avatar
Andreas Zwinkau committed
711
	clear_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_OUTS);
712
}
713

714
/* Set new keep-alives from old keep-alives, skipping irn */
715
716
void remove_End_keepalive(ir_node *end, ir_node *irn)
{
717
718
719
720
721
722
723
724
725
726
727
728
729
	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;
		}
730
	}
731
732
733
734
735
736
737
738
739
740
741
742
743
744
	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);
	}
745
	/* now n - 1 keeps, 1 block input */
746
	ARR_RESIZE(ir_node *, end->in, (n - 1) + 1 + END_KEEPALIVE_OFFSET);
747
748

	/* update irg flags */
Andreas Zwinkau's avatar
Andreas Zwinkau committed
749
	clear_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_OUTS);
750
}
751

Michael Beck's avatar
Michael Beck committed
752
/* remove Bads, NoMems and doublets from the keep-alive set */
753
754
void remove_End_Bads_and_doublets(ir_node *end)
{
755
756
757
	pset_new_t keeps;
	int        idx, n = get_End_n_keepalives(end);
	ir_graph   *irg;
758
	bool       changed = false;
759
760
761
762
763
764
765
766
767
768

	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
769
		if (is_Bad(ka) || is_NoMem(ka) || pset_new_contains(&keeps, ka)) {
770
			changed = true;
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
			/* 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);
790
791

	if (changed) {
Andreas Zwinkau's avatar
Andreas Zwinkau committed
792
		clear_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_OUTS);
793
	}
794
795
}

796
797
void free_End(ir_node *end)
{
798
	assert(is_End(end));
799
800
801
802
	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 ... */
803
804
}

805
size_t get_Return_n_ress(const ir_node *node)
806
{
807
	assert(is_Return(node));
808
	return (size_t)(get_irn_arity(node) - RETURN_RESULT_OFFSET);
809
810
}

811
ir_node **get_Return_res_arr(ir_node *node)
812
{
813
	assert(is_Return(node));
814
815
816
817
	if (get_Return_n_ress(node) > 0)
		return (ir_node **)&(get_irn_in(node)[1 + RETURN_RESULT_OFFSET]);
	else
		return NULL;
818
819
}

820
ir_node *get_Return_res(const ir_node *node, int pos)
821
{
822
	assert(is_Return(node));
823
824
	assert(pos >= 0);
	assert(get_Return_n_ress(node) > (size_t)pos);
825
	return get_irn_n(node, pos + RETURN_RESULT_OFFSET);
Christian Schäfer's avatar
Christian Schäfer committed
826
827
}

828
void set_Return_res(ir_node *node, int pos, ir_node *res)
829
{
830
	assert(is_Return(node));
831
	set_irn_n(node, pos + RETURN_RESULT_OFFSET, res);
Christian Schäfer's avatar
Christian Schäfer committed
832
833
}

834
835
int (is_Const_null)(const ir_node *node)
{
836
	return is_Const_null_(node);
837
838
}

839
840
int (is_Const_one)(const ir_node *node)
{
841
	return is_Const_one_(node);
842
843
}

844
845
int (is_Const_all_one)(const ir_node *node)
{
846
	return is_Const_all_one_(node);
Sebastian Hack's avatar
Sebastian Hack committed
847
848
}

849
850


851
symconst_kind get_SymConst_kind(const ir_node *node)
852
{
853
	assert(is_SymConst(node));
854
	return node->attr.symc.kind;
Christian Schäfer's avatar
Christian Schäfer committed
855
856
}

857
void set_SymConst_kind(ir_node *node, symconst_kind kind)
858
{
859
	assert(is_SymConst(node));
860
	node->attr.symc.kind = kind;
Christian Schäfer's avatar
Christian Schäfer committed
861
862
}

863
ir_type *get_SymConst_type(const ir_node *node)
864
{
Michael Beck's avatar
Michael Beck committed
865
866
867
	/* the cast here is annoying, but we have to compensate for
	   the skip_tip() */
	ir_node *irn = (ir_node *)node;
868
	assert(is_SymConst(node) &&
869
	       (SYMCONST_HAS_TYPE(get_SymConst_kind(node))));
Matthias Braun's avatar
Matthias Braun committed
870
	return irn->attr.symc.sym.type_p;
Christian Schäfer's avatar
Christian Schäfer committed
871
872
}

873
void set_SymConst_type(ir_node *node, ir_type *tp)
874
{
875
	assert(is_SymConst(node) &&
876
877
	       (SYMCONST_HAS_TYPE(get_SymConst_kind(node))));
	node->attr.symc.sym.type_p = tp;
Christian Schäfer's avatar
Christian Schäfer committed