irnode.c 72.6 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
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;
Michael Beck's avatar
Michael Beck committed
231
	ir_node *** pOld_in;
232
233
234
	ir_graph *irg = current_ir_graph;
	assert(node);
	if (get_interprocedural_view()) { /* handle Filter and Block specially */
Michael Beck's avatar
Michael Beck committed
235
236
		ir_opcode code = get_irn_opcode(node);
		if (code  == iro_Filter) {
237
			assert(node->attr.filter.in_cg);
Michael Beck's avatar
Michael Beck committed
238
239
240
			pOld_in = &node->attr.filter.in_cg;
		} else if (code == iro_Block && node->attr.block.in_cg) {
			pOld_in = &node->attr.block.in_cg;
241
		} else {
Michael Beck's avatar
Michael Beck committed
242
			pOld_in = &node->in;
243
244
		}
	} else {
Michael Beck's avatar
Michael Beck committed
245
		pOld_in = &node->in;
246
247
248
	}

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

Michael Beck's avatar
Michael Beck committed
258
259
260
261
	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;
262
263
264
	}
	fix_backedges(irg->obst, node);

Michael Beck's avatar
Michael Beck committed
265
	memcpy((*pOld_in) + 1, in, sizeof(ir_node *) * arity);
266
267
}

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

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

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

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

285
void
286
set_irn_n (ir_node *node, int n, ir_node *in) {
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
317
	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
318
319
}

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

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

333
334
335
	return pos;
}

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

871
/* returns the macro block header of a block. */
Michael Beck's avatar
Michael Beck committed
872
ir_node *get_Block_MacroBlock(const ir_node *block) {