irnode.c 72.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
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
pn_Cmp get_negated_pnc(long 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 (pn_Cmp) pnc;
Christian Schäfer's avatar
Christian Schäfer committed
83
84
}

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

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

93
	return (pn_Cmp) code;
Michael Beck's avatar
Michael Beck committed
94
95
}

96
97
98
99
100
101
102
103
104
105
/**
 * Indicates, whether additional data can be registered to ir nodes.
 * If set to 1, this is not possible anymore.
 */
static int forbid_new_data = 0;

/**
 * The amount of additional space for custom data to be allocated upon
 * creating a new node.
 */
106
unsigned firm_add_node_size = 0;
107
108


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

113
114
	if (forbid_new_data)
		return 0;
115

116
	return firm_add_node_size += size;
117
118
119
}


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

126
/*
127
128
129
 * irnode constructor.
 * Create a new irnode in irg, with an op, mode, arity and
 * some incoming irnodes.
130
131
 * If arity is negative, a node with a dynamic array is created.
 */
132
ir_node *
133
134
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
135
{
136
137
138
	ir_node *res;
	size_t node_size = offsetof(ir_node, attr) + op->attr_size + firm_add_node_size;
	char *p;
139
	int i;
140
141

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

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

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

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

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

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

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

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

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

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

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

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

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

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

206
207
208
209
210
211
/* 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. */
212
ir_node **
213
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
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);
264
265
}

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

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

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

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

