irnode.c 69.4 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
 * Copyright (C) 1995-2007 University of Karlsruhe.  All right reserved.
 *
 * This file is part of libFirm.
 *
 * This file may be distributed and/or modified under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation and appearing in the file LICENSE.GPL included in the
 * packaging of this file.
 *
 * Licensees holding valid libFirm Professional Edition licenses may use
 * this file in accordance with the libFirm Commercial License.
 * Agreement provided with the Software.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE.
 */

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

#ifdef HAVE_STRING_H
# include <string.h>
Boris Boesler's avatar
added    
Boris Boesler committed
32
33
#endif

34
#include "ident.h"
Götz Lindenmaier's avatar
Götz Lindenmaier committed
35
#include "irnode_t.h"
Götz Lindenmaier's avatar
Götz Lindenmaier committed
36
#include "irgraph_t.h"
Götz Lindenmaier's avatar
Götz Lindenmaier committed
37
#include "irmode_t.h"
38
#include "irbackedge_t.h"
39
#include "irdump.h"
40
#include "irop_t.h"
41
#include "irprog_t.h"
Sebastian Hack's avatar
Sebastian Hack committed
42
#include "iredgekinds.h"
Sebastian Hack's avatar
Sebastian Hack committed
43
#include "iredges_t.h"
Götz Lindenmaier's avatar
Götz Lindenmaier committed
44

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

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

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

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

Michael Beck's avatar
Michael Beck committed
72
/*
73
 * Calculates the negated (Complement(R)) pnc condition.
Michael Beck's avatar
Michael Beck committed
74
 */
75
int get_negated_pnc(int pnc, ir_mode *mode) {
76
	pnc ^= pn_Cmp_True;
77

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

82
	return pnc;
Christian Schäfer's avatar
Christian Schäfer committed
83
84
}

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

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

94
	return code;
Michael Beck's avatar
Michael Beck committed
95
96
}

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


110
/* register new space for every node */
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
}


Christian Schäfer's avatar
Christian Schäfer committed
121
void
122
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
 * irnode constructor.
 * Create a new irnode in irg, with an op, mode, arity and
 * some incoming irnodes.
131
132
 * If arity is negative, a node with a dynamic array is created.
 */
133
ir_node *
134
135
new_ir_node(dbg_info *db, ir_graph *irg, ir_node *block, ir_op *op, ir_mode *mode,
            int arity, ir_node **in)
Christian Schäfer's avatar
Christian Schäfer committed
136
{
137
138
139
	ir_node *res;
	size_t node_size = offsetof(ir_node, attr) + op->attr_size + firm_add_node_size;
	char *p;
140
	int i;
141
142

	assert(irg && op && mode);
143
	p = obstack_alloc(irg->obst, node_size);
144
	memset(p, 0, node_size);
145
	res = (ir_node *)(p + firm_add_node_size);
146
147
148
149
150
151
152
153
154
155

	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) {
156
		res->in = NEW_ARR_F(ir_node *, 1);  /* 1: space for block */
157
	} else {
158
159
		res->in = NEW_ARR_D(ir_node *, irg->obst, (arity+1));
		memcpy(&res->in[1], in, sizeof(ir_node *) * arity);
160
161
162
163
164
	}

	res->in[0] = block;
	set_irn_dbg_info(res, db);
	res->out = NULL;
Götz Lindenmaier's avatar
Götz Lindenmaier committed
165
166

#ifdef DEBUG_libfirm
167
	res->node_nr = get_irp_new_node_nr();
Götz Lindenmaier's avatar
Götz Lindenmaier committed
168
169
#endif

170
	for (i = 0; i < EDGE_KIND_LAST; ++i)
171
		INIT_LIST_HEAD(&res->edge_info[i].outs_head);
172

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

178
	hook_new_node(irg, res);
Michael Beck's avatar
Michael Beck committed
179

180
	return res;
Christian Schäfer's avatar
Christian Schäfer committed
181
182
}

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

