irnode.c 23.6 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
2
/*
 * This file is part of libFirm.
3
 * Copyright (C) 2012 University of Karlsruhe.
Christian Würdig's avatar
Christian Würdig committed
4
5
 */

Matthias Braun's avatar
Matthias Braun committed
6
7
8
9
/**
 * @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
10
 */
11
#include <string.h>
Boris Boesler's avatar
added    
Boris Boesler committed
12

13
#include "pset_new.h"
14
#include "ident.h"
Götz Lindenmaier's avatar
Götz Lindenmaier committed
15
#include "irnode_t.h"
Götz Lindenmaier's avatar
Götz Lindenmaier committed
16
#include "irgraph_t.h"
Götz Lindenmaier's avatar
Götz Lindenmaier committed
17
#include "irmode_t.h"
18
#include "irbackedge_t.h"
19
#include "irdump.h"
20
#include "irop_t.h"
21
#include "irprog_t.h"
Sebastian Hack's avatar
Sebastian Hack committed
22
#include "iredgekinds.h"
Sebastian Hack's avatar
Sebastian Hack committed
23
#include "iredges_t.h"
Matthias Braun's avatar
Matthias Braun committed
24
#include "ircons.h"
Matthias Braun's avatar
Matthias Braun committed
25
#include "panic.h"
26
#include "irverify.h"
Götz Lindenmaier's avatar
Götz Lindenmaier committed
27

28
#include "irhooks.h"
29
#include "util.h"
Michael Beck's avatar
Michael Beck committed
30

31
32
#include "beinfo.h"

Götz Lindenmaier's avatar
Götz Lindenmaier committed
33
34
/* some constants fixing the positions of nodes predecessors
   in the in array */
Michael Beck's avatar
Michael Beck committed
35
#define END_KEEPALIVE_OFFSET  0
Götz Lindenmaier's avatar
Götz Lindenmaier committed
36

37
const char *get_relation_string(ir_relation relation)
38
{
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
	static char const *const 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"
	};

	assert((size_t)relation < ARRAY_SIZE(relation_names));
59
	return relation_names[relation];
Christian Schäfer's avatar
Christian Schäfer committed
60
61
}

62
ir_relation get_negated_relation(ir_relation relation)
63
{
64
	return relation ^ ir_relation_true;
Christian Schäfer's avatar
Christian Schäfer committed
65
66
}

67
ir_relation get_inversed_relation(ir_relation relation)
68
{
69
70
71
	ir_relation code    = relation & ~(ir_relation_less|ir_relation_greater);
	bool        less    = relation & ir_relation_less;
	bool        greater = relation & ir_relation_greater;
72
73
	code |= (less ? ir_relation_greater : ir_relation_false)
	      | (greater ? ir_relation_less : ir_relation_false);
74
	return code;
Michael Beck's avatar
Michael Beck committed
75
76
}

77
ir_node *new_ir_node(dbg_info *db, ir_graph *irg, ir_node *block, ir_op *op,
78
                     ir_mode *mode, int arity, ir_node *const *in)
