irnode.c 72.4 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
}


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

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

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

	res->kind     = k_ir_node;
	res->op       = op;
	res->mode     = mode;
	res->visited  = 0;
	res->node_idx = irg_register_node_idx(irg, res);
	res->link     = NULL;
	res->deps     = NULL;

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

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

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

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

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

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

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

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

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

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

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

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

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

207
208
209
210
211
212
/* Returns the array with ins. This array is shifted with respect to the
   array accessed by get_irn_n: The block operand is at position 0 not -1.
   (@@@ This should be changed.)
   The order of the predecessors in this array is not guaranteed, except that
   lists of operands as predecessors of Block or arguments of a Call are
   consecutive. */
213
ir_node **
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
get_irn_in(const ir_node *node) {
	assert(node);
	if (get_interprocedural_view()) { /* handle Filter and Block specially */
		if (get_irn_opcode(node) == iro_Filter) {
			assert(node->attr.filter.in_cg);
			return node->attr.filter.in_cg;
		} else if (get_irn_opcode(node) == iro_Block && node->attr.block.in_cg) {
			return node->attr.block.in_cg;
		}
		/* else fall through */
	}
	return node->in;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

332
333
334
	return pos;
}

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

654
/* this works for all except Block */
Christian Schäfer's avatar
Christian Schäfer committed
655
ir_node *
656
657
658
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
659
660
}

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

Michael Beck's avatar
Michael Beck committed
667
668
669
670
671
672
673
/* 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));
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

870
/* returns the macro block header of a block. */
Michael Beck's avatar
Michael Beck committed
871
ir_node *get_Block_MacroBlock(const ir_node *block) {
872
	ir_node *mbh;
Michael Beck's avatar
Michael Beck committed
873
	assert(is_Block(block));
874
875
876
877
878
	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
879
880
}

Michael Beck's avatar
Michael Beck committed
881
882
/* returns the macro block header of a node. */
ir_node *get_irn_MacroBlock(const ir_node *n) {
883
	if (! is_Block(n)) {
Michael Beck's avatar
Michael Beck committed
884
		n = get_nodes_block(n);
885
886
		/* if the Block is Bad, do NOT try to get it's MB, it will fail. */
		if (is_Bad(n))
Matthias Braun's avatar
Matthias Braun committed
887
			return new_Bad();
888
	}
Michael Beck's avatar
Michael Beck committed
889
890
891
	return get_Block_MacroBlock(n);
}

892
893
894
895
896
897
/* returns the graph of a Block. */
ir_graph *