irnode.c 73.5 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"
Matthias Braun's avatar
Matthias Braun committed
44
#include "ircons.h"
Götz Lindenmaier's avatar
Götz Lindenmaier committed
45

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

Götz Lindenmaier's avatar
Götz Lindenmaier committed
49
50
/* some constants fixing the positions of nodes predecessors
   in the in array */
Michael Beck's avatar
Michael Beck committed
51
52
53
54
55
#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
56

57
static const char *pnc_name_arr [] = {
58
59
60
61
	"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"
62
};
Christian Schäfer's avatar
Christian Schäfer committed
63

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

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

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

83
	return (pn_Cmp) pnc;
Christian Schäfer's avatar
Christian Schäfer committed
84
85
}

86
/* Calculates the inversed (R^-1) pnc condition, i.e., "<" --> ">" */
87
88
89
90
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
91

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

94
	return (pn_Cmp) 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
}


121
void 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
159
160
161
		/* not nice but necessary: End must always have a flexible array */
		if (op == op_End)
			res->in = NEW_ARR_F(ir_node *, (arity+1));
		else
			res->in = NEW_ARR_D(ir_node *, irg->obst, (arity+1));
162
		memcpy(&res->in[1], in, sizeof(ir_node *) * arity);
163
164
165
166
167
	}

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

#ifdef DEBUG_libfirm
170
	res->node_nr = get_irp_new_node_nr();
Götz Lindenmaier's avatar
Götz Lindenmaier committed
171
172
#endif

173
	for (i = 0; i < EDGE_KIND_LAST; ++i)
174
		INIT_LIST_HEAD(&res->edge_info[i].outs_head);
175

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

181
	hook_new_node(irg, res);
Michael Beck's avatar
Michael Beck committed
182

183
	return res;
Christian Schäfer's avatar
Christian Schäfer committed
184
185
}

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

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

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