Christian Schäfer's avatar
Christian Schäfer committed
79
{
Matthias Braun's avatar
Matthias Braun committed
80
	assert(mode != NULL);
81
82

	size_t   const node_size = offsetof(ir_node, attr) + op->attr_size;
83
	ir_node *const res       = (ir_node*)OALLOCNZ(get_irg_obstack(irg), char, node_size);
84
85
86
87

	res->kind     = k_ir_node;
	res->op       = op;
	res->mode     = mode;
88
	res->irg      = irg;
89
90
91
92
93
94
	res->visited  = 0;
	res->node_idx = irg_register_node_idx(irg, res);
	res->link     = NULL;
	res->deps     = NULL;

	if (arity < 0) {
95
		res->in = NEW_ARR_F(ir_node *, 1);  /* 1: space for block */
96
	} else {
97
98
		/* Nodes with dynamic arity must always have a flexible array. */
		if (op->opar == oparity_dynamic)
99
100
			res->in = NEW_ARR_F(ir_node *, (arity+1));
		else
101
			res->in = NEW_ARR_D(ir_node*, get_irg_obstack(irg), arity + 1);
Christoph Mallon's avatar
Christoph Mallon committed
102
		MEMCPY(&res->in[1], in, arity);
103
104
	}

105
	res->in[0]   = block;
106
107
	set_irn_dbg_info(res, db);
	res->node_nr = get_irp_new_node_nr();
Götz Lindenmaier's avatar
Götz Lindenmaier committed
108

109
	for (ir_edge_kind_t i = EDGE_KIND_FIRST; i <= EDGE_KIND_LAST; ++i) {
110
		INIT_LIST_HEAD(&res->edge_info[i].outs_head);
111
		/* Edges will be built immediately. */
Michael Beck's avatar
Michael Beck committed
112
113
114
		res->edge_info[i].edges_built = 1;
		res->edge_info[i].out_count = 0;
	}
115

116
	/* don't put this into the for loop, arity is -1 for some nodes! */
Matthias Braun's avatar
Matthias Braun committed
117
118
	if (block != NULL)
		edges_notify_edge(res, -1, block, NULL, irg);
119
120
	for (int i = 0; i < arity; ++i)
		edges_notify_edge(res, i, res->in[i+1], NULL, irg);
Sebastian Hack's avatar
Sebastian Hack committed
121

122
	hook_new_node(res);
Matthias Braun's avatar
Matthias Braun committed
123
	if (irg_is_constrained(irg, IR_GRAPH_CONSTRAINT_BACKEND))
124
		be_info_new_node(irg, res);
Michael Beck's avatar
Michael Beck committed
125

126
	return res;
Christian Schäfer's avatar
Christian Schäfer committed
127
128
}

129
130
131
ir_node *new_similar_node(ir_node *const old, ir_node *const block, ir_node **const in)
{
	dbg_info *const dbgi  = get_irn_dbg_info(old);
132
	ir_graph *const irg   = get_irn_irg(old);
133
134
135
136
137
138
139
140
	ir_op    *const op    = get_irn_op(old);
	ir_mode  *const mode  = get_irn_mode(old);
	int       const arity = get_irn_arity(old);
	ir_node  *const n     = new_ir_node(dbgi, irg, block, op, mode, arity, in);
	copy_node_attr(irg, old, n);
	return n;
}

141
142
int (get_irn_arity)(const ir_node *node)
{
143
	return get_irn_arity_(node);
144
145
}

146
void set_irn_in(ir_node *const node, int const arity, ir_node *const *const in)
147
{
148
149
	assert(node != NULL && node->kind == k_ir_node);
	assert(arity >= 0);
Matthias Braun's avatar
Matthias Braun committed
150
151
#ifndef NDEBUG
	for (int i = 0; i < arity; ++i) {
yb9976's avatar
yb9976 committed
152
		assert(in[i] != NULL && in[i]->kind == k_ir_node);
153
154
	}
#endif
155

Matthias Braun's avatar
Matthias Braun committed
156
157
158
	ir_graph  *irg     = get_irn_irg(node);
	ir_node ***pOld_in = &node->in;
	int        i;
159
	for (i = 0; i < arity; i++) {
160
		if (i < (int)ARR_LEN(*pOld_in)-1)
Michael Beck's avatar
Michael Beck committed
161
			edges_notify_edge(node, i, in[i], (*pOld_in)[i+1], irg);
162
		else
Michael Beck's avatar
Michael Beck committed
163
			edges_notify_edge(node, i, in[i], NULL,            irg);
164
	}
165
	for (;i < (int)ARR_LEN(*pOld_in)-1; i++) {
Michael Beck's avatar
Michael Beck committed
166
		edges_notify_edge(node, i, NULL, (*pOld_in)[i+1], irg);
167
168
	}

169
	if (arity != (int)ARR_LEN(*pOld_in) - 1) {
Michael Beck's avatar
Michael Beck committed
170
		ir_node * block = (*pOld_in)[0];
171
		*pOld_in = NEW_ARR_D(ir_node*, get_irg_obstack(irg), arity + 1);
Michael Beck's avatar
Michael Beck committed
172
		(*pOld_in)[0] = block;
173
	}
174
	fix_backedges(get_irg_obstack(irg), node);
175

Christoph Mallon's avatar
Christoph Mallon committed
176
	MEMCPY(*pOld_in + 1, in, arity);
177
178

	/* update irg flags */
179
	clear_irg_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_OUTS | IR_GRAPH_PROPERTY_CONSISTENT_LOOPINFO);