Sebastian Felis's avatar
Sebastian Felis committed
185
int
186
(is_ir_node)(const void *thing) {
187
	return _is_ir_node(thing);
Sebastian Felis's avatar
Sebastian Felis committed
188
189
}

190
int
191
(get_irn_intra_arity)(const ir_node *node) {
192
	return _get_irn_intra_arity(node);
Christian Schäfer's avatar
Christian Schäfer committed
193
194
}

195
int
196
(get_irn_inter_arity)(const ir_node *node) {
197
	return _get_irn_inter_arity(node);
198
199
}

200
int (*_get_irn_arity)(const ir_node *node) = _get_irn_intra_arity;
201

202
int
203
(get_irn_arity)(const ir_node *node) {
204
	return _get_irn_arity(node);
205
206
}

207
208
209
210
211
212
/* 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. */
213
ir_node **
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
get_irn_in(const ir_node *node) {
	assert(node);
	if (get_interprocedural_view()) { /* handle Filter and Block specially */
		if (get_irn_opcode(node) == iro_Filter) {
			assert(node->attr.filter.in_cg);
			return node->attr.filter.in_cg;
		} else if (get_irn_opcode(node) == iro_Block && node->attr.block.in_cg) {
			return node->attr.block.in_cg;
		}
		/* else fall through */
	}
	return node->in;
}

void
set_irn_in(ir_node *node, int arity, ir_node **in) {
	int i;
	ir_node *** arr;
	ir_graph *irg = current_ir_graph;
	assert(node);
	if (get_interprocedural_view()) { /* handle Filter and Block specially */
		if (get_irn_opcode(node) == iro_Filter) {
			assert(node->attr.filter.in_cg);
			arr = &node->attr.filter.in_cg;
		} else if (get_irn_opcode(node) == iro_Block && node->attr.block.in_cg) {
			arr = &node->attr.block.in_cg;
		} else {
			arr = &node->in;
		}
	} else {
		arr = &node->in;
	}

	for (i = 0; i < arity; i++) {
		if (i < ARR_LEN(*arr)-1)
			edges_notify_edge(node, i, in[i], (*arr)[i+1], irg);
		else
			edges_notify_edge(node, i, in[i], NULL,        irg);
	}
	for(;i < ARR_LEN(*arr)-1; i++) {
		edges_notify_edge(node, i, NULL, (*arr)[i+1], irg);
	}

	if (arity != ARR_LEN(*arr) - 1) {
		ir_node * block = (*arr)[0];
		*arr = NEW_ARR_D(ir_node *, irg->obst, arity + 1);
		(*arr)[0] = block;
	}
	fix_backedges(irg->obst, node);

	memcpy((*arr) + 1, in, sizeof(ir_node *) * arity);
265
266
}

267
ir_node *
Sebastian Hack's avatar
Sebastian Hack committed
268
(get_irn_intra_n)(const ir_node *node, int n) {
269
	return _get_irn_intra_n (node, n);
270
271
}

272
ir_node *
Sebastian Hack's avatar
Sebastian Hack committed
273
(get_irn_inter_n)(const ir_node *node, int n) {
274
	return _get_irn_inter_n (node, n);
275
276
}

277
ir_node *(*_get_irn_n)(const ir_node *node, int n) = _get_irn_intra_n;
278

279
ir_node *
Sebastian Hack's avatar
Sebastian Hack committed
280
(get_irn_n)(const ir_node *node, int n) {
281
	return _get_irn_n(node, n);
Christian Schäfer's avatar
Christian Schäfer committed
282
283
}

