irnode.c 66.7 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 "typegmod.h"
39
#include "irbackedge_t.h"
40
#include "irdump.h"
41
#include "irop_t.h"
42
#include "irprog_t.h"
Sebastian Hack's avatar
Sebastian Hack committed
43
#include "iredgekinds.h"
Sebastian Hack's avatar
Sebastian Hack committed
44
#include "iredges_t.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
	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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163

	assert(irg && op && mode);
	p = obstack_alloc (irg->obst, node_size);
	memset(p, 0, node_size);
	res = (ir_node *) (p + firm_add_node_size);

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

	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
170
	for(i = 0; i < EDGE_KIND_LAST; ++i)
		INIT_LIST_HEAD(&res->edge_info[i].outs_head);
171

172
173
174
	// don't put this into the for loop, arity is -1 for some nodes!
	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
385
386
387
388
389
390
391
392
393
			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;
}

void add_irn_deps(ir_node *tgt, ir_node *src)
{
	int i, n;

	for(i = 0, n = get_irn_deps(src); i < n; ++i)
		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
}

434
ir_opcode
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
442
443
444
445
get_irn_opname(const ir_node *node) {
	assert(node);
	if ((get_irn_op((ir_node *)node) == op_Phi) &&
		(get_irg_phase_state(get_irn_irg((ir_node *)node)) == phase_building) &&
		(get_irn_arity((ir_node *)node) == 0)) return "Phi0";
	return get_id_str(node->op->name);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
446
447
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

545
const_attr
546
547
548
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
549
550
}

551
long
552
553
554
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
555
556
}

557
alloc_attr
558
559
560
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
561
562
}

563
free_attr
564
565
566
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
567
568
}

569
symconst_attr
570
571
572
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
573
574
}

Michael Beck's avatar
Michael Beck committed
575
ir_type *
576
577
578
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
579
580
}

581
sel_attr
582
583
584
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
585
586
}

587
int
588
589
590
get_irn_phi_attr(ir_node *node) {
	assert(node->op == op_Phi);
	return node->attr.phi0_pos;
Christian Schäfer's avatar
Christian Schäfer committed
591
592
}

593
block_attr
594
595
596
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
597
598
}

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

store_attr
606
607
608
get_irn_store_attr(ir_node *node) {
	assert(node->op == op_Store);
	return node->attr.store;
609
610
611
}

except_attr
612
613
614
615
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;
616
617
}

618
619
620
void *(get_irn_generic_attr)(ir_node *node) {
	assert(is_ir_node(node));
	return _get_irn_generic_attr(node);
621
622
}

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

628
unsigned (get_irn_idx)(const ir_node *node) {
629
630
	assert(is_ir_node(node));
	return _get_irn_idx(node);
631
632
}

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

Christian Schäfer's avatar
Christian Schäfer committed
642
643
644
645
/** manipulate fields of individual nodes **/

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

652
void
653
654
655
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
656
657
}

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

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

682
683
684
/* 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) {
685
686
687
688
689
690
691
	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;
692
693
}

694
695
696
/* 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) {
697
698
699
700
701
	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;
702
703
}

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

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

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

724
void
725
726
727
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
728
729
}

730
731
ir_node  *
(get_Block_cfgpred_block)(ir_node *node, int pos) {
732
	return _get_Block_cfgpred_block(node, pos);
733
734
}

735
int
736
737
738
get_Block_matured(ir_node *node) {
	assert(node->op == op_Block);
	return (int)node->attr.block.matured;
Christian Schäfer's avatar
Christian Schäfer committed
739
740
}

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

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

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

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

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

Matthias Braun's avatar
Matthias Braun committed
768
769
770
771
772
int
(Block_block_visited)(const ir_node *node) {
	return _Block_block_visited(node);
}

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

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

785
void set_Block_cg_cfgpred_arr(ir_node * node, int arity, ir_node ** in) {
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
	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);
801
802
803
}

void set_Block_cg_cfgpred(ir_node * node, int pos, ir_node * pred) {
804
805
806
807
	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;
808
809
}

810
811
812
ir_node **get_Block_cg_cfgpred_arr(ir_node * node) {
	assert(node->op == op_Block);
	return node->attr.block.in_cg == NULL ? NULL : node->attr.block.in_cg  + 1;
813
814
815
}

int get_Block_cg_n_cfgpreds(ir_node * node) {
816
817
	assert(node->op == op_Block);
	return node->attr.block.in_cg == NULL ? 0 : ARR_LEN(node->attr.block.in_cg) - 1;
818
819
}

820
821
822
ir_node *get_Block_cg_cfgpred(ir_node * node, int pos) {
	assert(node->op == op_Block && node->attr.block.in_cg);
	return node->attr.block.in_cg[pos + 1];
823
824
}

825
void remove_Block_cg_cfgpred_arr(ir_node * node) {
826
827
	assert(node->op == op_Block);
	node->attr.block.in_cg = NULL;
828
829
}

830
ir_node *(set_Block_dead)(ir_node *block) {
831
	return _set_Block_dead(block);
832
833
834
}

int (is_Block_dead)(const ir_node *block) {
835
	return _is_Block_dead(block);
836
837
}

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

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

852
int
853
get_End_n_keepalives(ir_node *end) {
854
855
	assert(end->op == op_End);
	return (get_irn_arity(end) - END_KEEPALIVE_OFFSET);
856
857
}

858
ir_node *
859
get_End_keepalive(ir_node *end, int pos) {
860
861
	assert(end->op == op_End);
	return get_irn_n(end, pos + END_KEEPALIVE_OFFSET);
862
863
}

864
void
865
add_End_keepalive (ir_node *end, ir_node *ka) {
866
	assert(end->op == op_End);
867
	add_irn_n(end, ka);
868
869
}

870
void
871
set_End_keepalive(ir_node *end, int pos, ir_node *ka) {
872
873
	assert(end->op == op_End);
	set_irn_n(end, pos + END_KEEPALIVE_OFFSET, ka);
874
875
}

876
877
/* Set new keep-alives */
void set_End_keepalives(ir_node *end, int n, ir_node *in[]) {
878
879
	int i;
	ir_graph *irg = get_irn_irg(end);
880

881
	/* notify that edges are deleted */
882
883
	for (i = END_KEEPALIVE_OFFSET; i < ARR_LEN(end->in) - 1; ++i) {
		edges_notify_edge(end, i, NULL, end->in[i + 1], irg);
884
885
	}
	ARR_RESIZE(ir_node *, end->in, n + 1 + END_KEEPALIVE_OFFSET);
886

887
888
	for (i = 0; i < n; ++i) {
		end->in[1 + END_KEEPALIVE_OFFSET + i] = in[i];
889
		edges_notify_edge(end, END_KEEPALIVE_OFFSET + i, end->in[1 + END_KEEPALIVE_OFFSET + i], NULL, irg);
890
	}
891
}
892