180
181
}

182
183
ir_node *(get_irn_n)(const ir_node *node, int n)
{
184
	return get_irn_n_(node, n);
Christian Schäfer's avatar
Christian Schäfer committed
185
186
}

187
188
void set_irn_n(ir_node *node, int n, ir_node *in)
{
189
	ir_graph *irg = get_irn_irg(node);
190
191
192
193
	assert(node && node->kind == k_ir_node);
	assert(-1 <= n);
	assert(n < get_irn_arity(node));
	assert(in && in->kind == k_ir_node);
194
	assert(!is_Deleted(in));
195
196
197
198
199

	/* 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 */
200
	edges_notify_edge(node, n, in, node->in[n + 1], irg);
201
202

	node->in[n + 1] = in;
203
204

	/* update irg flags */
205
	clear_irg_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_OUTS | IR_GRAPH_PROPERTY_CONSISTENT_LOOPINFO);
Christian Schäfer's avatar
Christian Schäfer committed
206
207
}

208
209
int add_irn_n(ir_node *node, ir_node *in)
{
210
211
	ir_graph *irg = get_irn_irg(node);

212
	assert(is_irn_dynamic(node));
Matthias Braun's avatar
Matthias Braun committed
213
	int pos = ARR_LEN(node->in) - 1;
214
215
216
	ARR_APP1(ir_node *, node->in, in);
	edges_notify_edge(node, pos, node->in[pos + 1], NULL, irg);

217
218
219
	/* Call the hook */
	hook_set_irn_n(node, pos, node->in[pos + 1], NULL);

Matthias Braun's avatar
Matthias Braun committed
220
221
222
	/* update irg flags */
	clear_irg_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_OUTS);

223
224
225
	return pos;
}

226
static void remove_irn_n(ir_node *node, int n)
Matthias Braun's avatar
Matthias Braun committed
227
{
228
229
230
231
232
233
234
235
	ir_graph *const irg   = get_irn_irg(node);
	int       const arity = get_irn_arity(node);
	ir_node  *const last  = node->in[arity];
	if (n != arity - 1) {
		/* Replace by last edge. */
		ir_node **const slot = &node->in[n + 1];
		ir_node  *const pred = *slot;
		*slot = last;
236
		edges_notify_edge(node, n, last, pred, irg);
Matthias Braun's avatar
Matthias Braun committed
237
	}
238
239
	/* Remove last edge. */
	edges_notify_edge(node, arity - 1, NULL, last, irg);
Matthias Braun's avatar
Matthias Braun committed
240
241
242
243
244
245
	ARR_SHRINKLEN(node->in, arity);

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

246
void remove_Sync_n(ir_node *n, int i)
Christoph Mallon's avatar
Christoph Mallon committed
247
{
248
	remove_irn_n(n, i);
Christoph Mallon's avatar
Christoph Mallon committed
249
250
}

251
int (get_irn_n_deps)(const ir_node *node)
252
{
253
	return get_irn_n_deps_(node);
Sebastian Hack's avatar
Sebastian Hack committed
254
255
}

256
257
ir_node *(get_irn_dep)(const ir_node *node, int pos)
{
258
	return get_irn_dep_(node, pos);
Sebastian Hack's avatar
Sebastian Hack committed
259
260
}

261
void set_irn_dep(ir_node *node, int pos, ir_node *dep)
262
{
Matthias Braun's avatar
Matthias Braun committed
263
264
	assert(node->deps != NULL);
	assert(pos >= 0 && pos < (int)ARR_LEN(node->deps));
265
	assert(dep != NULL);
Matthias Braun's avatar
Matthias Braun committed
266
	ir_node *old = node->deps[pos];
267
	node->deps[pos] = dep;
Matthias Braun's avatar
Matthias Braun committed
268
	ir_graph *irg = get_irn_irg(node);
269
270
	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
271
272
}

273
void add_irn_dep(ir_node *node, ir_node *dep)
274
{
275
	assert(dep != NULL);
Matthias Braun's avatar
Matthias Braun committed
276
	if (node->deps == NULL)
277
278
		node->deps = NEW_ARR_F(ir_node *, 0);
	ARR_APP1(ir_node*, node->deps, dep);
Matthias Braun's avatar
Matthias Braun committed
279
	ir_graph *irg = get_irn_irg(node);
280
281
	if (edges_activated_kind(irg, EDGE_KIND_DEP))
		edges_notify_edge_kind(node, ARR_LEN(node->deps)-1, dep, NULL, EDGE_KIND_DEP, irg);
282
}
Sebastian Hack's avatar
Sebastian Hack committed
283

284
285
286
287
288
void delete_irn_dep(ir_node *node, ir_node *dep)
{
	if (node->deps == NULL)
		return;

Matthias Braun's avatar
Matthias Braun committed
289
	for (size_t i = 0, n_deps = ARR_LEN(node->deps); i < n_deps; ++i) {
290
291
292
293
294
		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
295
296
297
298
		}
	}
}

