irnode.c 69 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) {
Matthias Braun's avatar
Matthias Braun committed
67
	assert(pnc >= 0 && pnc < sizeof(pnc_name_arr)/sizeof(pnc_name_arr[0]));
68
	return pnc_name_arr[pnc];
Christian Schäfer's avatar
Christian Schäfer committed
69
70
}

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

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

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

84
/* Calculates the inversed (R^-1) pnc condition, i.e., "<" --> ">" */
Michael Beck's avatar
Michael Beck committed
85
int
86
get_inversed_pnc(int pnc) {
87
88
89
	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
90

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

93
	return 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
110
/* register new space for every node */
unsigned 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
new_ir_node (dbg_info *db, ir_graph *irg, ir_node *block, ir_op *op, ir_mode *mode,
Florian Liekweg's avatar
Florian Liekweg committed
134
         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
320
321
322
323
324
325
326
327
int add_irn_n(ir_node *node, ir_node *in)
{
	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
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
int
(get_irn_deps)(const ir_node *node)
{
	return _get_irn_deps(node);
}

ir_node *
(get_irn_dep)(const ir_node *node, int pos)
{
	return _get_irn_dep(node, pos);
}

void
(set_irn_dep)(ir_node *node, int pos, ir_node *dep)
{
	_set_irn_dep(node, pos, dep);
}

int add_irn_dep(ir_node *node, ir_node *dep)
{
	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
}

433
ir_opcode
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
525
526
527
528
#else
/* Dummies needed for firmjni. */
struct abstval *get_irn_abst_value(ir_node *n) { return NULL; }
void set_irn_abst_value(ir_node *n, struct abstval *os) {}
struct section *firm_get_irn_section(ir_node *n) { return NULL; }
void firm_set_irn_section(ir_node *n, struct section *s) {}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
529
530
531
#endif /* DO_HEAPANALYSIS */


Götz Lindenmaier's avatar
Götz Lindenmaier committed
532
/* Outputs a unique number for this node */
533
long get_irn_node_nr(const ir_node *node) {
534
	assert(node);
535
#ifdef DEBUG_libfirm
536
	return node->node_nr;
537
#else
538
	return (long)PTR_TO_INT(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
539
#endif
540
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
541

542
const_attr
543
544
545
get_irn_const_attr(ir_node *node) {
	assert(node->op == op_Const);
	return node->attr.con;
Christian Schäfer's avatar
Christian Schäfer committed
546
547
}

548
long
549
550
551
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
552
553
}

554
alloc_attr
555
556
557
get_irn_alloc_attr(ir_node *node) {
	assert(node->op == op_Alloc);
	return node->attr.alloc;
Christian Schäfer's avatar
Christian Schäfer committed
558
559
}

560
free_attr
561
562
563
get_irn_free_attr(ir_node *node) {
	assert(node->op == op_Free);
	return node->attr.free;
Christian Schäfer's avatar
Christian Schäfer committed
564
565
}

566
symconst_attr
567
568
569
get_irn_symconst_attr(ir_node *node) {
	assert(node->op == op_SymConst);
	return node->attr.symc;
Christian Schäfer's avatar
Christian Schäfer committed
570
571
}

Michael Beck's avatar
Michael Beck committed
572
ir_type *
573
574
575
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
576
577
}

578
sel_attr
579
580
581
get_irn_sel_attr(ir_node *node) {
	assert(node->op == op_Sel);
	return node->attr.sel;
Christian Schäfer's avatar
Christian Schäfer committed
582
583
}

584
int
585
586
587
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
588
589
}

590
block_attr
591
592
593
get_irn_block_attr(ir_node *node) {
	assert(node->op == op_Block);
	return node->attr.block;
Christian Schäfer's avatar
Christian Schäfer committed
594
595
}

596
load_attr
597
598
599
get_irn_load_attr(ir_node *node) {
	assert(node->op == op_Load);
	return node->attr.load;
600
601
602
}

store_attr
603
604
605
get_irn_store_attr(ir_node *node) {
	assert(node->op == op_Store);
	return node->attr.store;
606
607
608
}

except_attr
609
610
611
612
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);
	return node->attr.except;
613
614
}

615
616
617
void *(get_irn_generic_attr)(ir_node *node) {
	assert(is_ir_node(node));
	return _get_irn_generic_attr(node);
618
619
}

Matthias Braun's avatar
fix    
Matthias Braun committed
620
const void *(get_irn_generic_attr_const)(const ir_node *node) {
621
622
623
624
	assert(is_ir_node(node));
	return _get_irn_generic_attr_const(node);
}

625
unsigned (get_irn_idx)(const ir_node *node) {
626
627
	assert(is_ir_node(node));
	return _get_irn_idx(node);
628
629
}

630
int get_irn_pred_pos(ir_node *node, ir_node *arg) {
631
632
633
634
635
636
	int i;
	for (i = get_irn_arity(node) - 1; i >= 0; i--) {
		if (get_irn_n(node, i) == arg)
			return i;
	}
	return -1;
637
638
}

Christian Schäfer's avatar
Christian Schäfer committed
639
640
641
642
/** manipulate fields of individual nodes **/

/* this works for all except Block */
ir_node *
643
644
get_nodes_block(const ir_node *node) {
	assert(node->op != op_Block);
645
	assert(is_irn_pinned_in_irg(node) && "block info may be incorrect");
646
	return get_irn_n(node, -1);
Christian Schäfer's avatar
Christian Schäfer committed
647
648
}

649
void
650
651
652
set_nodes_block(ir_node *node, ir_node *block) {
	assert(node->op != op_Block);
	set_irn_n(node, -1, block);
Christian Schäfer's avatar
Christian Schäfer committed
653
654
}