284
void
285
set_irn_n(ir_node *node, int n, ir_node *in) {
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
	assert(node && node->kind == k_ir_node);
	assert(-1 <= n);
	assert(n < get_irn_arity(node));
	assert(in && in->kind == k_ir_node);

	if ((n == -1) && (get_irn_opcode(node) == iro_Filter)) {
		/* Change block pred in both views! */
		node->in[n + 1] = in;
		assert(node->attr.filter.in_cg);
		node->attr.filter.in_cg[n + 1] = in;
		return;
	}
	if (get_interprocedural_view()) { /* handle Filter and Block specially */
		if (get_irn_opcode(node) == iro_Filter) {
			assert(node->attr.filter.in_cg);
			node->attr.filter.in_cg[n + 1] = in;
			return;
		} else if (get_irn_opcode(node) == iro_Block && node->attr.block.in_cg) {
			node->attr.block.in_cg[n + 1] = in;
			return;
		}
		/* else fall through */
	}

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

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

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

319
int add_irn_n(ir_node *node, ir_node *in) {
320
321
322
323
324
325
326
327
	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);

328
329
330
	/* Call the hook */
	hook_set_irn_n(node, pos, node->in[pos + 1], NULL);

331
332
333
	return pos;
}

Sebastian Hack's avatar
Sebastian Hack committed
334
int
335
(get_irn_deps)(const ir_node *node) {
Sebastian Hack's avatar
Sebastian Hack committed
336
337
338
339
	return _get_irn_deps(node);
}

ir_node *
340
(get_irn_dep)(const ir_node *node, int pos) {
Sebastian Hack's avatar
Sebastian Hack committed
341
342
343
344
	return _get_irn_dep(node, pos);
}

void
345
(set_irn_dep)(ir_node *node, int pos, ir_node *dep) {
Sebastian Hack's avatar
Sebastian Hack committed
346
347
348
	_set_irn_dep(node, pos, dep);
}