283
void
284
set_irn_n (ir_node *node, int n, ir_node *in) {
285
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
	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
316
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
336
(get_irn_deps)(const ir_node *node)
{
Sebastian Hack's avatar
Sebastian Hack committed
337
338
339
340
	return _get_irn_deps(node);
}

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

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

352
353
int add_irn_dep(ir_node *node, ir_node *dep)
{
Sebastian Hack's avatar
Sebastian Hack committed
354
355
356
357
358
	int res = 0;

	if (node->deps == NULL) {
		node->deps = NEW_ARR_F(ir_node *, 1);
		node->deps[0] = dep;
359
	} else {
Sebastian Hack's avatar
Sebastian Hack committed
360
361
362
363
364
365
366
367
368
369
370
		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;
		}

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

385
void add_irn_deps(ir_node *tgt, ir_node *src) {
Sebastian Hack's avatar
Sebastian Hack committed
386
387
	int i, n;

388
	for (i = 0, n = get_irn_deps(src); i < n; ++i)
Sebastian Hack's avatar
Sebastian Hack committed
389
390
391
392
		add_irn_dep(tgt, get_irn_dep(src, i));
}


393
ir_mode *
394
(get_irn_mode)(const ir_node *node) {
395
	return _get_irn_mode(node);
Christian Schäfer's avatar
Christian Schäfer committed
396
397
}

398
void
399
400
(set_irn_mode)(ir_node *node, ir_mode *mode) {
	_set_irn_mode(node, mode);
Till Riedel's avatar
Till Riedel committed
401
402
}

403
modecode
404
405
406
get_irn_modecode(const ir_node *node) {
	assert(node);
	return node->mode->code;
Christian Schäfer's avatar
Christian Schäfer committed
407
408
}

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

416
ident *
417
418
419
get_irn_modeident(const ir_node *node) {
	assert(node);
	return get_mode_ident(node->mode);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
420
421
}

422
ir_op *
423
(get_irn_op)(const ir_node *node) {
424
	return _get_irn_op(node);
Christian Schäfer's avatar
Christian Schäfer committed
425
426
427
}

/* should be private to the library: */
428
void
429
430
(set_irn_op)(ir_node *node, ir_op *op) {
	_set_irn_op(node, op);
Christian Schäfer's avatar
Christian Schäfer committed
431
432
}

Matthias Braun's avatar
Matthias Braun committed
433
unsigned
434
435
(get_irn_opcode)(const ir_node *node) {
	return _get_irn_opcode(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
436
437
}

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

445
ident *
446
447
448
get_irn_opident(const ir_node *node) {
	assert(node);
	return node->op->name;
449
450
}

451
unsigned long
452
453
(get_irn_visited)(const ir_node *node) {
	return _get_irn_visited(node);
454
455
}

456
void
457
458
(set_irn_visited)(ir_node *node, unsigned long visited) {
	_set_irn_visited(node, visited);
Christian Schäfer's avatar
Christian Schäfer committed
459
}
460

461
void
462
(mark_irn_visited)(ir_node *node) {
463
	_mark_irn_visited(node);
464
465
}

466
int
467
(irn_not_visited)(const ir_node *node) {
468
	return _irn_not_visited(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
469
470
}

471
int
472
(irn_visited)(const ir_node *node) {
473
	return _irn_visited(node);
474
475
}

476
void
477
(set_irn_link)(ir_node *node, void *link) {
478
	_set_irn_link(node, link);
Christian Schäfer's avatar
Christian Schäfer committed
479
480
}

481
void *
482
(get_irn_link)(const ir_node *node) {
483
	return _get_irn_link(node);
Christian Schäfer's avatar
Christian Schäfer committed
484
485
}

486
487
op_pin_state
(get_irn_pinned)(const ir_node *node) {
488
	return _get_irn_pinned(node);
489
490
}

491
492
op_pin_state
(is_irn_pinned_in_irg) (const ir_node *node) {
493
	return _is_irn_pinned_in_irg(node);
494
495
}

Michael Beck's avatar
Michael Beck committed
496
void set_irn_pinned(ir_node *node, op_pin_state state) {
497
498
499
	/* 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
500

501
502
	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
503

504
	node->attr.except.pin_state = state;
Michael Beck's avatar
Michael Beck committed
505
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
506
507
508
509
510

#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) {
511
	return n->av;
Götz Lindenmaier's avatar
Götz Lindenmaier committed
512
513
514
}
/* Set the abstract interpretation information of a node. */
void set_irn_abst_value(ir_node *n, struct abstval *os) {
515
	n->av = os;
Götz Lindenmaier's avatar
Götz Lindenmaier committed
516
517
}
struct section *firm_get_irn_section(ir_node *n) {
518
	return n->sec;
Götz Lindenmaier's avatar
Götz Lindenmaier committed
519
520
}
void firm_set_irn_section(ir_node *n, struct section *s) {
521
	n->sec = s;
Götz Lindenmaier's avatar
Götz Lindenmaier committed
522
}
523
524
#else
/* Dummies needed for firmjni. */
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
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
541
542
543
#endif /* DO_HEAPANALYSIS */


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

554
const_attr *
555
556
get_irn_const_attr(ir_node *node) {
	assert(node->op == op_Const);
557
	return &node->attr.con;
Christian Schäfer's avatar
Christian Schäfer committed
558
559
}

560
long
561
562
563
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
564
565
}

566
alloc_attr *
567
568
get_irn_alloc_attr(ir_node *node) {
	assert(node->op == op_Alloc);
569
	return &node->attr.alloc;
Christian Schäfer's avatar
Christian Schäfer committed
570
571
}

572
free_attr *
573
574
get_irn_free_attr(ir_node *node) {
	assert(node->op == op_Free);
575
	return &node->attr.free;
Christian Schäfer's avatar
Christian Schäfer committed
576
577
}

578
symconst_attr *
579
580
get_irn_symconst_attr(ir_node *node) {
	assert(node->op == op_SymConst);
581
	return &node->attr.symc;
Christian Schäfer's avatar
Christian Schäfer committed
582
583
}

Michael Beck's avatar
Michael Beck committed
584
ir_type *
585
586
587
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
588
589
}

590
sel_attr *
591
592
get_irn_sel_attr(ir_node *node) {
	assert(node->op == op_Sel);
593
	return &node->attr.sel;
Christian Schäfer's avatar
Christian Schäfer committed
594
595
}

596
int
597
598
599
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
600
601
}

602
block_attr *
603
604
get_irn_block_attr(ir_node *node) {
	assert(node->op == op_Block);
605
	return &node->attr.block;
Christian Schäfer's avatar
Christian Schäfer committed
606
607
}

608
load_attr *
609
610
get_irn_load_attr(ir_node *node) {
	assert(node->op == op_Load);
611
	return &node->attr.load;
612
613
}

614
store_attr *
615
616
get_irn_store_attr(ir_node *node) {
	assert(node->op == op_Store);
617
	return &node->attr.store;
618
619
}

620
except_attr *
621
622
623
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);
624
	return &node->attr.except;
625
626
}

