irnode.c 33.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
/**
 * @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
#define CALL_PARAM_OFFSET     (n_Call_max+1)
#define BUILTIN_PARAM_OFFSET  (n_Builtin_max+1)
53
#define ASM_PARAM_OFFSET      (n_ASM_max+1)
54
55
#define SEL_INDEX_OFFSET      (n_Sel_max+1)
#define RETURN_RESULT_OFFSET  (n_Return_max+1)
Michael Beck's avatar
Michael Beck committed
56
#define END_KEEPALIVE_OFFSET  0
Götz Lindenmaier's avatar
Götz Lindenmaier committed
57

58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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"
75
};
Christian Schäfer's avatar
Christian Schäfer committed
76

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

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

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

98
ir_node *new_ir_node(dbg_info *db, ir_graph *irg, ir_node *block, ir_op *op,
99
                     ir_mode *mode, int arity, ir_node *const *in)
Christian Schäfer's avatar
Christian Schäfer committed
100
{
101
	int i;
102

Christoph Mallon's avatar
Christoph Mallon committed
103
104
105
	assert(irg);
	assert(op);
	assert(mode);
106
107
108

	size_t   const node_size = offsetof(ir_node, attr) + op->attr_size;
	ir_node *const res       = (ir_node*)OALLOCNZ(irg->obst, char, node_size);
109
110
111
112
113
114
115
116
117
118

	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) {
119
		res->in = NEW_ARR_F(ir_node *, 1);  /* 1: space for block */
120
	} else {
121
122
		/* not nice but necessary: End and Sync must always have a flexible array */
		if (op == op_End || op == op_Sync)
123
124
125
			res->in = NEW_ARR_F(ir_node *, (arity+1));
		else
			res->in = NEW_ARR_D(ir_node *, irg->obst, (arity+1));
126
		memcpy(&res->in[1], in, sizeof(ir_node *) * arity);
127
128
	}

129
	res->in[0]   = block;
130
131
	set_irn_dbg_info(res, db);
	res->node_nr = get_irp_new_node_nr();
Götz Lindenmaier's avatar
Götz Lindenmaier committed
132

Michael Beck's avatar
Michael Beck committed
133
	for (i = 0; i < EDGE_KIND_LAST; ++i) {
134
		INIT_LIST_HEAD(&res->edge_info[i].outs_head);
Michael Beck's avatar
Michael Beck committed
135
136
137
138
		/* edges will be build immediately */
		res->edge_info[i].edges_built = 1;
		res->edge_info[i].out_count = 0;
	}
139

140
	/* don't put this into the for loop, arity is -1 for some nodes! */
Matthias Braun's avatar
Matthias Braun committed
141
142
	if (block != NULL)
		edges_notify_edge(res, -1, block, NULL, irg);
143
	for (i = 1; i <= arity; ++i)
144
		edges_notify_edge(res, i - 1, res->in[i], NULL, irg);
Sebastian Hack's avatar
Sebastian Hack committed
145

146
	hook_new_node(irg, res);
147
	if (irg_is_constrained(irg, IR_GRAPH_CONSTRAINT_BACKEND)) {
148
		be_info_new_node(irg, res);
149
	}
Michael Beck's avatar
Michael Beck committed
150

151
	return res;
Christian Schäfer's avatar
Christian Schäfer committed
152
153
}

154
155
int (is_ir_node)(const void *thing)
{
156
	return is_ir_node_(thing);
Sebastian Felis's avatar
Sebastian Felis committed
157
158
}

159
160
int (get_irn_arity)(const ir_node *node)
{
161
	return get_irn_arity_(node);
162
163
}

164
165
ir_node **get_irn_in(const ir_node *node)
{
166
167
168
	return node->in;
}