349
int add_irn_dep(ir_node *node, ir_node *dep) {
Sebastian Hack's avatar
Sebastian Hack committed
350
351
352
353
354
	int res = 0;

	if (node->deps == NULL) {
		node->deps = NEW_ARR_F(ir_node *, 1);
		node->deps[0] = dep;
355
	} else {
Sebastian Hack's avatar
Sebastian Hack committed
356
357
358
359
360
361
362
363
364
365
366
		int i, n;
		int first_zero = -1;

		for(i = 0, n = ARR_LEN(node->deps); i < n; ++i) {
			if(node->deps[i] == NULL)
				first_zero = i;

			if(node->deps[i] == dep)
				return i;
		}

367
		if (first_zero >= 0) {
Sebastian Hack's avatar
Sebastian Hack committed
368
369
			node->deps[first_zero] = dep;
			res = first_zero;
370
		} else {
Sebastian Hack's avatar
Sebastian Hack committed
371
372
373
374
375
376
377
378
379
380
			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;
}

381
void add_irn_deps(ir_node *tgt, ir_node *src) {
Sebastian Hack's avatar
Sebastian Hack committed
382
383
	int i, n;

384
	for (i = 0, n = get_irn_deps(src); i < n; ++i)
Sebastian Hack's avatar
Sebastian Hack committed
385
386
387
388
		add_irn_dep(tgt, get_irn_dep(src, i));
}


389
ir_mode *
390
(get_irn_mode)(const ir_node *node) {
391
	return _get_irn_mode(node);
Christian Schäfer's avatar
Christian Schäfer committed
392
393
}

394
void
395
396
(set_irn_mode)(ir_node *node, ir_mode *mode) {
	_set_irn_mode(node, mode);
Till Riedel's avatar
Till Riedel committed
397
398
}

399
modecode
400
401
402
get_irn_modecode(const ir_node *node) {
	assert(node);
	return node->mode->code;
Christian Schäfer's avatar
Christian Schäfer committed
403
404
}

405
/** Gets the string representation of the mode .*/
406
const char *
407
408
409
get_irn_modename(const ir_node *node) {
	assert(node);
	return get_mode_name(node->mode);
410
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
411

412
ident *
413
414
415
get_irn_modeident(const ir_node *node) {
	assert(node);
	return get_mode_ident(node->mode);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
416
417
}

418
ir_op *
419
(get_irn_op)(const ir_node *node) {
420
	return _get_irn_op(node);
Christian Schäfer's avatar
Christian Schäfer committed
421
422
423
}

/* should be private to the library: */
424
void
425
426
(set_irn_op)(ir_node *node, ir_op *op) {
	_set_irn_op(node, op);
Christian Schäfer's avatar
Christian Schäfer committed
427
428
}

Matthias Braun's avatar
Matthias Braun committed
429
unsigned
430
431
(get_irn_opcode)(const ir_node *node) {
	return _get_irn_opcode(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
432
433
}

434
const char *
435
436
get_irn_opname(const ir_node *node) {
	assert(node);
437
	if (is_Phi0(node)) return "Phi0";
438
	return get_id_str(node->op->name);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
439
440
}

441
ident *
442
443
444
get_irn_opident(const ir_node *node) {
	assert(node);
	return node->op->name;
445
446
}

447
unsigned long
448
449
(get_irn_visited)(const ir_node *node) {
	return _get_irn_visited(node);
450
451
}

452
void
453
454
(set_irn_visited)(ir_node *node, unsigned long visited) {
	_set_irn_visited(node, visited);
Christian Schäfer's avatar
Christian Schäfer committed
455
}
456

457
void
458
(mark_irn_visited)(ir_node *node) {
459
	_mark_irn_visited(node);
460
461
}

462
int
463
(irn_not_visited)(const ir_node *node) {
464
	return _irn_not_visited(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
465
466
}

467
int
468
(irn_visited)(const ir_node *node) {
469
	return _irn_visited(node);
470
471
}

472
void
473
(set_irn_link)(ir_node *node, void *link) {
474
	_set_irn_link(node, link);
Christian Schäfer's avatar
Christian Schäfer committed
475
476
}

477
void *
478
(get_irn_link)(const ir_node *node) {
479
	return _get_irn_link(node);
Christian Schäfer's avatar
Christian Schäfer committed
480
481
}

482
483
op_pin_state
(get_irn_pinned)(const ir_node *node) {
484
	return _get_irn_pinned(node);
485
486
}

487
488
op_pin_state
(is_irn_pinned_in_irg) (const ir_node *node) {
489
	return _is_irn_pinned_in_irg(node);
490
491
}

Michael Beck's avatar
Michael Beck committed
492
void set_irn_pinned(ir_node *node, op_pin_state state) {
493
494
495
	/* due to optimization an opt may be turned into a Tuple */
	if (get_irn_op(node) == op_Tuple)
		return;
Michael Beck's avatar
Michael Beck committed
496

497
498
	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
499

500
	node->attr.except.pin_state = state;
Michael Beck's avatar
Michael Beck committed
501
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
502
503
504
505
506

#ifdef DO_HEAPANALYSIS
/* Access the abstract interpretation information of a node.
   Returns NULL if no such information is available. */
struct abstval *get_irn_abst_value(ir_node *n) {
507
	return n->av;
Götz Lindenmaier's avatar
Götz Lindenmaier committed
508
509
510
}
/* Set the abstract interpretation information of a node. */
void set_irn_abst_value(ir_node *n, struct abstval *os) {
511
	n->av = os;
Götz Lindenmaier's avatar
Götz Lindenmaier committed
512
513
}
struct section *firm_get_irn_section(ir_node *n) {
514
	return n->sec;
Götz Lindenmaier's avatar
Götz Lindenmaier committed
515
516
}
void firm_set_irn_section(ir_node *n, struct section *s) {
517
	n->sec = s;
Götz Lindenmaier's avatar
Götz Lindenmaier committed
518
}
519
520
#else
/* Dummies needed for firmjni. */
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
struct abstval *get_irn_abst_value(ir_node *n) {
	(void) n;
	return NULL;
}
void set_irn_abst_value(ir_node *n, struct abstval *os) {
	(void) n;
	(void) os;
}
struct section *firm_get_irn_section(ir_node *n) {
	(void) n;
	return NULL;
}
void firm_set_irn_section(ir_node *n, struct section *s) {
	(void) n;
	(void) s;
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
537
538
539
#endif /* DO_HEAPANALYSIS */


Götz Lindenmaier's avatar
Götz Lindenmaier committed
540
/* Outputs a unique number for this node */
541
long get_irn_node_nr(const ir_node *node) {
542
	assert(node);
543
#ifdef DEBUG_libfirm
544
	return node->node_nr;
545
#else
546
	return (long)PTR_TO_INT(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
547
#endif
548
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
549

550
const_attr *
551
552
get_irn_const_attr(ir_node *node) {
	assert(node->op == op_Const);
553
	return &node->attr.con;
Christian Schäfer's avatar
Christian Schäfer committed
554
555
}

556
long
557
558
559
get_irn_proj_attr(ir_node *node) {
	assert(node->op == op_Proj);
	return node->attr.proj;
Christian Schäfer's avatar
Christian Schäfer committed
560
561
}

562
alloc_attr *
563
564
get_irn_alloc_attr(ir_node *node) {
	assert(node->op == op_Alloc);
565
	return &node->attr.alloc;
Christian Schäfer's avatar
Christian Schäfer committed
566
567
}

568
free_attr *
569
570
get_irn_free_attr(ir_node *node) {
	assert(node->op == op_Free);
571
	return &node->attr.free;
Christian Schäfer's avatar
Christian Schäfer committed
572
573
}

574
symconst_attr *
575
576
get_irn_symconst_attr(ir_node *node) {
	assert(node->op == op_SymConst);
577
	return &node->attr.symc;
Christian Schäfer's avatar
Christian Schäfer committed
578
579
}

Michael Beck's avatar
Michael Beck committed
580
ir_type *
581
582
583
get_irn_call_attr(ir_node *node) {
	assert(node->op == op_Call);
	return node->attr.call.cld_tp = skip_tid(node->attr.call.cld_tp);
Christian Schäfer's avatar
Christian Schäfer committed
584
585
}

586
sel_attr *
587
588
get_irn_sel_attr(ir_node *node) {
	assert(node->op == op_Sel);
589
	return &node->attr.sel;
Christian Schäfer's avatar
Christian Schäfer committed
590
591
}

592
int
593
594
595
get_irn_phi0_attr(ir_node *node) {
	assert(is_Phi0(node));
	return node->attr.phi0.pos;
Christian Schäfer's avatar
Christian Schäfer committed
596
597
}

598
block_attr *
599
600
get_irn_block_attr(ir_node *node) {
	assert(node->op == op_Block);
601
	return &node->attr.block;
Christian Schäfer's avatar
Christian Schäfer committed
602
603
}

604
load_attr *
605
606
get_irn_load_attr(ir_node *node) {
	assert(node->op == op_Load);
607
	return &node->attr.load;
608
609
}

610
store_attr *
611
612
get_irn_store_attr(ir_node *node) {
	assert(node->op == op_Store);
613
	return &node->attr.store;
614
615
}

616
except_attr *
617
618
619
get_irn_except_attr(ir_node *node) {
	assert(node->op == op_Div || node->op == op_Quot ||
	       node->op == op_DivMod || node->op == op_Mod || node->op == op_Call || node->op == op_Alloc);
620
	return &node->attr.except;
621
622
}

623
624
625
void *(get_irn_generic_attr)(ir_node *node) {
	assert(is_ir_node(node));
	return _get_irn_generic_attr(node);
626
627
}

Matthias Braun's avatar
fix    
Matthias Braun committed
628
const void *(get_irn_generic_attr_const)(const ir_node *node) {
629
630
631
632
	assert(is_ir_node(node));
	return _get_irn_generic_attr_const(node);
}

633
unsigned (get_irn_idx)(const ir_node *node) {
634
635
	assert(is_ir_node(node));
	return _get_irn_idx(node);
636
637
}

638
int get_irn_pred_pos(ir_node *node, ir_node *arg) {
639
640
641
642
643
644
	int i;
	for (i = get_irn_arity(node) - 1; i >= 0; i--) {
		if (get_irn_n(node, i) == arg)
			return i;
	}
	return -1;
645
646
}

Christian Schäfer's avatar
Christian Schäfer committed
647
648
649
/** manipulate fields of individual nodes **/

ir_node *
650
651
(get_nodes_block)(const ir_node *node) {
	return _get_nodes_block(node);
Christian Schäfer's avatar
Christian Schäfer committed
652
653
}

654
void
655
set_nodes_block(ir_node *node, ir_node *block) {
656
	node->op->ops.set_block(node, block);
Christian Schäfer's avatar
Christian Schäfer committed
657
658
}

659
660
/* Test whether arbitrary node is frame pointer, i.e. Proj(pn_Start_P_frame_base)
 * from Start.  If so returns frame type, else Null. */
Michael Beck's avatar
Michael Beck committed
661
ir_type *is_frame_pointer(ir_node *n) {
662
663
664
665
666
667
668
	if (is_Proj(n) && (get_Proj_proj(n) == pn_Start_P_frame_base)) {
		ir_node *start = get_Proj_pred(n);
		if (get_irn_op(start) == op_Start) {
			return get_irg_frame_type(get_irn_irg(start));
		}
	}
	return NULL;
669
670
671
672
}

/* Test whether arbitrary node is globals pointer, i.e. Proj(pn_Start_P_globals)
 * from Start.  If so returns global type, else Null. */
Michael Beck's avatar
Michael Beck committed
673
ir_type *is_globals_pointer(ir_node *n) {
674
675
676
677
678
679
680
	if (is_Proj(n) && (get_Proj_proj(n) == pn_Start_P_globals)) {
		ir_node *start = get_Proj_pred(n);
		if (get_irn_op(start) == op_Start) {
			return get_glob_type();
		}
	}
	return NULL;
681
682
}

683
684
685
/* Test whether arbitrary node is tls pointer, i.e. Proj(pn_Start_P_tls)
 * from Start.  If so returns tls type, else Null. */
ir_type *is_tls_pointer(ir_node *n) {
686
687
688
689
690
691
692
	if (is_Proj(n) && (get_Proj_proj(n) == pn_Start_P_globals)) {
		ir_node *start = get_Proj_pred(n);
		if (get_irn_op(start) == op_Start) {
			return get_tls_type();
		}
	}
	return NULL;
693
694
}

695
696
697
/* Test whether arbitrary node is value arg base, i.e. Proj(pn_Start_P_value_arg_base)
 * from Start.  If so returns 1, else 0. */
int is_value_arg_pointer(ir_node *n) {
698
699
700
701
702
	if ((get_irn_op(n) == op_Proj) &&
		(get_Proj_proj(n) == pn_Start_P_value_arg_base) &&
		(get_irn_op(get_Proj_pred(n)) == op_Start))
		return 1;
	return 0;
703
704
}

705
/* Returns an array with the predecessors of the Block. Depending on
706
   the implementation of the graph data structure this can be a copy of
707
708
   the internal representation of predecessors as well as the internal
   array itself. Therefore writing to this array might obstruct the ir. */
709
ir_node **
710
711
712
get_Block_cfgpred_arr(ir_node *node) {
	assert((node->op == op_Block));
	return (ir_node **)&(get_irn_in(node)[1]);
713
714
}

715
int
Christoph Mallon's avatar
Christoph Mallon committed
716
(get_Block_n_cfgpreds)(const ir_node *node) {
717
	return _get_Block_n_cfgpreds(node);
Christian Schäfer's avatar
Christian Schäfer committed
718
719
}

720
ir_node *
721
(get_Block_cfgpred)(ir_node *node, int pos) {
722
	return _get_Block_cfgpred(node, pos);
Christian Schäfer's avatar
Christian Schäfer committed
723
724
}

725
void
726
727
728
set_Block_cfgpred(ir_node *node, int pos, ir_node *pred) {
	assert(node->op == op_Block);
	set_irn_n(node, pos, pred);
Christian Schäfer's avatar
Christian Schäfer committed
729
730
}

731
732
ir_node  *
(get_Block_cfgpred_block)(ir_node *node, int pos) {
733
	return _get_Block_cfgpred_block(node, pos);
734
735
}

736
int
737
738
get_Block_matured(ir_node *node) {
	assert(node->op == op_Block);
Michael Beck's avatar
Michael Beck committed
739
	return (int)node->attr.block.is_matured;
Christian Schäfer's avatar
Christian Schäfer committed
740
741
}

742
void
743
744
set_Block_matured(ir_node *node, int matured) {
	assert(node->op == op_Block);
Michael Beck's avatar
Michael Beck committed
745
	node->attr.block.is_matured = matured;
Christian Schäfer's avatar
Christian Schäfer committed
746
}
Michael Beck's avatar
Michael Beck committed
747

748
unsigned long
Matthias Braun's avatar
Matthias Braun committed
749
(get_Block_block_visited)(const ir_node *node) {
750
	return _get_Block_block_visited(node);
Christian Schäfer's avatar
Christian Schäfer committed
751
752
}

753
void
Michael Beck's avatar
Michael Beck committed
754
(set_Block_block_visited)(ir_node *node, unsigned long visit) {
755
	_set_Block_block_visited(node, visit);
Christian Schäfer's avatar
Christian Schäfer committed
756
757
}

Götz Lindenmaier's avatar
Götz Lindenmaier committed
758
/* For this current_ir_graph must be set. */
759
void
Michael Beck's avatar
Michael Beck committed
760
(mark_Block_block_visited)(ir_node *node) {
761
	_mark_Block_block_visited(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
762
763
}

764
int
Matthias Braun's avatar
Matthias Braun committed
765
(Block_not_block_visited)(const ir_node *node) {
766
	return _Block_not_block_visited(node);
767
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
768

Matthias Braun's avatar
Matthias Braun committed
769
770
771
772
773
int
(Block_block_visited)(const ir_node *node) {
	return _Block_block_visited(node);
}

774
ir_node *
Christian Schäfer's avatar
Christian Schäfer committed
775
get_Block_graph_arr (ir_node *node, int pos) {
776
777
	assert(node->op == op_Block);
	return node->attr.block.graph_arr[pos+1];
Christian Schäfer's avatar
Christian Schäfer committed
778
779
}

780
void
Christian Schäfer's avatar
Christian Schäfer committed
781
set_Block_graph_arr (ir_node *node, int pos, ir_node *value) {
782
783
	assert(node->op == op_Block);
	node->attr.block.graph_arr[pos+1] = value;
Christian Schäfer's avatar
Christian Schäfer committed
784
}
785

Michael Beck's avatar
Michael Beck committed
786
void set_Block_cg_cfgpred_arr(ir_node *node, int arity, ir_node *in[]) {
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
	assert(node->op == op_Block);
	if (node->attr.block.in_cg == NULL || arity != ARR_LEN(node->attr.block.in_cg) - 1) {
		node->attr.block.in_cg = NEW_ARR_D(ir_node *, current_ir_graph->obst, arity + 1);
		node->attr.block.in_cg[0] = NULL;
		node->attr.block.cg_backedge = new_backedge_arr(current_ir_graph->obst, arity);
		{
			/* Fix backedge array.  fix_backedges() operates depending on
			   interprocedural_view. */
			int ipv = get_interprocedural_view();
			set_interprocedural_view(1);
			fix_backedges(current_ir_graph->obst, node);
			set_interprocedural_view(ipv);
		}
	}
	memcpy(node->attr.block.in_cg + 1, in, sizeof(ir_node *) * arity);
802
803
}

Michael Beck's avatar
Michael Beck committed
804
void set_Block_cg_cfgpred(ir_node *node, int pos, ir_node *pred) {
805
806
807
808
	assert(node->op == op_Block &&
	       node->attr.block.in_cg &&
	       0 <= pos && pos < ARR_LEN(node->attr.block.in_cg) - 1);
	node->attr.block.in_cg[pos + 1] = pred;
809
810
}

Michael Beck's avatar
Michael Beck committed
811
ir_node **get_Block_cg_cfgpred_arr(ir_node *node) {
812
813
	assert(node->op == op_Block);
	return node->attr.block.in_cg == NULL ? NULL : node->attr.block.in_cg  + 1;
814
815
}

Michael Beck's avatar
Michael Beck committed
816
int get_Block_cg_n_cfgpreds(ir_node *node) {
817
818
	assert(node->op == op_Block);
	return node->attr.block.in_cg == NULL ? 0 : ARR_LEN(node->attr.block.in_cg) - 1;
819
820
}

Michael Beck's avatar
Michael Beck committed
821
ir_node *get_Block_cg_cfgpred(ir_node *node, int pos) {
822
823
	assert(node->op == op_Block && node->attr.block.in_cg);
	return node->attr.block.in_cg[pos + 1];
824
825
}

Michael Beck's avatar
Michael Beck committed
826
void remove_Block_cg_cfgpred_arr(ir_node *node) {
827
828
	assert(node->op == op_Block);
	node->attr.block.in_cg = NULL;
829
830
}

831
ir_node *(set_Block_dead)(ir_node *block) {
832
	return _set_Block_dead(block);
833
834
835
}

int (is_Block_dead)(const ir_node *block) {
836
	return _is_Block_dead(block);
837
838
}

839
ir_extblk *get_Block_extbb(const ir_node *block) {
Michael Beck's avatar
Michael Beck committed
840
	ir_extblk *res;
841
	assert(is_Block(block));
Michael Beck's avatar
Michael Beck committed
842
843
	res = block->attr.block.extblk;
	assert(res == NULL || is_ir_extbb(res));
844
	return res;
845
846
847
}

void set_Block_extbb(ir_node *block, ir_extblk *extblk) {
848
	assert(is_Block(block));
Michael Beck's avatar
Michael Beck committed
849
	assert(extblk == NULL || is_ir_extbb(extblk));
850
	block->attr.block.extblk = extblk;
851
852
}

853
/* returns the macro block header of a block. */
Michael Beck's avatar
Michael Beck committed
854
855
856
857
858
ir_node *get_Block_MacroBlock(const ir_node *block) {
	assert(is_Block(block));
	return get_irn_n(block, -1);
}

859
860
861
862
863
864
/* returns the graph of a Block. */
ir_graph *get_Block_irg(const ir_node *block) {
	assert(is_Block(block));
	return block->attr.block.irg;
}

865
int
866
get_End_n_keepalives(ir_node *end) {
867
868
	assert(end->op == op_End);
	return (get_irn_arity(end) - END_KEEPALIVE_OFFSET);
869
870
}

871
ir_node *
872
get_End_keepalive(ir_node *end, int pos) {
873
874
	assert(end->op == op_End);
	return get_irn_n(end, pos + END_KEEPALIVE_OFFSET);
875
876
}

877
void
Michael Beck's avatar
Michael Beck committed
878
add_End_keepalive(ir_node *end, ir_node *ka) {
879
	assert(end->op == op_End);
Michael Beck's avatar
Michael Beck committed
880
	assert((is_Phi(ka) || is_Proj(ka) || is_Block(ka) || is_irn_keep(ka)) && "Only Phi, Block or Keep nodes can be kept alive!");
881
	add_irn_n(end, ka);
882
883
}

884
void
885
set_End_keepalive(ir_node *end, int pos, ir_node *ka) {
886
887
	assert(end->op == op_End);
	set_irn_n(end, pos + END_KEEPALIVE_OFFSET, ka);
888
889
}

890
891
/* Set new keep-alives */
void set_End_keepalives(ir_node *end, int n, ir_node *in[]) {
892
893
	int i;
	ir_graph *irg = get_irn_irg(end);
894

895
	/* notify that edges are deleted */
896
897
	for (i = END_KEEPALIVE_OFFSET; i < ARR_LEN(end->in) - 1; ++i) {
		edges_notify_edge(end, i, NULL, end->in[i + 1], irg);
898
899
	}
	ARR_RESIZE(ir_node *, end->in, n + 1 + END_KEEPALIVE_OFFSET);
900

901
902
	for (i = 0; i < n; ++i) {
		end->in[1 + END_KEEPALIVE_OFFSET + i] = in[i];
903
		edges_notify_edge(end, END_KEEPALIVE_OFFSET + i, end->in[1 + END_KEEPALIVE_OFFSET + i], NULL, irg);
Michael Beck's avatar
<