627
628
629
void *(get_irn_generic_attr)(ir_node *node) {
	assert(is_ir_node(node));
	return _get_irn_generic_attr(node);
630
631
}

Matthias Braun's avatar
fix    
Matthias Braun committed
632
const void *(get_irn_generic_attr_const)(const ir_node *node) {
633
634
635
636
	assert(is_ir_node(node));
	return _get_irn_generic_attr_const(node);
}

637
unsigned (get_irn_idx)(const ir_node *node) {
638
639
	assert(is_ir_node(node));
	return _get_irn_idx(node);
640
641
}

642
int get_irn_pred_pos(ir_node *node, ir_node *arg) {
643
644
645
646
647
648
	int i;
	for (i = get_irn_arity(node) - 1; i >= 0; i--) {
		if (get_irn_n(node, i) == arg)
			return i;
	}
	return -1;
649
650
}

Christian Schäfer's avatar
Christian Schäfer committed
651
652
/** manipulate fields of individual nodes **/

653
/* this works for all except Block */
Christian Schäfer's avatar
Christian Schäfer committed
654
ir_node *
655
656
657
get_nodes_block(const ir_node *node) {
	assert(node->op != op_Block);
	return get_irn_n(node, -1);
Christian Schäfer's avatar
Christian Schäfer committed
658
659
}

660
void
661
set_nodes_block(ir_node *node, ir_node *block) {
662
663
	assert(node->op != op_Block);
	set_irn_n(node, -1, block);
Christian Schäfer's avatar
Christian Schäfer committed
664
665
}

Michael Beck's avatar
Michael Beck committed
666
667
668
669
670
671
672
/* this works for all except Block */
ir_node *
get_nodes_MacroBlock(const ir_node *node) {
	assert(node->op != op_Block);
	return get_Block_MacroBlock(get_irn_n(node, -1));
}

673
674
/* Test whether arbitrary node is frame pointer, i.e. Proj(pn_Start_P_frame_base)
 * from Start.  If so returns frame type, else Null. */
675
ir_type *is_frame_pointer(const ir_node *n) {
676
677
	if (is_Proj(n) && (get_Proj_proj(n) == pn_Start_P_frame_base)) {
		ir_node *start = get_Proj_pred(n);
678
		if (is_Start(start)) {
679
680
681
682
			return get_irg_frame_type(get_irn_irg(start));
		}
	}
	return NULL;
683
684
685
686
}

/* Test whether arbitrary node is globals pointer, i.e. Proj(pn_Start_P_globals)
 * from Start.  If so returns global type, else Null. */
687
ir_type *is_globals_pointer(const ir_node *n) {
688
689
	if (is_Proj(n) && (get_Proj_proj(n) == pn_Start_P_globals)) {
		ir_node *start = get_Proj_pred(n);
690
		if (is_Start(start)) {
691
692
693
694
			return get_glob_type();
		}
	}
	return NULL;
695
696
}

697
698
/* Test whether arbitrary node is tls pointer, i.e. Proj(pn_Start_P_tls)
 * from Start.  If so returns tls type, else Null. */
699
ir_type *is_tls_pointer(const ir_node *n) {
700
701
	if (is_Proj(n) && (get_Proj_proj(n) == pn_Start_P_globals)) {
		ir_node *start = get_Proj_pred(n);
702
		if (is_Start(start)) {
703
704
705
706
			return get_tls_type();
		}
	}
	return NULL;
707
708
}

