irnode.c 33.9 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! */
141
142
	edges_notify_edge(res, -1, res->in[0], NULL, irg);
	for (i = 1; i <= arity; ++i)
143
		edges_notify_edge(res, i - 1, res->in[i], NULL, irg);
Sebastian Hack's avatar
Sebastian Hack committed
144

145
	hook_new_node(irg, res);
146
	if (get_irg_phase_state(irg) == phase_backend) {
147
		be_info_new_node(irg, res);
148
	}
Michael Beck's avatar
Michael Beck committed
149

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

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

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

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

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

174
	pOld_in = &node->in;
175

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

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

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

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

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

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

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

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

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

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

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

245
246
247
	return pos;
}

Christoph Mallon's avatar
Christoph Mallon committed
248
249
250
251
252
253
254
255
256
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);
}

257
258
int (get_irn_deps)(const ir_node *node)
{
259
	return get_irn_deps_(node);
Sebastian Hack's avatar
Sebastian Hack committed
260
261
}

262
263
ir_node *(get_irn_dep)(const ir_node *node, int pos)
{
264
	return get_irn_dep_(node, pos);
Sebastian Hack's avatar
Sebastian Hack committed
265
266
}

267
void set_irn_dep(ir_node *node, int pos, ir_node *dep)
268
{
269
270
271
272
273
274
275
276
277
278
279
	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
280
281
}

282
void add_irn_dep(ir_node *node, ir_node *dep)
283
{
284
	ir_graph *irg;
285
	assert(dep != NULL);
Sebastian Hack's avatar
Sebastian Hack committed
286
	if (node->deps == NULL) {
287
288
289
		node->deps = NEW_ARR_F(ir_node *, 0);
	}
	ARR_APP1(ir_node*, node->deps, dep);
290
291
292
	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);
293
}
Sebastian Hack's avatar
Sebastian Hack committed
294

295
296
297
298
299
300
301
302
303
304
305
306
307
308
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
309
310
311
312
		}
	}
}

313
314
void add_irn_deps(ir_node *tgt, ir_node *src)
{
Sebastian Hack's avatar
Sebastian Hack committed
315
316
	int i, n;

317
	for (i = 0, n = get_irn_deps(src); i < n; ++i)
Sebastian Hack's avatar
Sebastian Hack committed
318
319
320
321
		add_irn_dep(tgt, get_irn_dep(src, i));
}


322
323
ir_mode *(get_irn_mode)(const ir_node *node)
{
324
	return get_irn_mode_(node);
Christian Schäfer's avatar
Christian Schäfer committed
325
326
}

327
328
void (set_irn_mode)(ir_node *node, ir_mode *mode)
{
329
	set_irn_mode_(node, mode);
Till Riedel's avatar
Till Riedel committed
330
331
}

332
333
ir_op *(get_irn_op)(const ir_node *node)
{
334
	return get_irn_op_(node);
Christian Schäfer's avatar
Christian Schäfer committed
335
336
}

337
338
void (set_irn_op)(ir_node *node, ir_op *op)
{
339
	set_irn_op_(node, op);
Christian Schäfer's avatar
Christian Schäfer committed
340
341
}