655
656
/* 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
657
ir_type *is_frame_pointer(ir_node *n) {
658
659
660
661
662
663
664
	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;
665
666
667
668
}

/* 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
669
ir_type *is_globals_pointer(ir_node *n) {
670
671
672
673
674
675
676
	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;
677
678
}

679
680
681
/* 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) {
682
683
684
685
686
687
688
	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;
689
690
}

691
692
693
/* 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) {
694
695
696
697
698
	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;
699
700
}

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

711
int
Christoph Mallon's avatar
Christoph Mallon committed
712
(get_Block_n_cfgpreds)(const ir_node *node) {
713
	return _get_Block_n_cfgpreds(node);
Christian Schäfer's avatar
Christian Schäfer committed
714
715
}

716
ir_node *
717
(get_Block_cfgpred)(ir_node *node, int pos) {
718
	return _get_Block_cfgpred(node, pos);
Christian Schäfer's avatar
Christian Schäfer committed
719
720
}

721
void
722
723
724
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
725
726
}

727
728
ir_node  *
(get_Block_cfgpred_block)(ir_node *node, int pos) {
729
	return _get_Block_cfgpred_block(node, pos);
730
731
}

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

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

744
unsigned long
Matthias Braun's avatar
Matthias Braun committed
745
(get_Block_block_visited)(const ir_node *node) {
746
	return _get_Block_block_visited(node);
Christian Schäfer's avatar
Christian Schäfer committed
747
748
}

749
void
Michael Beck's avatar
Michael Beck committed
750
(set_Block_block_visited)(ir_node *node, unsigned long visit) {
751
	_set_Block_block_visited(node, visit);
Christian Schäfer's avatar
Christian Schäfer committed
752
753
}

Götz Lindenmaier's avatar
Götz Lindenmaier committed
754
/* For this current_ir_graph must be set. */
755
void
Michael Beck's avatar
Michael Beck committed
756
(mark_Block_block_visited)(ir_node *node) {
757
	_mark_Block_block_visited(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
758
759
}

760
int
Matthias Braun's avatar
Matthias Braun committed
761
(Block_not_block_visited)(const ir_node *node) {
762
	return _Block_not_block_visited(node);
763
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
764

Matthias Braun's avatar
Matthias Braun committed
765
766
767
768
769
int
(Block_block_visited)(const ir_node *node) {
	return _Block_block_visited(node);
}

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

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

Michael Beck's avatar
Michael Beck committed
782
void set_Block_cg_cfgpred_arr(ir_node *node, int arity, ir_node *in[]) {
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
	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);
798
799
}

Michael Beck's avatar
Michael Beck committed
800
void set_Block_cg_cfgpred(ir_node *node, int pos, ir_node *pred) {
801
802
803
804
	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;
805
806
}

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

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

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

Michael Beck's avatar
Michael Beck committed
822
void remove_Block_cg_cfgpred_arr(ir_node *node) {
823
824
	assert(node->op == op_Block);
	node->attr.block.in_cg = NULL;
825
826
}

827
ir_node *(set_Block_dead)(ir_node *block) {
828
	return _set_Block_dead(block);
829
830
831
}

int (is_Block_dead)(const ir_node *block) {
832
	return _is_Block_dead(block);
833
834
}

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

void set_Block_extbb(ir_node *block, ir_extblk *extblk) {
844
	assert(is_Block(block));
Michael Beck's avatar
Michael Beck committed
845
	assert(extblk == NULL || is_ir_extbb(extblk));
846
	block->attr.block.extblk = extblk;
847
848
}

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

855
856
857
858
859
860
/* returns the graph of a Block. */
ir_graph *get_Block_irg(const ir_node *block) {
	assert(is_Block(block));
	return block->attr.block.irg;
}

861
int
862
get_End_n_keepalives(ir_node *end) {
863
864
	assert(end->op == op_End);
	return (get_irn_arity(end) - END_KEEPALIVE_OFFSET);
865
866
}

867
ir_node *
868
get_End_keepalive(ir_node *end, int pos) {
869
870
	assert(end->op == op_End);
	return get_irn_n(end, pos + END_KEEPALIVE_OFFSET);
871
872
}

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

880
void
881
set_End_keepalive(ir_node *end, int pos, ir_node *ka) {
882
883
	assert(end->op == op_End);
	set_irn_n(end, pos + END_KEEPALIVE_OFFSET, ka);
884
885
}

886
887
/* Set new keep-alives */
void set_End_keepalives(ir_node *end, int n, ir_node *in[]) {
888
889
	int i;
	ir_graph *irg = get_irn_irg(end);
890

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

897
898
	for (i = 0; i < n; ++i) {
		end->in[1 + END_KEEPALIVE_OFFSET + i] = in[i];
899
		edges_notify_edge(end, END_KEEPALIVE_OFFSET + i, end->in[1 + END_KEEPALIVE_OFFSET + i], NULL, irg);
900
	}
901
}
902

903
904
/* Set new keep-alives from old keep-alives, skipping irn */
void remove_End_keepalive(ir_node *end, ir_node *irn) {
905
906
907
	int     n = get_End_n_keepalives(end);
	ir_node **in;
	int     i, idx;
908

909
	NEW_ARR_A(ir_node *, in, n);
910

911
912
	for (idx = i = 0; i < n; ++i) {
		ir_node *old_ka = get_End_keepalive(end, i);
913

914
915
916
917
		/* skip irn */
		if (old_ka != irn)
			in[idx++] = old_ka;
	}
918

919
920
	/* set new keep-alives */
	set_End_keepalives(end, idx, in);
921
}