709
710
/* 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. */
711
712
int is_value_arg_pointer(const ir_node *n) {
	if (is_Proj(n) &&
713
		(get_Proj_proj(n) == pn_Start_P_value_arg_base) &&
714
		is_Start(get_Proj_pred(n)))
715
716
		return 1;
	return 0;
717
718
}

719
/* Returns an array with the predecessors of the Block. Depending on
720
   the implementation of the graph data structure this can be a copy of
721
722
   the internal representation of predecessors as well as the internal
   array itself. Therefore writing to this array might obstruct the ir. */
723
ir_node **
724
725
726
get_Block_cfgpred_arr(ir_node *node) {
	assert((node->op == op_Block));
	return (ir_node **)&(get_irn_in(node)[1]);
727
728
}

729
int
Christoph Mallon's avatar
Christoph Mallon committed
730
(get_Block_n_cfgpreds)(const ir_node *node) {
731
	return _get_Block_n_cfgpreds(node);
Christian Schäfer's avatar
Christian Schäfer committed
732
733
}

734
ir_node *
735
(get_Block_cfgpred)(const ir_node *node, int pos) {
736
	return _get_Block_cfgpred(node, pos);
Christian Schäfer's avatar
Christian Schäfer committed
737
738
}

739
void
740
741
742
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
743
744
}

745
ir_node  *
746
(get_Block_cfgpred_block)(const ir_node *node, int pos) {
747
	return _get_Block_cfgpred_block(node, pos);
748
749
}

750
int
751
get_Block_matured(const ir_node *node) {
752
	assert(node->op == op_Block);
Michael Beck's avatar
Michael Beck committed
753
	return (int)node->attr.block.is_matured;
Christian Schäfer's avatar
Christian Schäfer committed
754
755
}

756
void
757
758
set_Block_matured(ir_node *node, int matured) {
	assert(node->op == op_Block);
Michael Beck's avatar
Michael Beck committed
759
	node->attr.block.is_matured = matured;
Christian Schäfer's avatar
Christian Schäfer committed
760
}
Michael Beck's avatar
Michael Beck committed
761

762
unsigned long
Matthias Braun's avatar
Matthias Braun committed
763
(get_Block_block_visited)(const ir_node *node) {
764
	return _get_Block_block_visited(node);
Christian Schäfer's avatar
Christian Schäfer committed
765
766
}

767
void
Michael Beck's avatar
Michael Beck committed
768
(set_Block_block_visited)(ir_node *node, unsigned long visit) {
769
	_set_Block_block_visited(node, visit);
Christian Schäfer's avatar
Christian Schäfer committed
770
771
}