Christoph Mallon's avatar
Christoph Mallon committed
299
void add_irn_deps(ir_node *const tgt, ir_node const *const src)
300
{
Matthias Braun's avatar
Matthias Braun committed
301
	for (int i = 0, n = get_irn_n_deps(src); i < n; ++i)
Sebastian Hack's avatar
Sebastian Hack committed
302
303
304
305
		add_irn_dep(tgt, get_irn_dep(src, i));
}


306
307
ir_mode *(get_irn_mode)(const ir_node *node)
{
308
	return get_irn_mode_(node);
Christian Schäfer's avatar
Christian Schäfer committed
309
310
}

311
312
void (set_irn_mode)(ir_node *node, ir_mode *mode)
{
313
	set_irn_mode_(node, mode);
Till Riedel's avatar
Till Riedel committed
314
315
}

316
317
ir_op *(get_irn_op)(const ir_node *node)
{
318
	return get_irn_op_(node);
Christian Schäfer's avatar
Christian Schäfer committed
319
320
}

321
322
void (set_irn_op)(ir_node *node, ir_op *op)
{
323
	set_irn_op_(node, op);
Christian Schäfer's avatar
Christian Schäfer committed
324
325
}

326
327
unsigned (get_irn_opcode)(const ir_node *node)
{
328
	return get_irn_opcode_(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
329
330
}

331
332
const char *get_irn_opname(const ir_node *node)
{
333
	return get_id_str(node->op->name);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
334
335
}

336
337
ident *get_irn_opident(const ir_node *node)
{
338
339
	assert(node);
	return node->op->name;
340
341
}

342
343
ir_visited_t (get_irn_visited)(const ir_node *node)
{
344
	return get_irn_visited_(node);
345
346
}

347
348
void (set_irn_visited)(ir_node *node, ir_visited_t visited)
{
349
	set_irn_visited_(node, visited);
Christian Schäfer's avatar
Christian Schäfer committed
350
}
351

352
353
void (mark_irn_visited)(ir_node *node)
{
354
	mark_irn_visited_(node);
355
356
}

357
358
int (irn_visited)(const ir_node *node)
{
359
	return irn_visited_(node);
360
361
}

362
363
int (irn_visited_else_mark)(ir_node *node)
{
364
	return irn_visited_else_mark_(node);
365
366
}

367
368
void (set_irn_link)(ir_node *node, void *link)
{
369
	set_irn_link_(node, link);
Christian Schäfer's avatar
Christian Schäfer committed
370
371
}

372
373
void *(get_irn_link)(const ir_node *node)
{
374
	return get_irn_link_(node);
Christian Schäfer's avatar
Christian Schäfer committed
375
376
}

377
378
op_pin_state (get_irn_pinned)(const ir_node *node)
{
379
	return get_irn_pinned_(node);
380
381
}

382
383
void set_irn_pinned(ir_node *node, op_pin_state state)
{
Matthias Braun's avatar
Matthias Braun committed
384
	assert(get_op_pinned(get_irn_op(node)) >= op_pin_state_exc_pinned);
385
	assert(state == op_pin_state_pinned || state == op_pin_state_floats);
Michael Beck's avatar
Michael Beck committed
386

387
	node->attr.except.pin_state = state;
Michael Beck's avatar
Michael Beck committed
388
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
389

390
391
long get_irn_node_nr(const ir_node *node)
{
Matthias Braun's avatar
Matthias Braun committed
392
	assert(node->kind == k_ir_node);
393
	return node->node_nr;
394
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
395

396
397
void *(get_irn_generic_attr)(ir_node *node)
{
398
	assert(node->kind == k_ir_node);
399
	return get_irn_generic_attr_(node);
400
401
}

402
403
const void *(get_irn_generic_attr_const)(const ir_node *node)
{
404
	assert(node->kind == k_ir_node);
405
	return get_irn_generic_attr_const_(node);
406
407
}

408
409
unsigned (get_irn_idx)(const ir_node *node)
{
410
	assert(node->kind == k_ir_node);
411
	return get_irn_idx_(node);
412
413
}

414
ir_node *(get_nodes_block)(const ir_node *node)
415
{
416
	return get_nodes_block_(node);
Christian Schäfer's avatar
Christian Schäfer committed
417
418
}

419
420
void set_nodes_block(ir_node *node, ir_node *block)
{
421
	assert(!is_Block(node));
422
	set_irn_n(node, -1, block);
Christian Schäfer's avatar
Christian Schäfer committed
423
424
}

425
426
ir_node *(get_Block_cfgpred_block)(const ir_node *node, int pos)
{
427
	return get_Block_cfgpred_block_(node, pos);
428
429
}

430
431
int get_Block_matured(const ir_node *node)
{
432
	assert(is_Block(node));
Michael Beck's avatar
Michael Beck committed
433
	return (int)node->attr.block.is_matured;
Christian Schäfer's avatar
Christian Schäfer committed
434
435
}

436
437
void set_Block_matured(ir_node *node, int matured)
{
438
	assert(is_Block(node));
Michael Beck's avatar
Michael Beck committed
439
	node->attr.block.is_matured = matured;
Christian Schäfer's avatar
Christian Schäfer committed
440
}
Michael Beck's avatar
Michael Beck committed
441

442
443
ir_visited_t (get_Block_block_visited)(const ir_node *node)
{
444
	return get_Block_block_visited_(node);
Christian Schäfer's avatar
Christian Schäfer committed
445
446
}

447
448
void (set_Block_block_visited)(ir_node *node, ir_visited_t visit)
{
449
	set_Block_block_visited_(node, visit);
Christian Schäfer's avatar
Christian Schäfer committed
450
451
}

452
453
void (mark_Block_block_visited)(ir_node *node)
{
454
	mark_Block_block_visited_(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
455
456
}

457
458
int (Block_block_visited)(const ir_node *node)
{
459
	return Block_block_visited_(node);
Matthias Braun's avatar
Matthias Braun committed
460
461
}

462
463
ir_entity *create_Block_entity(ir_node *block)
{
464
	ir_entity *entity;
Michael Beck's avatar
Michael Beck committed
465
	assert(is_Block(block));
466
467
468

	entity = block->attr.block.entity;
	if (entity == NULL) {
Matthias Braun's avatar
Matthias Braun committed
469
470
		ir_label_t nr = get_irp_next_label_nr();
		entity = new_label_entity(nr);
471
472
		set_entity_visibility(entity, ir_visibility_local);
		set_entity_linkage(entity, IR_LINKAGE_CONSTANT);
473
474
475
476
477
		set_entity_compiler_generated(entity, 1);

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

480
481
ir_node *(get_Block_phis)(const ir_node *block)
{
482
	return get_Block_phis_(block);
483
484
}

485
486
void (set_Block_phis)(ir_node *block, ir_node *phi)
{
487
	set_Block_phis_(block, phi);
488
489
}

490
491
void (add_Block_phi)(ir_node *block, ir_node *phi)
{
492
	add_Block_phi_(block, phi);
Michael Beck's avatar
Michael Beck committed
493
494
}

495
496
unsigned (get_Block_mark)(const ir_node *block)
{
497
	return get_Block_mark_(block);
Michael Beck's avatar
Michael Beck committed
498
499
}

500
501
void (set_Block_mark)(ir_node *block, unsigned mark)
{
502
	set_Block_mark_(block, mark);
Michael Beck's avatar
Michael Beck committed
503
504
}

505
506
void add_End_keepalive(ir_node *end, ir_node *ka)
{
507
	assert(is_End(end));
508
	add_irn_n(end, ka);
509
510
}

511
512
void set_End_keepalives(ir_node *end, int n, ir_node *in[])
{
513
	/* notify that edges are deleted */
Matthias Braun's avatar
Matthias Braun committed
514
515
	ir_graph *irg = get_irn_irg(end);
	for (size_t e = END_KEEPALIVE_OFFSET; e < ARR_LEN(end->in) - 1; ++e) {
516
		edges_notify_edge(end, e, NULL, end->in[e + 1], irg);
517
518
	}
	ARR_RESIZE(ir_node *, end->in, n + 1 + END_KEEPALIVE_OFFSET);
519

Matthias Braun's avatar
Matthias Braun committed
520
	for (int i = 0; i < n; ++i) {
521
		end->in[1 + END_KEEPALIVE_OFFSET + i] = in[i];
522
		edges_notify_edge(end, END_KEEPALIVE_OFFSET + i, end->in[1 + END_KEEPALIVE_OFFSET + i], NULL, irg);
523
	}
524
525

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

529
530
531
532
533
void remove_End_n(ir_node *n, int idx)
{
	remove_irn_n(n, idx);
}

Matthias Braun's avatar
Matthias Braun committed
534
void remove_End_keepalive(ir_node *end, const ir_node *irn)
535
{
536
	assert(END_KEEPALIVE_OFFSET == 0);
537
	foreach_irn_in_r(end, i, ka) {
538
539
		if (ka == irn) {
			remove_irn_n(end, i);
Christoph Mallon's avatar
Christoph Mallon committed
540
			return;
541
		}
542
	}
543
}
544

545
void remove_keep_alive(const ir_node *irn)
546
547
548
549
550
551
{
	ir_graph *irg = get_irn_irg(irn);
	ir_node  *end = get_irg_end(irg);

	for (int i = get_End_n_keepalives(end);;) {
		if (i-- == 0)
552
			return;
553
554
555
556

		ir_node *old_ka = end->in[1 + END_KEEPALIVE_OFFSET + i];

		/* find irn */
557
		if (old_ka == irn)
558
559
560
561
			set_irn_n(end, END_KEEPALIVE_OFFSET+i, new_r_Bad(irg, get_irn_mode(irn)));
	}
}

562
563
void remove_End_Bads_and_doublets(ir_node *end)
{
Matthias Braun's avatar
Matthias Braun committed
564
	int n = get_End_n_keepalives(end);
565
566
567
	if (n <= 0)
		return;

Matthias Braun's avatar
Matthias Braun committed
568
569
	ir_graph *irg = get_irn_irg(end);
	pset_new_t keeps;
570
571
	pset_new_init(&keeps);

Matthias Braun's avatar
Matthias Braun committed
572
573
	bool changed = false;
	for (int idx = n; idx-- > 0; ) {
574
575
		ir_node *ka = get_End_keepalive(end, idx);

Michael Beck's avatar
Michael Beck committed
576
		if (is_Bad(ka) || is_NoMem(ka) || pset_new_contains(&keeps, ka)) {
577
			changed = true;
578
			remove_irn_n(end, idx - END_KEEPALIVE_OFFSET);
579
580
581
582
583
584
			--n;
		} else {
			pset_new_insert(&keeps, ka);
		}
	}
	pset_new_destroy(&keeps);
585

Matthias Braun's avatar
Matthias Braun committed
586
	if (changed)
587
		clear_irg_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_OUTS);
588
589
}

590
591
void free_End(ir_node *end)
{
592
	assert(is_End(end));
593
594
595
596
	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 ... */
597
598
}

599
600
int (is_Const_null)(const ir_node *node)
{
601
	return is_Const_null_(node);
602
603
}

604
605
int (is_Const_one)(const ir_node *node)
{
606
	return is_Const_one_(node);
607
608
}

609
610
int (is_Const_all_one)(const ir_node *node)
{
611
	return is_Const_all_one_(node);
Sebastian Hack's avatar
Sebastian Hack committed
612
613
}

614
615
const char *get_builtin_kind_name(ir_builtin_kind kind)
{
616
#define X(a)    case a: return #a
617
	switch (kind) {
Michael Beck's avatar
Michael Beck committed
618
		X(ir_bk_trap);
619
		X(ir_bk_debugbreak);
620
		X(ir_bk_return_address);
621
		X(ir_bk_frame_address);
622
		X(ir_bk_prefetch);
Michael Beck's avatar
Michael Beck committed
623
624
625
626
627
628
		X(ir_bk_ffs);
		X(ir_bk_clz);
		X(ir_bk_ctz);
		X(ir_bk_popcount);
		X(ir_bk_parity);
		X(ir_bk_bswap);
629
630
		X(ir_bk_inport);
		X(ir_bk_outport);
631
		X(ir_bk_saturating_increment);
632
		X(ir_bk_compare_swap);
Matthias Braun's avatar
Matthias Braun committed
633
		X(ir_bk_may_alias);
634
635
636
637
638
	}
	return "<unknown>";
#undef X
}

639
640
641
ir_entity *get_Call_callee(const ir_node *node)
{
	ir_node *ptr = get_Call_ptr(node);
642
	if (!is_Address(ptr))
643
		return NULL;
644
	ir_entity *entity = get_Address_entity(ptr);
645
646
	/* some (corner case/pointless) graphs can have non-method entities as
	 * call pointers */
647
	if (!is_method_entity(entity) && !is_alias_entity(entity))
648
649
650
651
		return NULL;
	return entity;
}

652
ir_node *get_binop_left(const ir_node *node)
653
{
654
	assert(is_binop(node));
655
	return get_irn_n(node, node->op->op_index);
656
657
}

658
void set_binop_left(ir_node *node, ir_node *left)
659
{
660
	assert(is_binop(node));
661
	set_irn_n(node, node->op->op_index, left);
662
663
}

664
ir_node *get_binop_right(const ir_node *node)
665
{
666
	assert(is_binop(node));
667
	return get_irn_n(node, node->op->op_index + 1);
668
669
}

670
void set_binop_right(ir_node *node, ir_node *right)
671
{
672
	assert(is_binop(node));
673
	set_irn_n(node, node->op->op_index + 1, right);
674
675
}

676
677
ir_node *(get_Phi_next)(const ir_node *phi)
{
678
	return get_Phi_next_(phi);
679
680
}

681
682
void (set_Phi_next)(ir_node *phi, ir_node *next)
{
683
	set_Phi_next_(phi, next);
684
}
685

686
687
int is_memop(const ir_node *node)
{
688
	return is_op_uses_memory(get_irn_op(node));
689
690
}

691
692
ir_node *get_memop_mem(const ir_node *node)
{
693
	const ir_op *op = get_irn_op(node);
694
	assert(is_memop(node));
695
	return get_irn_n(node, op->memory_index);
696
697
}

698
699
void set_memop_mem(ir_node *node, ir_node *mem)
{
700
	const ir_op *op = get_irn_op(node);
701
	assert(is_memop(node));
702
	set_irn_n(node, op->memory_index, mem);
703
704
}

705
706
void add_Sync_pred(ir_node *node, ir_node *pred)
{
707
	assert(is_Sync(node));
708
	add_irn_n(node, pred);
Michael Beck's avatar
Michael Beck committed
709
710
}

Matthias Braun's avatar
Matthias Braun committed
711
712
713
714
int is_x_except_Proj(const ir_node *node)
{
	if (!is_Proj(node))
		return false;
Matthias Braun's avatar
Matthias Braun committed
715
	ir_node *pred = get_Proj_pred(node);
Matthias Braun's avatar
Matthias Braun committed
716
717
	if (!is_fragile_op(pred))
		return false;
718
	return get_Proj_num(node) == pred->op->pn_x_except;
Matthias Braun's avatar
Matthias Braun committed
719
720
721
722
723
724
}

int is_x_regular_Proj(const ir_node *node)
{
	if (!is_Proj(node))
		return false;
Matthias Braun's avatar
Matthias Braun committed
725
	ir_node *pred = get_Proj_pred(node);
Matthias Braun's avatar
Matthias Braun committed
726
727
	if (!is_fragile_op(pred))
		return false;
728
	return get_Proj_num(node) == pred->op->pn_x_regular;
Matthias Braun's avatar
Matthias Braun committed
729
730
}

731
732
733
734
735
736
737
738
739
740
741
742
743
744
void ir_set_throws_exception(ir_node *node, int throws_exception)
{
	except_attr *attr = &node->attr.except;
	assert(is_fragile_op(node));
	attr->throws_exception = throws_exception;
}

int ir_throws_exception(const ir_node *node)
{
	const except_attr *attr = &node->attr.except;
	assert(is_fragile_op(node));
	return attr->throws_exception;
}

745
size_t get_ASM_n_output_constraints(const ir_node *node)
746
{
747
	assert(is_ASM(node));
748
	return ARR_LEN(node->attr.assem.output_constraints);
Michael Beck's avatar
Michael Beck committed
749
}
750

751
size_t get_ASM_n_clobbers(const ir_node *node)
752
{
753
	assert(is_ASM(node));
754
	return ARR_LEN(node->attr.assem.clobbers);
Michael Beck's avatar
Michael Beck committed
755
756
}

757
ir_graph *(get_irn_irg)(const ir_node *node)
758
{
759
	return get_irn_irg_(node);
760
761
}

762
ir_node *skip_Proj(ir_node *node)
763
{
764
765
766
	if (is_Proj(node))
		node = get_Proj_pred(node);
	return node;
Matthias Braun's avatar
Matthias Braun committed
767
768
}

Matthias Braun's avatar
Matthias Braun committed
769
const ir_node *skip_Proj_const(const ir_node *node)
770
{
771
772
773
	if (is_Proj(node))
		node = get_Proj_pred(node);
	return node;
Christian Schäfer's avatar
Christian Schäfer committed
774
775
}

776
ir_node *skip_Tuple(ir_node *node)
777
{
778
restart:
779
	if (is_Proj(node)) {
Matthias Braun's avatar
Matthias Braun committed
780
		ir_node *pred = get_Proj_pred(node);
781

782
		if (is_Proj(pred)) { /* nested Tuple ? */
783
784
		    pred = skip_Tuple(pred);

785
			if (is_Tuple(pred)) {
786
				node = get_Tuple_pred(pred, get_Proj_num(node));
787
788
				goto restart;
			}
789
		} else if (is_Tuple(pred)) {
790
			node = get_Tuple_pred(pred, get_Proj_num(node));
791
792
793
794
			goto restart;
		}
	}
	return node;
795
796
}

797
798
ir_node *skip_Pin(ir_node *node)
{
Michael Beck's avatar