893
894
/* Set new keep-alives from old keep-alives, skipping irn */
void remove_End_keepalive(ir_node *end, ir_node *irn) {
895
896
897
	int     n = get_End_n_keepalives(end);
	ir_node **in;
	int     i, idx;
898

899
	NEW_ARR_A(ir_node *, in, n);
900

901
902
	for (idx = i = 0; i < n; ++i) {
		ir_node *old_ka = get_End_keepalive(end, i);
903

904
905
906
907
		/* skip irn */
		if (old_ka != irn)
			in[idx++] = old_ka;
	}
908

909
910
	/* set new keep-alives */
	set_End_keepalives(end, idx, in);
911
}
912

913
void
914
free_End (ir_node *end) {
915
916
917
918
919
	assert(end->op == op_End);
	end->kind = k_BAD;
	DEL_ARR_F(end->in);
	end->in = NULL;   /* @@@ make sure we get an error if we use the
	                     in array afterwards ... */
920
921
}

922
923
/* Return the target address of an IJmp */
ir_node *get_IJmp_target(ir_node *ijmp) {
924
925
	assert(ijmp->op == op_IJmp);
	return get_irn_n(ijmp, 0);
926
927
928
929
}

/** Sets the target address of an IJmp */
void set_IJmp_target(ir_node *ijmp, ir_node *tgt) {
930
931
	assert(ijmp->op == op_IJmp);
	set_irn_n(ijmp, 0, tgt);
932
}
933

Götz Lindenmaier's avatar
Götz Lindenmaier committed
934
935
936
937
938
939
940
941
942
/*
> Implementing the case construct (which is where the constant Proj node is
> important) involves far more than simply determining the constant values.
> We could argue that this is more properly a function of the translator from
> Firm to the target machine.  That could be done if there was some way of
> projecting "default" out of the Cond node.
I know it's complicated.
Basically there are two proglems:
 - determining the gaps between the projs
943
 - determining the biggest case constant to know the proj number for
Götz Lindenmaier's avatar
Götz Lindenmaier committed
944
945
946
947
948
949
950
951
952
953
954
955
   the default node.
I see several solutions:
1. Introduce a ProjDefault node.  Solves both problems.
   This means to extend all optimizations executed during construction.
2. Give the Cond node for switch two flavors:
   a) there are no gaps in the projs  (existing flavor)
   b) gaps may exist, default proj is still the Proj with the largest
      projection number.  This covers also the gaps.
3. Fix the semantic of the Cond to that of 2b)

Solution 2 seems to be the best:
Computing the gaps in the Firm representation is not too hard, i.e.,
956
libFIRM can implement a routine that transforms between the two
Götz Lindenmaier's avatar
Götz Lindenmaier committed
957
958
959
960
961
962
963
964
flavours.  This is also possible for 1) but 2) does not require to
change any existing optimization.
Further it should be far simpler to determine the biggest constant than
to compute all gaps.
I don't want to choose 3) as 2a) seems to have advantages for
dataflow analysis and 3) does not allow to convert the representation to
2a).
*/
965
ir_node *
966
967
968
get_Cond_selector(ir_node *node) {
	assert(node->op == op_Cond);
	return get_irn_n(node, 0);
Christian Schäfer's avatar
Christian Schäfer committed
969