169
170
void set_irn_in(ir_node *node, int arity, ir_node **in)
{
171
	int i;
Michael Beck's avatar
Michael Beck committed
172
	ir_node *** pOld_in;
173
	ir_graph *irg = get_irn_irg(node);
174

175
	pOld_in = &node->in;
176

177
178
179
180
181
182
183
#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
184
185

	for (i = 0; i < arity; i++) {
186
		if (i < (int)ARR_LEN(*pOld_in)-1)
Michael Beck's avatar
Michael Beck committed
187
			edges_notify_edge(node, i, in[i], (*pOld_in)[i+1], irg);
188
		else
Michael Beck's avatar
Michael Beck committed
189
			edges_notify_edge(node, i, in[i], NULL,            irg);
190
	}
191
	for (;i < (int)ARR_LEN(*pOld_in)-1; i++) {
Michael Beck's avatar
Michael Beck committed
192
		edges_notify_edge(node, i, NULL, (*pOld_in)[i+1], irg);
193
194
	}

195
	if (arity != (int)ARR_LEN(*pOld_in) - 1) {
Michael Beck's avatar
Michael Beck committed
196
197
198
		ir_node * block = (*pOld_in)[0];
		*pOld_in = NEW_ARR_D(ir_node *, irg->obst, arity + 1);
		(*pOld_in)[0] = block;
199
200
201
	}
	fix_backedges(irg->obst, node);

Michael Beck's avatar
Michael Beck committed
202
	memcpy((*pOld_in) + 1, in, sizeof(ir_node *) * arity);
203
204

	/* update irg flags */
205
	clear_irg_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_OUTS | IR_GRAPH_PROPERTY_CONSISTENT_LOOPINFO);
206
207
}

208
209
ir_node *(get_irn_n)(const ir_node *node, int n)
{
210
	return get_irn_n_(node, n);
Christian Schäfer's avatar
Christian Schäfer committed
211
212
}

213
214
void set_irn_n(ir_node *node, int n, ir_node *in)
{
215
	ir_graph *irg = get_irn_irg(node);
216
217
218
219
220
221
222
223
224
	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 */
225
	edges_notify_edge(node, n, in, node->in[n + 1], irg);
226
227

	node->in[n + 1] = in;
228
229

	/* update irg flags */
230
	clear_irg_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_OUTS | IR_GRAPH_PROPERTY_CONSISTENT_LOOPINFO);
Christian Schäfer's avatar
Christian Schäfer committed
231
232
}

233
234
int add_irn_n(ir_node *node, ir_node *in)
{
235
236
237
238
239
240
241
242
	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);

243
244
245
	/* Call the hook */
	hook_set_irn_n(node, pos, node->in[pos + 1], NULL);

Matthias Braun's avatar
Matthias Braun committed
246
247
248
	/* update irg flags */
	clear_irg_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_OUTS);

249
250
251
	return pos;
}

Matthias Braun's avatar
Matthias Braun committed
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
static void del_irn_n(ir_node *node, int n)
{
	ir_graph *irg = get_irn_irg(node);

	/* remove the edge */
	ir_node *pred = node->in[n+1];
	edges_notify_edge(node, n, NULL, pred, irg);

	int arity = get_irn_arity(node);
	if (n != arity-1) {
		/* exchange with the last one */
		ir_node *old = node->in[arity];
		edges_notify_edge(node, arity-1, NULL, old, irg);
		node->in[n+1] = old;
		edges_notify_edge(node, n, old, NULL, irg);
	}
	ARR_SHRINKLEN(node->in, arity);

	/* update irg flags */
	clear_irg_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_OUTS);
}

Christoph Mallon's avatar
Christoph Mallon committed
274
275
void del_Sync_n(ir_node *n, int i)
{
Matthias Braun's avatar
Matthias Braun committed
276
	del_irn_n(n, i);
Christoph Mallon's avatar
Christoph Mallon committed
277
278
}

279
280
int (get_irn_deps)(const ir_node *node)
{
281
	return get_irn_deps_(node);
Sebastian Hack's avatar
Sebastian Hack committed
282
283
}

284
285
ir_node *(get_irn_dep)(const ir_node *node, int pos)
{
286
	return get_irn_dep_(node, pos);
Sebastian Hack's avatar
Sebastian Hack committed
287
288
}