196
int (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 (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 **get_irn_in(const ir_node *node) {
213
214
215
216
217
218
219
220
221
222
223
224
225
	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;
}

226
void set_irn_in(ir_node *node, int arity, ir_node **in) {
227
	int i;
Michael Beck's avatar
Michael Beck committed
228
	ir_node *** pOld_in;
229
230
231
	ir_graph *irg = current_ir_graph;
	assert(node);
	if (get_interprocedural_view()) { /* handle Filter and Block specially */
Michael Beck's avatar
Michael Beck committed
232
233
		ir_opcode code = get_irn_opcode(node);
		if (code  == iro_Filter) {
234
			assert(node->attr.filter.in_cg);
Michael Beck's avatar
Michael Beck committed
235
236
237
			pOld_in = &node->attr.filter.in_cg;
		} else if (code == iro_Block && node->attr.block.in_cg) {
			pOld_in = &node->attr.block.in_cg;
238
		} else {
Michael Beck's avatar
Michael Beck committed
239
			pOld_in = &node->in;
240
241
		}
	} else {
Michael Beck's avatar
Michael Beck committed
242
		pOld_in = &node->in;
243
244
245
	}

	for (i = 0; i < arity; i++) {
Michael Beck's avatar
Michael Beck committed
246
247
		if (i < ARR_LEN(*pOld_in)-1)
			edges_notify_edge(node, i, in[i], (*pOld_in)[i+1], irg);
248
		else
Michael Beck's avatar
Michael Beck committed
249
			edges_notify_edge(node, i, in[i], NULL,            irg);
250
	}
Michael Beck's avatar
Michael Beck committed
251
252
	for (;i < ARR_LEN(*pOld_in)-1; i++) {
		edges_notify_edge(node, i, NULL, (*pOld_in)[i+1], irg);
253
254
	}

Michael Beck's avatar
Michael Beck committed
255
256
257
258
	if (arity != ARR_LEN(*pOld_in) - 1) {
		ir_node * block = (*pOld_in)[0];
		*pOld_in = NEW_ARR_D(ir_node *, irg->obst, arity + 1);
		(*pOld_in)[0] = block;
259
260
261
	}
	fix_backedges(irg->obst, node);

Michael Beck's avatar
Michael Beck committed
262
	memcpy((*pOld_in) + 1, in, sizeof(ir_node *) * arity);
263
264
}

265
ir_node *(get_irn_intra_n)(const ir_node *node, int n) {
266
	return _get_irn_intra_n (node, n);
267
268
}

269
ir_node *(get_irn_inter_n)(const ir_node *node, int n) {
270
	return _get_irn_inter_n (node, n);
271
272
}

273
ir_node *(*_get_irn_n)(const ir_node *node, int n) = _get_irn_intra_n;
274

275
ir_node *(get_irn_n)(const ir_node *node, int n) {
276
	return _get_irn_n(node, n);
Christian Schäfer's avatar
Christian Schäfer committed
277
278
}

279
void set_irn_n(ir_node *node, int n, ir_node *in) {
280
281
282
283
284
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
	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
311
312
}

313
int add_irn_n(ir_node *node, ir_node *in) {
314
315
316
317
318
319
320
321
	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);

322
323
324
	/* Call the hook */
	hook_set_irn_n(node, pos, node->in[pos + 1], NULL);

325
326
327
	return pos;
}

328
int (get_irn_deps)(const ir_node *node) {
Sebastian Hack's avatar
Sebastian Hack committed
329
330
331
	return _get_irn_deps(node);
}

332
ir_node *(get_irn_dep)(const ir_node *node, int pos) {
Sebastian Hack's avatar
Sebastian Hack committed
333
334
335
	return _get_irn_dep(node, pos);
}

336
void (set_irn_dep)(ir_node *node, int pos, ir_node *dep) {
Sebastian Hack's avatar
Sebastian Hack committed
337
338
339
	_set_irn_dep(node, pos, dep);
}

340
int add_irn_dep(ir_node *node, ir_node *dep) {
Sebastian Hack's avatar
Sebastian Hack committed
341
342
343
344
345
	int res = 0;

	if (node->deps == NULL) {
		node->deps = NEW_ARR_F(ir_node *, 1);
		node->deps[0] = dep;
346
	} else {
Sebastian Hack's avatar
Sebastian Hack committed
347
348
349
350
351
352
353
354
355
356
357
		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;
		}

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

372
void add_irn_deps(ir_node *tgt, ir_node *src) {
Sebastian Hack's avatar
Sebastian Hack committed
373
374
	int i, n;

375
	for (i = 0, n = get_irn_deps(src); i < n; ++i)
Sebastian Hack's avatar
Sebastian Hack committed
376
377
378
379
		add_irn_dep(tgt, get_irn_dep(src, i));
}


380
ir_mode *(get_irn_mode)(const ir_node *node) {
381
	return _get_irn_mode(node);
Christian Schäfer's avatar
Christian Schäfer committed
382
383
}

384
void (set_irn_mode)(ir_node *node, ir_mode *mode) {
385
	_set_irn_mode(node, mode);
Till Riedel's avatar
Till Riedel committed
386
387
}

388
modecode get_irn_modecode(const ir_node *node) {
389
390
	assert(node);
	return node->mode->code;
Christian Schäfer's avatar
Christian Schäfer committed
391
392
}

393
/** Gets the string representation of the mode .*/
394
const char *get_irn_modename(const ir_node *node) {
395
396
	assert(node);
	return get_mode_name(node->mode);
397
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
398

399
ident *get_irn_modeident(const ir_node *node) {
400
401
	assert(node);
	return get_mode_ident(node->mode);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
402
403
}

404
ir_op *(get_irn_op)(const ir_node *node) {
405
	return _get_irn_op(node);
Christian Schäfer's avatar
Christian Schäfer committed
406
407
408
}

/* should be private to the library: */
409
void (set_irn_op)(ir_node *node, ir_op *op) {
410
	_set_irn_op(node, op);
Christian Schäfer's avatar
Christian Schäfer committed
411
412
}

413
unsigned (get_irn_opcode)(const ir_node *node) {
414
	return _get_irn_opcode(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
415
416
}

417
const char *get_irn_opname(const ir_node *node) {
418
	assert(node);
419
	if (is_Phi0(node)) return "Phi0";
420
	return get_id_str(node->op->name);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
421
422
}

423
ident *get_irn_opident(const ir_node *node) {
424
425
	assert(node);
	return node->op->name;
426
427
}

428
unsigned long (get_irn_visited)(const ir_node *node) {
429
	return _get_irn_visited(node);
430
431
}

432
void (set_irn_visited)(ir_node *node, unsigned long visited) {
433
	_set_irn_visited(node, visited);
Christian Schäfer's avatar
Christian Schäfer committed
434
}
435

436
void (mark_irn_visited)(ir_node *node) {
437
	_mark_irn_visited(node);
438
439
}

440
int (irn_not_visited)(const ir_node *node) {
441
	return _irn_not_visited(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
442
443
}

444
int (irn_visited)(const ir_node *node) {
445
	return _irn_visited(node);
446
447
}

448
void (set_irn_link)(ir_node *node, void *link) {
449
	_set_irn_link(node, link);
Christian Schäfer's avatar
Christian Schäfer committed
450
451
}

452
void *(get_irn_link)(const ir_node *node) {
453
	return _get_irn_link(node);
Christian Schäfer's avatar
Christian Schäfer committed
454
455
}

456
op_pin_state (get_irn_pinned)(const ir_node *node) {
457
	return _get_irn_pinned(node);
458
459
}

460
op_pin_state (is_irn_pinned_in_irg) (const ir_node *node) {
461
	return _is_irn_pinned_in_irg(node);
462
463
}

Michael Beck's avatar
Michael Beck committed
464
void set_irn_pinned(ir_node *node, op_pin_state state) {
465
466
467
	/* 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
468

469
470
	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
471

472
	node->attr.except.pin_state = state;
Michael Beck's avatar
Michael Beck committed
473
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
474
475
476
477
478

#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) {
479
	return n->av;
Götz Lindenmaier's avatar
Götz Lindenmaier committed
480
481
482
}
/* Set the abstract interpretation information of a node. */
void set_irn_abst_value(ir_node *n, struct abstval *os) {
483
	n->av = os;
Götz Lindenmaier's avatar
Götz Lindenmaier committed
484
485
}
struct section *firm_get_irn_section(ir_node *n) {
486
	return n->sec;
Götz Lindenmaier's avatar
Götz Lindenmaier committed
487
488
}
void firm_set_irn_section(ir_node *n, struct section *s) {
489
	n->sec = s;
Götz Lindenmaier's avatar
Götz Lindenmaier committed
490
}
491
492
#else
/* Dummies needed for firmjni. */
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
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
509
510
511
#endif /* DO_HEAPANALYSIS */


Götz Lindenmaier's avatar
Götz Lindenmaier committed
512
/* Outputs a unique number for this node */
513
long get_irn_node_nr(const ir_node *node) {
514
	assert(node);
515
#ifdef DEBUG_libfirm
516
	return node->node_nr;
517
#else
518
	return (long)PTR_TO_INT(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
519
#endif
520
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
521

522
const_attr *get_irn_const_attr(ir_node *node) {
523
	assert(node->op == op_Const);
524
	return &node->attr.con;
Christian Schäfer's avatar
Christian Schäfer committed
525
526
}

527
long get_irn_proj_attr(ir_node *node) {
528
529
	assert(node->op == op_Proj);
	return node->attr.proj;
Christian Schäfer's avatar
Christian Schäfer committed
530
531
}

532
alloc_attr *get_irn_alloc_attr(ir_node *node) {
533
	assert(node->op == op_Alloc);
534
	return &node->attr.alloc;
Christian Schäfer's avatar
Christian Schäfer committed
535
536
}

537
free_attr *get_irn_free_attr(ir_node *node) {
538
	assert(node->op == op_Free);
539
	return &node->attr.free;
Christian Schäfer's avatar
Christian Schäfer committed
540
541
}

542
symconst_attr *get_irn_symconst_attr(ir_node *node) {
543
	assert(node->op == op_SymConst);
544
	return &node->attr.symc;
Christian Schäfer's avatar
Christian Schäfer committed
545
546
}

547
ir_type *get_irn_call_attr(ir_node *node) {
548
549
	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
550
551
}

552
sel_attr *get_irn_sel_attr(ir_node *node) {
553
	assert(node->op == op_Sel);
554
	return &node->attr.sel;
Christian Schäfer's avatar
Christian Schäfer committed
555
556
}

557
phi_attr *get_irn_phi_attr(ir_node *node) {
558
	return &node->attr.phi;
Christian Schäfer's avatar
Christian Schäfer committed
559
560
}

561
block_attr *get_irn_block_attr(ir_node *node) {
562
	assert(node->op == op_Block);
563
	return &node->attr.block;
Christian Schäfer's avatar
Christian Schäfer committed
564
565
}

566
load_attr *get_irn_load_attr(ir_node *node) {
567
	assert(node->op == op_Load);
568
	return &node->attr.load;
569
570
}

571
store_attr *get_irn_store_attr(ir_node *node) {
572
	assert(node->op == op_Store);
573
	return &node->attr.store;
574
575
}

576
except_attr *get_irn_except_attr(ir_node *node) {
577
	assert(node->op == op_Div || node->op == op_Quot ||
578
	       node->op == op_DivMod || node->op == op_Mod || node->op == op_Call || node->op == op_Alloc || node->op == op_Bound);
579
	return &node->attr.except;
580
581
}

582
583
584
585
586
587
divmod_attr *get_irn_divmod_attr(ir_node *node) {
	assert(node->op == op_Div || node->op == op_Quot ||
	       node->op == op_DivMod || node->op == op_Mod);
	return &node->attr.divmod;
}

588
589
590
void *(get_irn_generic_attr)(ir_node *node) {
	assert(is_ir_node(node));
	return _get_irn_generic_attr(node);
591
592
}

Matthias Braun's avatar
fix    
Matthias Braun committed
593
const void *(get_irn_generic_attr_const)(const ir_node *node) {
594
595
596
597
	assert(is_ir_node(node));
	return _get_irn_generic_attr_const(node);
}

598
unsigned (get_irn_idx)(const ir_node *node) {
599
600
	assert(is_ir_node(node));
	return _get_irn_idx(node);
601
602
}

603
int get_irn_pred_pos(ir_node *node, ir_node *arg) {
604
605
606
607
608
609
	int i;
	for (i = get_irn_arity(node) - 1; i >= 0; i--) {
		if (get_irn_n(node, i) == arg)
			return i;
	}
	return -1;
610
611
}

Christian Schäfer's avatar
Christian Schäfer committed
612
613
/** manipulate fields of individual nodes **/

614
/* this works for all except Block */
615
ir_node *get_nodes_block(const ir_node *node) {
616
617
	assert(node->op != op_Block);
	return get_irn_n(node, -1);
Christian Schäfer's avatar
Christian Schäfer committed
618
619
}

620
void set_nodes_block(ir_node *node, ir_node *block) {
621
622
	assert(node->op != op_Block);
	set_irn_n(node, -1, block);
Christian Schäfer's avatar
Christian Schäfer committed
623
624
}

Michael Beck's avatar
Michael Beck committed
625
/* this works for all except Block */
626
ir_node *get_nodes_MacroBlock(const ir_node *node) {
Michael Beck's avatar
Michael Beck committed
627
628
629
630
	assert(node->op != op_Block);
	return get_Block_MacroBlock(get_irn_n(node, -1));
}

631
632
/* Test whether arbitrary node is frame pointer, i.e. Proj(pn_Start_P_frame_base)
 * from Start.  If so returns frame type, else Null. */
633
ir_type *is_frame_pointer(const ir_node *n) {
634
635
	if (is_Proj(n) && (get_Proj_proj(n) == pn_Start_P_frame_base)) {
		ir_node *start = get_Proj_pred(n);
636
		if (is_Start(start)) {
637
638
639
640
			return get_irg_frame_type(get_irn_irg(start));
		}
	}
	return NULL;
641
642
643
644
}

/* Test whether arbitrary node is globals pointer, i.e. Proj(pn_Start_P_globals)
 * from Start.  If so returns global type, else Null. */
645
ir_type *is_globals_pointer(const ir_node *n) {
646
647
	if (is_Proj(n) && (get_Proj_proj(n) == pn_Start_P_globals)) {
		ir_node *start = get_Proj_pred(n);
648
		if (is_Start(start)) {
649
650
651
652
			return get_glob_type();
		}
	}
	return NULL;
653
654
}

655
656
/* Test whether arbitrary node is tls pointer, i.e. Proj(pn_Start_P_tls)
 * from Start.  If so returns tls type, else Null. */
657
ir_type *is_tls_pointer(const ir_node *n) {
658
659
	if (is_Proj(n) && (get_Proj_proj(n) == pn_Start_P_globals)) {
		ir_node *start = get_Proj_pred(n);
660
		if (is_Start(start)) {
661
662
663
664
			return get_tls_type();
		}
	}
	return NULL;
665
666
}

667
668
/* 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. */
669
670
int is_value_arg_pointer(const ir_node *n) {
	if (is_Proj(n) &&
671
		(get_Proj_proj(n) == pn_Start_P_value_arg_base) &&
672
		is_Start(get_Proj_pred(n)))
673
674
		return 1;
	return 0;
675
676
}

677
/* Returns an array with the predecessors of the Block. Depending on
678
   the implementation of the graph data structure this can be a copy of
679
680
   the internal representation of predecessors as well as the internal
   array itself. Therefore writing to this array might obstruct the ir. */
681
ir_node **get_Block_cfgpred_arr(ir_node *node) {
682
683
	assert((node->op == op_Block));
	return (ir_node **)&(get_irn_in(node)[1]);
684
685
}

686
int (get_Block_n_cfgpreds)(const ir_node *node) {
687
	return _get_Block_n_cfgpreds(node);
Christian Schäfer's avatar
Christian Schäfer committed
688
689
}

690
ir_node *(get_Block_cfgpred)(const ir_node *node, int pos) {
691
	return _get_Block_cfgpred(node, pos);
Christian Schäfer's avatar
Christian Schäfer committed
692
693
}

694
void set_Block_cfgpred(ir_node *node, int pos, ir_node *pred) {
695
696
	assert(node->op == op_Block);
	set_irn_n(node, pos, pred);
Christian Schäfer's avatar
Christian Schäfer committed
697
698
}

699
ir_node *(get_Block_cfgpred_block)(const ir_node *node, int pos) {
700
	return _get_Block_cfgpred_block(node, pos);
701
702
}

703
int get_Block_matured(const ir_node *node) {
704
	assert(node->op == op_Block);
Michael Beck's avatar
Michael Beck committed
705
	return (int)node->attr.block.is_matured;
Christian Schäfer's avatar
Christian Schäfer committed
706
707
}

708
void set_Block_matured(ir_node *node, int matured) {
709
	assert(node->op == op_Block);
Michael Beck's avatar
Michael Beck committed
710
	node->attr.block.is_matured = matured;
Christian Schäfer's avatar
Christian Schäfer committed
711
}
Michael Beck's avatar
Michael Beck committed
712

713
unsigned long (get_Block_block_visited)(const ir_node *node) {
714
	return _get_Block_block_visited(node);
Christian Schäfer's avatar
Christian Schäfer committed
715
716
}

717
void (set_Block_block_visited)(ir_node *node, unsigned long visit) {
718
	_set_Block_block_visited(node, visit);
Christian Schäfer's avatar
Christian Schäfer committed
719
720
}

Götz Lindenmaier's avatar
Götz Lindenmaier committed
721
/* For this current_ir_graph must be set. */
722
void (mark_Block_block_visited)(ir_node *node) {
723
	_mark_Block_block_visited(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
724
725
}

726
int (Block_not_block_visited)(const ir_node *node) {
727
	return _Block_not_block_visited(node);
728
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
729

730
int (Block_block_visited)(const ir_node *node) {
Matthias Braun's avatar
Matthias Braun committed
731
732
733
	return _Block_block_visited(node);
}

734
ir_node *get_Block_graph_arr(ir_node *node, int pos) {
735
736
	assert(node->op == op_Block);
	return node->attr.block.graph_arr[pos+1];
Christian Schäfer's avatar
Christian Schäfer committed
737
738
}

739
void set_Block_graph_arr(ir_node *node, int pos, ir_node *value) {
740
741
	assert(node->op == op_Block);
	node->attr.block.graph_arr[pos+1] = value;
Christian Schäfer's avatar
Christian Schäfer committed
742
}
743

744
#ifdef INTERPROCEDURAL_VIEW
Michael Beck's avatar
Michael Beck committed
745
void set_Block_cg_cfgpred_arr(ir_node *node, int arity, ir_node *in[]) {
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
	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);
761
762
}

Michael Beck's avatar
Michael Beck committed
763
void set_Block_cg_cfgpred(ir_node *node, int pos, ir_node *pred) {
764
765
766
767
	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;
768
769
}

Michael Beck's avatar
Michael Beck committed
770
ir_node **get_Block_cg_cfgpred_arr(ir_node *node) {
771
772
	assert(node->op == op_Block);
	return node->attr.block.in_cg == NULL ? NULL : node->attr.block.in_cg  + 1;
773
774
}

775
int get_Block_cg_n_cfgpreds(const ir_node *node) {
776
777
	assert(node->op == op_Block);
	return node->attr.block.in_cg == NULL ? 0 : ARR_LEN(node->attr.block.in_cg) - 1;
778
779
}

780
ir_node *get_Block_cg_cfgpred(const ir_node *node, int pos) {
781
782
	assert(node->op == op_Block && node->attr.block.in_cg);
	return node->attr.block.in_cg[pos + 1];
783
784
}

Michael Beck's avatar
Michael Beck committed
785
void remove_Block_cg_cfgpred_arr(ir_node *node) {
786
787
	assert(node->op == op_Block);
	node->attr.block.in_cg = NULL;
788
}
789
#endif
790

791
ir_node *(set_Block_dead)(ir_node *block) {
792
	return _set_Block_dead(block);
793
794
795
}

int (is_Block_dead)(const ir_node *block) {
796
	return _is_Block_dead(block);
797
798
}

799
ir_extblk *get_Block_extbb(const ir_node *block) {
Michael Beck's avatar
Michael Beck committed
800
	ir_extblk *res;
801
	assert(is_Block(block));
Michael Beck's avatar
Michael Beck committed
802
803
	res = block->attr.block.extblk;
	assert(res == NULL || is_ir_extbb(res));
804
	return res;
805
806
807
}

void set_Block_extbb(ir_node *block, ir_extblk *extblk) {
808
	assert(is_Block(block));
Michael Beck's avatar
Michael Beck committed
809
	assert(extblk == NULL || is_ir_extbb(extblk));
810
	block->attr.block.extblk = extblk;
811
812
}

Michael Beck's avatar
Michael Beck committed
813
/* Returns the macro block header of a block.*/
Michael Beck's avatar
Michael Beck committed
814
ir_node *get_Block_MacroBlock(const ir_node *block) {
815
	ir_node *mbh;
Michael Beck's avatar
Michael Beck committed
816
	assert(is_Block(block));
817
818
819
820
821
	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
822
823
}

Michael Beck's avatar
Michael Beck committed
824
825
826
827
828
829
830
/* Sets the macro block header of a block. */
void set_Block_MacroBlock(ir_node *block, ir_node *mbh) {
	assert(is_Block(block));
	assert(is_Block(mbh));
	set_irn_n(block, -1, mbh);
}

Michael Beck's avatar
Michael Beck committed
831
832
/* returns the macro block header of a node. */
ir_node *get_irn_MacroBlock(const ir_node *n) {
833
	if (! is_Block(n)) {
Michael Beck's avatar
Michael Beck committed
834
		n = get_nodes_block(n);
835
836
		/* if the Block is Bad, do NOT try to get it's MB, it will fail. */
		if (is_Bad(n))
837
			return (ir_node *)n;
838
	}
Michael Beck's avatar
Michael Beck committed
839
840
841
	return get_Block_MacroBlock(n);
}

842
843
844
845
846
847
/* 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
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
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;
}