342
343
unsigned (get_irn_opcode)(const ir_node *node)
{
344
	return get_irn_opcode_(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
345
346
}

347
348
const char *get_irn_opname(const ir_node *node)
{
349
	return get_id_str(node->op->name);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
350
351
}

352
353
ident *get_irn_opident(const ir_node *node)
{
354
355
	assert(node);
	return node->op->name;
356
357
}

358
359
ir_visited_t (get_irn_visited)(const ir_node *node)
{
360
	return get_irn_visited_(node);
361
362
}

363
364
void (set_irn_visited)(ir_node *node, ir_visited_t visited)
{
365
	set_irn_visited_(node, visited);
Christian Schäfer's avatar
Christian Schäfer committed
366
}
367

368
369
void (mark_irn_visited)(ir_node *node)
{
370
	mark_irn_visited_(node);
371
372
}

373
374
int (irn_visited)(const ir_node *node)
{
375
	return irn_visited_(node);
376
377
}

378
379
int (irn_visited_else_mark)(ir_node *node)
{
380
	return irn_visited_else_mark_(node);
381
382
}

383
384
void (set_irn_link)(ir_node *node, void *link)
{
385
	set_irn_link_(node, link);
Christian Schäfer's avatar
Christian Schäfer committed
386
387
}

388
389
void *(get_irn_link)(const ir_node *node)
{
390
	return get_irn_link_(node);
Christian Schäfer's avatar
Christian Schäfer committed
391
392
}

393
394
op_pin_state (get_irn_pinned)(const ir_node *node)
{
395
	return get_irn_pinned_(node);
396
397
}

398
399
op_pin_state (is_irn_pinned_in_irg) (const ir_node *node)
{
400
	return is_irn_pinned_in_irg_(node);
401
402
}

403
404
void set_irn_pinned(ir_node *node, op_pin_state state)
{
405
	/* due to optimization an opt may be turned into a Tuple */
406
	if (is_Tuple(node))
407
		return;
Michael Beck's avatar
Michael Beck committed
408

409
410
	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
411

412
	node->attr.except.pin_state = state;
Michael Beck's avatar
Michael Beck committed
413
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
414

415
416
long get_irn_node_nr(const ir_node *node)
{
417
418
	assert(node);
	return node->node_nr;
419
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
420

421
422
void *(get_irn_generic_attr)(ir_node *node)
{
423
	assert(is_ir_node(node));
424
	return get_irn_generic_attr_(node);
425
426
}

427
428
const void *(get_irn_generic_attr_const)(const ir_node *node)
{
429
	assert(is_ir_node(node));
430
	return get_irn_generic_attr_const_(node);
431
432
}

433
434
unsigned (get_irn_idx)(const ir_node *node)
{
435
	assert(is_ir_node(node));
436
	return get_irn_idx_(node);
437
438
}

439
440
int get_irn_pred_pos(ir_node *node, ir_node *arg)
{
441
442
443
444
445
446
	int i;
	for (i = get_irn_arity(node) - 1; i >= 0; i--) {
		if (get_irn_n(node, i) == arg)
			return i;
	}
	return -1;
447
448
}

449
ir_node *(get_nodes_block)(const ir_node *node)
450
{
451
	return get_nodes_block_(node);
Christian Schäfer's avatar
Christian Schäfer committed
452
453
}

454
455
void set_nodes_block(ir_node *node, ir_node *block)
{
456
	assert(!is_Block(node));
457
	set_irn_n(node, -1, block);
Christian Schäfer's avatar
Christian Schäfer committed
458
459
}

460
461
ir_type *is_frame_pointer(const ir_node *n)
{
462
463
	if (is_Proj(n) && (get_Proj_proj(n) == pn_Start_P_frame_base)) {
		ir_node *start = get_Proj_pred(n);
464
		if (is_Start(start)) {
465
466
467
468
			return get_irg_frame_type(get_irn_irg(start));
		}
	}
	return NULL;
469
470
}

471
472
ir_node **get_Block_cfgpred_arr(ir_node *node)
{
473
	assert(is_Block(node));
474
	return (ir_node **)&(get_irn_in(node)[1]);
475
476
}

477
478
int (get_Block_n_cfgpreds)(const ir_node *node)
{
479
	return get_Block_n_cfgpreds_(node);
Christian Schäfer's avatar
Christian Schäfer committed
480
481
}

482
483
ir_node *(get_Block_cfgpred)(const ir_node *node, int pos)
{
484
	return get_Block_cfgpred_(node, pos);
Christian Schäfer's avatar
Christian Schäfer committed
485
486
}

487
488
void set_Block_cfgpred(ir_node *node, int pos, ir_node *pred)
{
489
	assert(is_Block(node));
490
	set_irn_n(node, pos, pred);
Christian Schäfer's avatar
Christian Schäfer committed
491
492
}

493
494
int get_Block_cfgpred_pos(const ir_node *block, const ir_node *pred)
{
495
496
497
498
499
500
501
502
503
	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;
}

504
505
ir_node *(get_Block_cfgpred_block)(const ir_node *node, int pos)
{
506
	return get_Block_cfgpred_block_(node, pos);
507
508
}

509
510
int get_Block_matured(const ir_node *node)
{
511
	assert(is_Block(node));
Michael Beck's avatar
Michael Beck committed
512
	return (int)node->attr.block.is_matured;
Christian Schäfer's avatar
Christian Schäfer committed
513
514
}

515
516
void set_Block_matured(ir_node *node, int matured)
{
517
	assert(is_Block(node));
Michael Beck's avatar
Michael Beck committed
518
	node->attr.block.is_matured = matured;
Christian Schäfer's avatar
Christian Schäfer committed
519
}
Michael Beck's avatar
Michael Beck committed
520

521
522
ir_visited_t (get_Block_block_visited)(const ir_node *node)
{
523
	return get_Block_block_visited_(node);
Christian Schäfer's avatar
Christian Schäfer committed
524
525
}

526
527
void (set_Block_block_visited)(ir_node *node, ir_visited_t visit)
{
528
	set_Block_block_visited_(node, visit);
Christian Schäfer's avatar
Christian Schäfer committed
529
530
}

531
532
void (mark_Block_block_visited)(ir_node *node)
{
533
	mark_Block_block_visited_(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
534
535
}

536
537
int (Block_block_visited)(const ir_node *node)
{
538
	return Block_block_visited_(node);
Matthias Braun's avatar
Matthias Braun committed
539
540
}

541
542
ir_graph *(get_Block_irg)(const ir_node *block)
{
543
	return get_Block_irg_(block);
544
545
}

546
547
ir_entity *create_Block_entity(ir_node *block)
{
548
	ir_entity *entity;
Michael Beck's avatar
Michael Beck committed
549
	assert(is_Block(block));
550
551
552

	entity = block->attr.block.entity;
	if (entity == NULL) {
Matthias Braun's avatar
Matthias Braun committed
553
554
		ir_label_t nr = get_irp_next_label_nr();
		entity = new_label_entity(nr);
555
556
		set_entity_visibility(entity, ir_visibility_local);
		set_entity_linkage(entity, IR_LINKAGE_CONSTANT);
557
558
559
560
561
		set_entity_compiler_generated(entity, 1);

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

564
565
ir_node *(get_Block_phis)(const ir_node *block)
{
566
	return get_Block_phis_(block);
567
568
}

569
570
void (set_Block_phis)(ir_node *block, ir_node *phi)
{
571
	set_Block_phis_(block, phi);
572
573
}

574
575
void (add_Block_phi)(ir_node *block, ir_node *phi)
{
576
	add_Block_phi_(block, phi);
Michael Beck's avatar
Michael Beck committed
577
578
}

579
580
unsigned (get_Block_mark)(const ir_node *block)
{
581
	return get_Block_mark_(block);
Michael Beck's avatar
Michael Beck committed
582
583
}

584
585
void (set_Block_mark)(ir_node *block, unsigned mark)
{
586
	set_Block_mark_(block, mark);
Michael Beck's avatar
Michael Beck committed
587
588
}

589
590
int get_End_n_keepalives(const ir_node *end)
{
591
	assert(is_End(end));
592
	return (get_irn_arity(end) - END_KEEPALIVE_OFFSET);
593
594
}

595
596
ir_node *get_End_keepalive(const ir_node *end, int pos)
{
597
	assert(is_End(end));
598
	return get_irn_n(end, pos + END_KEEPALIVE_OFFSET);
599
600
}

601
602
void add_End_keepalive(ir_node *end, ir_node *ka)
{
603
	assert(is_End(end));
604
	add_irn_n(end, ka);
605
606
}

607
608
void set_End_keepalive(ir_node *end, int pos, ir_node *ka)
{
609
	assert(is_End(end));
610
	set_irn_n(end, pos + END_KEEPALIVE_OFFSET, ka);
611
612
}

613
614
void set_End_keepalives(ir_node *end, int n, ir_node *in[])
{
615
616
	size_t e;
	int    i;
617
	ir_graph *irg = get_irn_irg(end);
618

619
	/* notify that edges are deleted */
620
621
	for (e = END_KEEPALIVE_OFFSET; e < ARR_LEN(end->in) - 1; ++e) {
		edges_notify_edge(end, e, NULL, end->in[e + 1], irg);
622
623
	}
	ARR_RESIZE(ir_node *, end->in, n + 1 + END_KEEPALIVE_OFFSET);
624

625
626
	for (i = 0; i < n; ++i) {
		end->in[1 + END_KEEPALIVE_OFFSET + i] = in[i];
627
		edges_notify_edge(end, END_KEEPALIVE_OFFSET + i, end->in[1 + END_KEEPALIVE_OFFSET + i], NULL, irg);
628
	}
629
630

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

634
635
void remove_End_keepalive(ir_node *end, ir_node *irn)
{
636
637
638
	int      n = get_End_n_keepalives(end);
	ir_graph *irg;

Christoph Mallon's avatar
Christoph Mallon committed
639
640
641
642
643
	int idx = -1;
	for (int i = n;;) {
		if (i-- == 0)
			return;

644
645
646
647
648
		ir_node *old_ka = end->in[1 + END_KEEPALIVE_OFFSET + i];

		/* find irn */
		if (old_ka == irn) {
			idx = i;
Christoph Mallon's avatar
Christoph Mallon committed
649
			break;
650
		}
651
	}
652
653
654
655
656
657
658
659
660
661
662
663
	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);
	}
664
	/* now n - 1 keeps, 1 block input */
665
	ARR_RESIZE(ir_node *, end->in, (n - 1) + 1 + END_KEEPALIVE_OFFSET);
666
667

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

671
672
void remove_End_Bads_and_doublets(ir_node *end)
{
673
674
675
	pset_new_t keeps;
	int        idx, n = get_End_n_keepalives(end);
	ir_graph   *irg;
676
	bool       changed = false;
677
678
679
680
681
682
683
684
685
686

	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
687
		if (is_Bad(ka) || is_NoMem(ka) || pset_new_contains(&keeps, ka)) {
688
			changed = true;
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
			/* 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);
708
709

	if (changed) {
710
		clear_irg_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_OUTS);
711
	}
712
713
}

714
715
void free_End(ir_node *end)
{
716
	assert(is_End(end));
717
718
719
720
	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 ... */
721
722
}

723
size_t get_Return_n_ress(const ir_node *node)
724
{
725
	assert(is_Return(node));
726
	return (size_t)(get_irn_arity(node) - RETURN_RESULT_OFFSET);
727
728
}

729
ir_node **get_Return_res_arr(ir_node *node)
730
{
731
	assert(is_Return(node));
732
733
734
735
	if (get_Return_n_ress(node) > 0)
		return (ir_node **)&(get_irn_in(node)[1 + RETURN_RESULT_OFFSET]);
	else
		return NULL;
736
737
}

738
ir_node *get_Return_res(const ir_node *node, int pos)
739
{
740
	assert(is_Return(node));
741
742
	assert(pos >= 0);
	assert(get_Return_n_ress(node) > (size_t)pos);
743
	return get_irn_n(node, pos + RETURN_RESULT_OFFSET);
Christian Schäfer's avatar
Christian Schäfer committed
744
745
}

746
void set_Return_res(ir_node *node, int pos, ir_node *res)
747
{
748
	assert(is_Return(node));
749
	set_irn_n(node, pos + RETURN_RESULT_OFFSET, res);
Christian Schäfer's avatar
Christian Schäfer committed
750
751
}

752
753
int (is_Const_null)(const ir_node *node)
{
754
	return is_Const_null_(node);
755
756
}

757
758
int (is_Const_one)(const ir_node *node)
{
759
	return is_Const_one_(node);
760
761
}

762
763
int (is_Const_all_one)(const ir_node *node)
{
764
	return is_Const_all_one_(node);
Sebastian Hack's avatar
Sebastian Hack committed
765
766
}

767
768


769
symconst_kind get_SymConst_kind(const ir_node *node)
770
{
771
	assert(is_SymConst(node));
772
	return node->attr.symc.kind;
Christian Schäfer's avatar
Christian Schäfer committed
773
774
}

775
void set_SymConst_kind(ir_node *node, symconst_kind kind)
776
{
777
	assert(is_SymConst(node));
778
	node->attr.symc.kind = kind;
Christian Schäfer's avatar
Christian Schäfer committed
779
780
}

781
ir_type *get_SymConst_type(const ir_node *node)
782
{
Michael Beck's avatar
Michael Beck committed
783
784
785
	/* the cast here is annoying, but we have to compensate for
	   the skip_tip() */
	ir_node *irn = (ir_node *)node;
786
	assert(is_SymConst(node) &&
787
	       (SYMCONST_HAS_TYPE(get_SymConst_kind(node))));
Matthias Braun's avatar
Matthias Braun committed
788
	return irn->attr.symc.sym.type_p;
Christian Schäfer's avatar
Christian Schäfer committed
789
790
}

791
void set_SymConst_type(ir_node *node, ir_type *tp)
792
{
793
	assert(is_SymConst(node) &&
794
795
	       (SYMCONST_HAS_TYPE(get_SymConst_kind(node))));
	node->attr.symc.sym.type_p = tp;
Christian Schäfer's avatar
Christian Schäfer committed
796
797
}

798
799
ir_entity *get_SymConst_entity(const ir_node *node)
{
800
	assert(is_SymConst(node) && SYMCONST_HAS_ENT(get_SymConst_kind(node)));
801
	return node->attr.symc.sym.entity_p;
Beyhan's avatar
Beyhan committed
802
803
}

804
805
void set_SymConst_entity(ir_node *node, ir_entity *ent)
{
806
	assert(is_SymConst(node) && SYMCONST_HAS_ENT(get_SymConst_kind(node)));
807
	node->attr.symc.sym.entity_p  = ent;
Beyhan's avatar
Beyhan committed
808
809
}

810
811
ir_enum_const *get_SymConst_enum(const ir_node *node)
{
812
	assert(is_SymConst(node) && SYMCONST_HAS_ENUM(get_SymConst_kind(node)));
813
	return node->attr.symc.sym.enum_p;
814
815
}

816
817
void set_SymConst_enum(ir_node *node, ir_enum_const *ec)
{
818
	assert(is_SymConst(node) && SYMCONST_HAS_ENUM(get_SymConst_kind(node)));
819
	node->attr.symc.sym.enum_p  = ec;
820
821
}

Michael Beck's avatar
Michael Beck committed
822
union symconst_symbol
823
824
get_SymConst_symbol(const ir_node *node)
{
825
	assert(is_SymConst(node));
826
	return node->attr.symc.sym;
Götz Lindenmaier's avatar
Götz Lindenmaier committed
827
828
}

829
void set_SymConst_symbol(ir_node *node, union symconst_symbol sym)
830
{
831
	assert(is_SymConst(node));
832
	node->attr.symc.sym = sym;
Götz Lindenmaier's avatar
Götz Lindenmaier committed
833
834
}

835
int get_Sel_n_indexs(const ir_node *node)
836
{
837
	assert(is_Sel(node));
838
	return (get_irn_arity(node) - SEL_INDEX_OFFSET);
839
840
}

841
ir_node **get_Sel_index_arr(ir_node *node)
842
{
843
	assert(is_Sel(node));
844
845
846
847
	if (get_Sel_n_indexs(node) > 0)
		return (ir_node **)& get_irn_in(node)[SEL_INDEX_OFFSET + 1];
	else
		return NULL;
848
849
}

850
ir_node *get_Sel_index(const ir_node *node, int pos)
851
{