289
void set_irn_dep(ir_node *node, int pos, ir_node *dep)
290
{
291
292
293
294
295
296
297
298
299
300
301
	ir_node *old;
	ir_graph *irg;

	assert(node->deps && "dependency array node yet allocated. use add_irn_dep()");
	assert(pos >= 0 && pos < (int)ARR_LEN(node->deps) && "dependency index out of range");
	assert(dep != NULL);
	old = node->deps[pos];
	node->deps[pos] = dep;
	irg = get_irn_irg(node);
	if (edges_activated_kind(irg, EDGE_KIND_DEP))
		edges_notify_edge_kind(node, pos, dep, old, EDGE_KIND_DEP, irg);
Sebastian Hack's avatar
Sebastian Hack committed
302
303
}

304
void add_irn_dep(ir_node *node, ir_node *dep)
305
{
306
	ir_graph *irg;
307
	assert(dep != NULL);
Sebastian Hack's avatar
Sebastian Hack committed
308
	if (node->deps == NULL) {
309
310
311
		node->deps = NEW_ARR_F(ir_node *, 0);
	}
	ARR_APP1(ir_node*, node->deps, dep);
312
313
314
	irg = get_irn_irg(node);
	if (edges_activated_kind(irg, EDGE_KIND_DEP))
		edges_notify_edge_kind(node, ARR_LEN(node->deps)-1, dep, NULL, EDGE_KIND_DEP, irg);
315
}
Sebastian Hack's avatar
Sebastian Hack committed
316

317
318
319
320
321
322
323
324
325
326
327
328
329
330
void delete_irn_dep(ir_node *node, ir_node *dep)
{
	size_t i;
	size_t n_deps;
	if (node->deps == NULL)
		return;

	n_deps = ARR_LEN(node->deps);
	for (i = 0; i < n_deps; ++i) {
		if (node->deps[i] == dep) {
			set_irn_dep(node, i, node->deps[n_deps-1]);
			edges_notify_edge(node, i, NULL, dep, get_irn_irg(node));
			ARR_SHRINKLEN(node->deps, n_deps-1);
			break;
Sebastian Hack's avatar
Sebastian Hack committed
331
332
333
334
		}
	}
}

335
336
void add_irn_deps(ir_node *tgt, ir_node *src)
{
Sebastian Hack's avatar
Sebastian Hack committed
337
338
	int i, n;

339
	for (i = 0, n = get_irn_deps(src); i < n; ++i)
Sebastian Hack's avatar
Sebastian Hack committed
340
341
342
343
		add_irn_dep(tgt, get_irn_dep(src, i));
}


344
345
ir_mode *(get_irn_mode)(const ir_node *node)
{
346
	return get_irn_mode_(node);
Christian Schäfer's avatar
Christian Schäfer committed
347
348
}

349
350
void (set_irn_mode)(ir_node *node, ir_mode *mode)
{
351
	set_irn_mode_(node, mode);
Till Riedel's avatar
Till Riedel committed
352
353
}

354
355
ir_op *(get_irn_op)(const ir_node *node)
{
356
	return get_irn_op_(node);
Christian Schäfer's avatar
Christian Schäfer committed
357
358
}

359
360
void (set_irn_op)(ir_node *node, ir_op *op)
{
361
	set_irn_op_(node, op);
Christian Schäfer's avatar
Christian Schäfer committed
362
363
}