Götz Lindenmaier's avatar
Götz Lindenmaier committed
772
/* For this current_ir_graph must be set. */
773
void
Michael Beck's avatar
Michael Beck committed
774
(mark_Block_block_visited)(ir_node *node) {
775
	_mark_Block_block_visited(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
776
777
}

778
int
Matthias Braun's avatar
Matthias Braun committed
779
(Block_not_block_visited)(const ir_node *node) {
780
	return _Block_not_block_visited(node);
781
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
782

Matthias Braun's avatar
Matthias Braun committed
783
784
785
786
787
int
(Block_block_visited)(const ir_node *node) {
	return _Block_block_visited(node);
}

788
ir_node *
789
get_Block_graph_arr(ir_node *node, int pos) {
790
791
	assert(node->op == op_Block);
	return node->attr.block.graph_arr[pos+1];
Christian Schäfer's avatar
Christian Schäfer committed
792
793
}

794
void
795
set_Block_graph_arr(ir_node *node, int pos, ir_node *value) {
796
797
	assert(node->op == op_Block);
	node->attr.block.graph_arr[pos+1] = value;
Christian Schäfer's avatar
Christian Schäfer committed
798
}
799

800
#ifdef INTERPROCEDURAL_VIEW
Michael Beck's avatar
Michael Beck committed
801
void set_Block_cg_cfgpred_arr(ir_node *node, int arity, ir_node *in[]) {
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
	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);
817
818
}

Michael Beck's avatar
Michael Beck committed
819
void set_Block_cg_cfgpred(ir_node *node, int pos, ir_node *pred) {
820
821
822
823
	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;
824
825
}

Michael Beck's avatar
Michael Beck committed
826
ir_node **get_Block_cg_cfgpred_arr(ir_node *node) {
827
828
	assert(node->op == op_Block);
	return node->attr.block.in_cg == NULL ? NULL : node->attr.block.in_cg  + 1;
829
830
}

831
int get_Block_cg_n_cfgpreds(const ir_node *node) {
832
833
	assert(node->op == op_Block);
	return node->attr.block.in_cg == NULL ? 0 : ARR_LEN(node->attr.block.in_cg) - 1;
834
835
}

836
ir_node *get_Block_cg_cfgpred(const ir_node *node, int pos) {
837
838
	assert(node->op == op_Block && node->attr.block.in_cg);
	return node->attr.block.in_cg[pos + 1];
839
840
}

Michael Beck's avatar
Michael Beck committed
841
void remove_Block_cg_cfgpred_arr(ir_node *node) {
842
843
	assert(node->op == op_Block);
	node->attr.block.in_cg = NULL;
844
}
845
#endif
846

847
ir_node *(set_Block_dead)(ir_node *block) {
848
	return _set_Block_dead(block);
849
850
851
}

int (is_Block_dead)(const ir_node *block) {
852
	return _is_Block_dead(block);
853
854
}

855
ir_extblk *get_Block_extbb(const ir_node *block) {
Michael Beck's avatar
Michael Beck committed
856
	ir_extblk *res;
857
	assert(is_Block(block));
Michael Beck's avatar
Michael Beck committed
858
859
	res = block->attr.block.extblk;
	assert(res == NULL || is_ir_extbb(res));
860
	return res;
861
862
863
}

void set_Block_extbb(ir_node *block, ir_extblk *extblk) {
864
	assert(is_Block(block));
Michael Beck's avatar
Michael Beck committed
865
	assert(extblk == NULL || is_ir_extbb(extblk));
866
	block->attr.block.extblk = extblk;
867
868
}

869
/* returns the macro block header of a block. */
Michael Beck's avatar
Michael Beck committed
870
ir_node *get_Block_MacroBlock(const ir_node *block) {
871
	ir_node *mbh;
Michael Beck's avatar
Michael Beck committed
872
	assert(is_Block(block));
873
874
875
876
877
	mbh = get_irn_n(block, -1);
	/* once macro block header is respected by all optimizations,
	   this assert can be removed */
	assert(mbh != NULL);
	return mbh;
Michael Beck's avatar
Michael Beck committed
878
879
}

Michael Beck's avatar
Michael Beck committed
880
881
882
883
884
885
886
/* returns the macro block header of a node. */
ir_node *get_irn_MacroBlock(const ir_node *n) {
	if (! is_Block(n))
		n = get_nodes_block(n);
	return get_Block_MacroBlock(n);
}

887
888
889
890
891
892
/* returns the graph of a Block. */
ir_graph *get_Block_irg(const ir_node *block) {
	assert(is_Block(block));
	return block->attr.block.irg;
}

Michael Beck's avatar
Michael Beck committed
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
int has_Block_label(const ir_node *block) {
	assert(is_Block(block));
	return block->attr.block.has_label;
}

ir_label_t get_Block_label(const ir_node *block) {
	assert(is_Block(block));
	return block->attr.block.label;
}

void set_Block_label(ir_node *block, ir_label_t label) {
	assert(is_Block(block));
	block->attr.block.has_label = 1;
	block->attr.block.label = label;
}

909
int
910
get_End_n_keepalives(const ir_node *end) {
911
912
	assert(end->op == op_End);
	return (get_irn_arity(end) - END_KEEPALIVE_OFFSET);