364
365
unsigned (get_irn_opcode)(const ir_node *node)
{
366
	return get_irn_opcode_(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
367
368
}

369
370
const char *get_irn_opname(const ir_node *node)
{
371
	return get_id_str(node->op->name);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
372
373
}

374
375
ident *get_irn_opident(const ir_node *node)
{
376
377
	assert(node);
	return node->op->name;
378
379
}

380
381
ir_visited_t (get_irn_visited)(const ir_node *node)
{
382
	return get_irn_visited_(node);
383
384
}

385
386
void (set_irn_visited)(ir_node *node, ir_visited_t visited)
{
387
	set_irn_visited_(node, visited);
Christian Schäfer's avatar
Christian Schäfer committed
388
}
389

390
391
void (mark_irn_visited)(ir_node *node)
{
392
	mark_irn_visited_(node);
393
394
}

395
396
int (irn_visited)(const ir_node *node)
{
397
	return irn_visited_(node);
398
399
}

400
401
int (irn_visited_else_mark)(ir_node *node)
{
402
	return irn_visited_else_mark_(node);
403
404
}

405
406
void (set_irn_link)(ir_node *node, void *link)
{
407
	set_irn_link_(node, link);
Christian Schäfer's avatar
Christian Schäfer committed
408
409
}

410
411
void *(get_irn_link)(const ir_node *node)
{
412
	return get_irn_link_(node);
Christian Schäfer's avatar
Christian Schäfer committed
413
414
}

415
416
op_pin_state (get_irn_pinned)(const ir_node *node)
{
417
	return get_irn_pinned_(node);
418
419
}

420
421
op_pin_state (is_irn_pinned_in_irg) (const ir_node *node)
{
422
	return is_irn_pinned_in_irg_(node);
423
424
}

425
426
void set_irn_pinned(ir_node *node, op_pin_state state)
{
427
	/* due to optimization an opt may be turned into a Tuple */
428
	if (is_Tuple(node))
429
		return;
Michael Beck's avatar
Michael Beck committed
430

431
432
	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
433

434
	node->attr.except.pin_state = state;
Michael Beck's avatar
Michael Beck committed
435
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
436

437
438
long get_irn_node_nr(const ir_node *node)
{
439
440
	assert(node);
	return node->node_nr;
441
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
442

443
444
void *(get_irn_generic_attr)(ir_node *node)
{
445
	assert(is_ir_node(node));
446
	return get_irn_generic_attr_(node);
447
448
}

449
450
const void *(get_irn_generic_attr_const)(const ir_node *node)
{
451
	assert(is_ir_node(node));
452
	return get_irn_generic_attr_const_(node);
453
454
}

455
456
unsigned (get_irn_idx)(const ir_node *node)
{
457
	assert(is_ir_node(node));
458
	return get_irn_idx_(node);
459
460
}

461
ir_node *(get_nodes_block)(const ir_node *node)
462
{
463
	return get_nodes_block_(node);
Christian Schäfer's avatar
Christian Schäfer committed
464
465
}

466
467
void set_nodes_block(ir_node *node, ir_node *block)
{
468
	assert(!is_Block(node));
469
	set_irn_n(node, -1, block);
Christian Schäfer's avatar
Christian Schäfer committed
470
471
}

472
473
ir_type *is_frame_pointer(const ir_node *n)
{
474
475
	if (is_Proj(n) && (get_Proj_proj(n) == pn_Start_P_frame_base)) {
		ir_node *start = get_Proj_pred(n);
476
		if (is_Start(start)) {
477
478
479
480
			return get_irg_frame_type(get_irn_irg(start));
		}
	}
	return NULL;
481
482
}

483
484
ir_node **get_Block_cfgpred_arr(ir_node *node)
{
485
	assert(is_Block(node));
486
	return (ir_node **)&(get_irn_in(node)[1]);
487
488
}

489
490
int (get_Block_n_cfgpreds)(const ir_node *node)
{
491
	return get_Block_n_cfgpreds_(node);
Christian Schäfer's avatar
Christian Schäfer committed
492
493
}

494
495
ir_node *(get_Block_cfgpred)(const ir_node *node, int pos)
{
496
	return get_Block_cfgpred_(node, pos);
Christian Schäfer's avatar
Christian Schäfer committed
497
498
}

499
500
void set_Block_cfgpred(ir_node *node, int pos, ir_node *pred)
{
501
	assert(is_Block(node));
502
	set_irn_n(node, pos, pred);
Christian Schäfer's avatar
Christian Schäfer committed
503
504
}

505
506
int get_Block_cfgpred_pos(const ir_node *block, const ir_node *pred)
{
507
508
509
510
511
512
513
514
515
	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;
}

516
517
ir_node *(get_Block_cfgpred_block)(const ir_node *node, int pos)
{
518
	return get_Block_cfgpred_block_(node, pos);
519
520
}

521
522
int get_Block_matured(const ir_node *node)
{
523
	assert(is_Block(node));
Michael Beck's avatar
Michael Beck committed
524
	return (int)node->attr.block.is_matured;
Christian Schäfer's avatar
Christian Schäfer committed
525
526
}

527
528
void set_Block_matured(ir_node *node, int matured)
{
529
	assert(is_Block(node));
Michael Beck's avatar
Michael Beck committed
530
	node->attr.block.is_matured = matured;
Christian Schäfer's avatar
Christian Schäfer committed
531
}
Michael Beck's avatar
Michael Beck committed
532

533
534
ir_visited_t (get_Block_block_visited)(const ir_node *node)
{
535
	return get_Block_block_visited_(node);
Christian Schäfer's avatar
Christian Schäfer committed
536
537
}

538
539
void (set_Block_block_visited)(ir_node *node, ir_visited_t visit)
{
540
	set_Block_block_visited_(node, visit);
Christian Schäfer's avatar
Christian Schäfer committed
541
542
}

543
544
void (mark_Block_block_visited)(ir_node *node)
{
545
	mark_Block_block_visited_(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
546
547
}

548
549
int (Block_block_visited)(const ir_node *node)
{
550
	return Block_block_visited_(node);
Matthias Braun's avatar
Matthias Braun committed
551
552
}

553
554
ir_graph *(get_Block_irg)(const ir_node *block)
{
555
	return get_Block_irg_(block);
556
557
}

558
559
ir_entity *create_Block_entity(ir_node *block)
{
560
	ir_entity *entity;
Michael Beck's avatar
Michael Beck committed
561
	assert(is_Block(block));
562
563
564

	entity = block->attr.block.entity;
	if (entity == NULL) {
Matthias Braun's avatar
Matthias Braun committed
565
566
		ir_label_t nr = get_irp_next_label_nr();
		entity = new_label_entity(nr);
567
568
		set_entity_visibility(entity, ir_visibility_local);
		set_entity_linkage(entity, IR_LINKAGE_CONSTANT);
569
570
571
572
573
		set_entity_compiler_generated(entity, 1);

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

576
577
ir_node *(get_Block_phis)(const ir_node *block)
{
578
	return get_Block_phis_(block);
579
580
}

581
582
void (set_Block_phis)(ir_node *block, ir_node *phi)
{
583
	set_Block_phis_(block, phi);
584
585
}

586
587
void (add_Block_phi)(ir_node *block, ir_node *phi)
{
588
	add_Block_phi_(block, phi);
Michael Beck's avatar
Michael Beck committed
589
590
}

591
592
unsigned (get_Block_mark)(const ir_node *block)
{
593
	return get_Block_mark_(block);
Michael Beck's avatar
Michael Beck committed
594
595
}

596
597
void (set_Block_mark)(ir_node *block, unsigned mark)
{
598
	set_Block_mark_(block, mark);
Michael Beck's avatar
Michael Beck committed
599
600
}

601
602
int get_End_n_keepalives(const ir_node *end)
{
603
	assert(is_End(end));
604
	return (get_irn_arity(end) - END_KEEPALIVE_OFFSET);
605
606
}

607
608
ir_node *get_End_keepalive(const ir_node *end, int pos)
{
609
	assert(is_End(end));
610
	return get_irn_n(end, pos + END_KEEPALIVE_OFFSET);
611
612
}

613
614
void add_End_keepalive(ir_node *end, ir_node *ka)
{
615
	assert(is_End(end));
616
	add_irn_n(end, ka);
617
618
}

619
620
void set_End_keepalive(ir_node *end, int pos, ir_node *ka)
{
621
	assert(is_End(end));
622
	set_irn_n(end, pos + END_KEEPALIVE_OFFSET, ka);
623
624
}

625
626
void set_End_keepalives(ir_node *end, int n, ir_node *in[])
{
627
628
	size_t e;
	int    i;
629
	ir_graph *irg = get_irn_irg(end);
630

631
	/* notify that edges are deleted */
632
633
	for (e = END_KEEPALIVE_OFFSET; e < ARR_LEN(end->in) - 1; ++e) {
		edges_notify_edge(end, e, NULL, end->in[e + 1], irg);
634
635
	}
	ARR_RESIZE(ir_node *, end->in, n + 1 + END_KEEPALIVE_OFFSET);
636

637
638
	for (i = 0; i < n; ++i) {
		end->in[1 + END_KEEPALIVE_OFFSET + i] = in[i];
639
		edges_notify_edge(end, END_KEEPALIVE_OFFSET + i, end->in[1 + END_KEEPALIVE_OFFSET + i], NULL, irg);
640
	}
641
642

	/* update irg flags */
643
	clear_irg_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_OUTS);
644
}
645

646
647
void remove_End_keepalive(ir_node *end, ir_node *irn)
{
Matthias Braun's avatar
Matthias Braun committed
648
	int n = get_End_n_keepalives(end);
Christoph Mallon's avatar
Christoph Mallon committed
649
650
651
652
653
	int idx = -1;
	for (int i = n;;) {
		if (i-- == 0)
			return;

654
655
656
657
		ir_node *old_ka = end->in[1 + END_KEEPALIVE_OFFSET + i];

		/* find irn */
		if (old_ka == irn) {
Matthias Braun's avatar
Matthias Braun committed
658
			idx = END_KEEPALIVE_OFFSET + i;
Christoph Mallon's avatar
Christoph Mallon committed
659
			break;
660
		}
661
	}
Matthias Braun's avatar
Matthias Braun committed
662
663
	assert(idx != -1);
	del_irn_n(end, idx);
664
}
665

666
667
void remove_End_Bads_and_doublets(ir_node *end)
{
668
669
670
	pset_new_t keeps;
	int        idx, n = get_End_n_keepalives(end);
	ir_graph   *irg;
671
	bool       changed = false;
672
673
674
675
676
677
678
679
680
681

	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
682
		if (is_Bad(ka) || is_NoMem(ka) || pset_new_contains(&keeps, ka)) {
683
			changed = true;
Matthias Braun's avatar
Matthias Braun committed
684
			del_irn_n(end, idx - END_KEEPALIVE_OFFSET);
685
686
687
688
689
690
			--n;
		} else {
			pset_new_insert(&keeps, ka);
		}
	}
	pset_new_destroy(&keeps);
691
692

	if (changed) {
693
		clear_irg_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_OUTS);
694
	}
695
696
}

697
698
void free_End(ir_node *end)
{
699
	assert(is_End(end));
700
701
702
703
	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 ... */
704
705
}

706
size_t get_Return_n_ress(const ir_node *node)
707
{
708
	assert(is_Return(node));
709
	return (size_t)(get_irn_arity(node) - RETURN_RESULT_OFFSET);
710
711
}

712
ir_node **get_Return_res_arr(ir_node *node)
713
{
714
	assert(is_Return(node));
715
716
717
718
	if (get_Return_n_ress(node) > 0)
		return (ir_node **)&(get_irn_in(node)[1 + RETURN_RESULT_OFFSET]);
	else
		return NULL;
719
720
}

721
ir_node *get_Return_res(const ir_node *node, int pos)
722
{
723
	assert(is_Return(node));
724
725
	assert(pos >= 0);
	assert(get_Return_n_ress(node) > (size_t)pos);
726
	return get_irn_n(node, pos + RETURN_RESULT_OFFSET);
Christian Schäfer's avatar
Christian Schäfer committed
727
728
}

729
void set_Return_res(ir_node *node, int pos, ir_node *res)
730
{
731
	assert(is_Return(node));
732
	set_irn_n(node, pos + RETURN_RESULT_OFFSET, res);
Christian Schäfer's avatar
Christian Schäfer committed
733
734
}

735
736
int (is_Const_null)(const ir_node *node)
{
737
	return is_Const_null_(node);
738
739
}

740
741
int (is_Const_one)(const ir_node *node)
{
742
	return is_Const_one_(node);
743
744
}

745
746
int (is_Const_all_one)(const ir_node *node)
{
747
	return is_Const_all_one_(node);
Sebastian Hack's avatar
Sebastian Hack committed
748
749
}

750
751


752
symconst_kind get_SymConst_kind(const ir_node *node)
753
{
754
	assert(is_SymConst(node));
755
	return node->attr.symc.kind;
Christian Schäfer's avatar
Christian Schäfer committed
756
757
}

758
void set_SymConst_kind(ir_node *node, symconst_kind kind)
759
{
760
	assert(is_SymConst(node));
761
	node->attr.symc.kind = kind;
Christian Schäfer's avatar
Christian Schäfer committed
762
763
}

764
ir_type *get_SymConst_type(const ir_node *node)
765
{
Michael Beck's avatar
Michael Beck committed
766
767
768
	/* the cast here is annoying, but we have to compensate for
	   the skip_tip() */
	ir_node *irn = (ir_node *)node;
769
	assert(is_SymConst(node) &&
770
	       (SYMCONST_HAS_TYPE(get_SymConst_kind(node))));
Matthias Braun's avatar
Matthias Braun committed
771
	return irn->attr.symc.sym.type_p;
Christian Schäfer's avatar
Christian Schäfer committed
772
773
}

774
void set_SymConst_type(ir_node *node, ir_type *tp)
775
{
776
	assert(is_SymConst(node) &&
777
778
	       (SYMCONST_HAS_TYPE(get_SymConst_kind(node))));
	node->attr.symc.sym.type_p = tp;
Christian Schäfer's avatar
Christian Schäfer committed
779
780
}

781
782
ir_entity *get_SymConst_entity(const ir_node *node)
{
783
	assert(is_SymConst(node) && SYMCONST_HAS_ENT(get_SymConst_kind(node)));
784
	return node->attr.symc.sym.entity_p;
Beyhan's avatar
Beyhan committed
785
786
}

787
788
void set_SymConst_entity(ir_node *node, ir_entity *ent)
{
789
	assert(is_SymConst(node) && SYMCONST_HAS_ENT(get_SymConst_kind(node)));
790
	node->attr.symc.sym.entity_p  = ent;
Beyhan's avatar
Beyhan committed
791
792
}

793
794
ir_enum_const *get_SymConst_enum(const ir_node *node)
{
795
	assert(is_SymConst(node) && SYMCONST_HAS_ENUM(get_SymConst_kind(node)));
796
	return node->attr.symc.sym.enum_p;
797
798
}

799
800
void set_SymConst_enum(ir_node *node, ir_enum_const *ec)
{
801
	assert(is_SymConst(node) && SYMCONST_HAS_ENUM(get_SymConst_kind(node)));
802
	node->attr.symc.sym.enum_p  = ec;
803
804
}

Michael Beck's avatar
Michael Beck committed
805
union symconst_symbol
806
807
get_SymConst_symbol(const ir_node *node)
{
808
	assert(is_SymConst(node));
809
	return node->attr.symc.sym;
Götz Lindenmaier's avatar
Götz Lindenmaier committed
810
811
}

812
void set_SymConst_symbol(ir_node *node, union symconst_symbol sym)
813
{
814
	assert(is_SymConst(node));
815
	node->attr.symc.sym = sym;
Götz Lindenmaier's avatar
Götz Lindenmaier committed
816
817
}

818
int get_Sel_n_indexs(const ir_node *node)
819
{
820
	assert(is_Sel(node));
821
	return (get_irn_arity(node) - SEL_INDEX_OFFSET);
822
823
}

824
ir_node **get_Sel_index_arr(ir_node *node)
825
{
826
	assert(is_Sel(node));
827
828
829
830
	if (get_Sel_n_indexs(node) > 0)
		return (ir_node **)& get_irn_in(node)[SEL_INDEX_OFFSET + 1];
	else
		return NULL;
831
832
}

833
ir_node *get_Sel_index(const ir_node *node, int pos)
834
{
835
	assert(is_Sel(node));
836
	return get_irn_n(node, pos + SEL_INDEX_OFFSET);
Christian Schäfer's avatar
Christian Schäfer committed
837
838
}

839
void set_Sel_index(ir_node *node, int pos, ir_node *index)
840
{
841
	assert(is_Sel(node));