irnode.c 65.9 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.
 */

Götz Lindenmaier's avatar
Götz Lindenmaier committed
20
21
22
23
24
/*
 * Project:     libFIRM
 * File name:   ir/ir/irnode.c
 * Purpose:     Representation of an intermediate operation.
 * Author:      Martin Trapp, Christian Schaefer
25
 * Modified by: Goetz Lindenmaier, Michael Beck
Götz Lindenmaier's avatar
Götz Lindenmaier committed
26
27
 * Created:
 * CVS-ID:      $Id$
28
 * Copyright:   (c) 1998-2006 Universitt Karlsruhe
Götz Lindenmaier's avatar
Götz Lindenmaier committed
29
 */
Boris Boesler's avatar
Boris Boesler committed
30

Boris Boesler's avatar
added    
Boris Boesler committed
31
#ifdef HAVE_CONFIG_H
Michael Beck's avatar
Michael Beck committed
32
33
34
35
36
# include "config.h"
#endif

#ifdef HAVE_STRING_H
# include <string.h>
Boris Boesler's avatar
added    
Boris Boesler committed
37
38
#endif

39
#include "ident.h"
Götz Lindenmaier's avatar
Götz Lindenmaier committed
40
#include "irnode_t.h"
Götz Lindenmaier's avatar
Götz Lindenmaier committed
41
#include "irgraph_t.h"
Götz Lindenmaier's avatar
Götz Lindenmaier committed
42
#include "irmode_t.h"
43
#include "typegmod.h"
44
#include "irbackedge_t.h"
45
#include "irdump.h"
46
#include "irop_t.h"
47
#include "irprog_t.h"
Sebastian Hack's avatar
Sebastian Hack committed
48
#include "iredgekinds.h"
Sebastian Hack's avatar
Sebastian Hack committed
49
#include "iredges_t.h"
Götz Lindenmaier's avatar
Götz Lindenmaier committed
50

51
#include "irhooks.h"
52
#include "irtools.h"
Michael Beck's avatar
Michael Beck committed
53

Götz Lindenmaier's avatar
Götz Lindenmaier committed
54
55
/* some constants fixing the positions of nodes predecessors
   in the in array */
Michael Beck's avatar
Michael Beck committed
56
57
58
59
60
#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
61

62
static const char *pnc_name_arr [] = {
63
64
65
66
	"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"
67
};
Christian Schäfer's avatar
Christian Schäfer committed
68

Michael Beck's avatar
Michael Beck committed
69
70
71
/**
 * returns the pnc name from an pnc constant
 */
72
const char *get_pnc_string(int pnc) {
73
	return pnc_name_arr[pnc];
Christian Schäfer's avatar
Christian Schäfer committed
74
75
}

Michael Beck's avatar
Michael Beck committed
76
/*
77
 * Calculates the negated (Complement(R)) pnc condition.
Michael Beck's avatar
Michael Beck committed
78
 */
79
int get_negated_pnc(int pnc, ir_mode *mode) {
80
	pnc ^= pn_Cmp_True;
81

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

86
	return pnc;
Christian Schäfer's avatar
Christian Schäfer committed
87
88
}

89
/* Calculates the inversed (R^-1) pnc condition, i.e., "<" --> ">" */
Michael Beck's avatar
Michael Beck committed
90
int
91
get_inversed_pnc(int pnc) {
92
93
94
	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
95

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

98
	return code;
Michael Beck's avatar
Michael Beck committed
99
100
}

101
102
103
104
105
106
107
108
109
110
/**
 * 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.
 */
111
unsigned firm_add_node_size = 0;
112
113


114
115
/* register new space for every node */
unsigned register_additional_node_data(unsigned size) {
116
	assert(!forbid_new_data && "Too late to register additional node data");
117

118
119
	if (forbid_new_data)
		return 0;
120

121
	return firm_add_node_size += size;
122
123
124
}


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

131
/*
132
133
134
 * irnode constructor.
 * Create a new irnode in irg, with an op, mode, arity and
 * some incoming irnodes.
135
136
 * If arity is negative, a node with a dynamic array is created.
 */
137
ir_node *
138
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
139
         int arity, ir_node **in)
Christian Schäfer's avatar
Christian Schäfer committed
140
{
141
142
143
	ir_node *res;
	size_t node_size = offsetof(ir_node, attr) + op->attr_size + firm_add_node_size;
	char *p;
144
	int i;
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168

	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
169
170

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

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

177
178
179
	// 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)
180
		edges_notify_edge(res, i - 1, res->in[i], NULL, irg);
Sebastian Hack's avatar
Sebastian Hack committed
181

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

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

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

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

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

199
int
200
(get_irn_inter_arity)(const ir_node *node) {
201
	return _get_irn_inter_arity(node);
202
203
}

204
int (*_get_irn_arity)(const ir_node *node) = _get_irn_intra_arity;
205

206
int
207
(get_irn_arity)(const ir_node *node) {
208
	return _get_irn_arity(node);
209
210
}

211
212
213
214
215
216
/* 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. */
217
ir_node **
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
265
266
267
268
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);
269
270
}

271
ir_node *
Sebastian Hack's avatar
Sebastian Hack committed
272
(get_irn_intra_n)(const ir_node *node, int n) {
273
	return _get_irn_intra_n (node, n);
274
275
}

276
ir_node *
Sebastian Hack's avatar
Sebastian Hack committed
277
(get_irn_inter_n)(const ir_node *node, int n) {
278
	return _get_irn_inter_n (node, n);
279
280
}

281
ir_node *(*_get_irn_n)(const ir_node *node, int n) = _get_irn_intra_n;
282

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

288
void
289
set_irn_n (ir_node *node, int n, ir_node *in) {
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
318
319
320
	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
321
322
}

323
324
325
326
327
328
329
330
331
332
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);

333
334
335
	/* Call the hook */
	hook_set_irn_n(node, pos, node->in[pos + 1], NULL);

336
337
338
	return pos;
}

Sebastian Hack's avatar
Sebastian Hack committed
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
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;
364
	} else {
Sebastian Hack's avatar
Sebastian Hack committed
365
366
367
368
369
370
371
372
373
374
375
		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;
		}

376
		if (first_zero >= 0) {
Sebastian Hack's avatar
Sebastian Hack committed
377
378
			node->deps[first_zero] = dep;
			res = first_zero;
379
		} else {
Sebastian Hack's avatar
Sebastian Hack committed
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
			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));
}


399
ir_mode *
400
(get_irn_mode)(const ir_node *node) {
401
	return _get_irn_mode(node);
Christian Schäfer's avatar
Christian Schäfer committed
402
403
}

404
void
405
406
(set_irn_mode)(ir_node *node, ir_mode *mode) {
	_set_irn_mode(node, mode);
Till Riedel's avatar
Till Riedel committed
407
408
}

409
modecode
410
411
412
get_irn_modecode(const ir_node *node) {
	assert(node);
	return node->mode->code;
Christian Schäfer's avatar
Christian Schäfer committed
413
414
}

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

422
ident *
423
424
425
get_irn_modeident(const ir_node *node) {
	assert(node);
	return get_mode_ident(node->mode);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
426
427
}

428
ir_op *
429
(get_irn_op)(const ir_node *node) {
430
	return _get_irn_op(node);
Christian Schäfer's avatar
Christian Schäfer committed
431
432
433
}

/* should be private to the library: */
434
void
435
436
(set_irn_op)(ir_node *node, ir_op *op) {
	_set_irn_op(node, op);
Christian Schäfer's avatar
Christian Schäfer committed
437
438
}

439
ir_opcode
440
441
(get_irn_opcode)(const ir_node *node) {
	return _get_irn_opcode(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
442
443
}

444
const char *
445
446
447
448
449
450
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
451
452
}

453
ident *
454
455
456
get_irn_opident(const ir_node *node) {
	assert(node);
	return node->op->name;
457
458
}

459
unsigned long
460
461
(get_irn_visited)(const ir_node *node) {
	return _get_irn_visited(node);
462
463
}

464
void
465
466
(set_irn_visited)(ir_node *node, unsigned long visited) {
	_set_irn_visited(node, visited);
Christian Schäfer's avatar
Christian Schäfer committed
467
}
468

469
void
470
(mark_irn_visited)(ir_node *node) {
471
	_mark_irn_visited(node);
472
473
}

474
int
475
(irn_not_visited)(const ir_node *node) {
476
	return _irn_not_visited(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
477
478
}

479
int
480
(irn_visited)(const ir_node *node) {
481
	return _irn_visited(node);
482
483
}

484
void
485
(set_irn_link)(ir_node *node, void *link) {
486
	_set_irn_link(node, link);
Christian Schäfer's avatar
Christian Schäfer committed
487
488
}

489
void *
490
(get_irn_link)(const ir_node *node) {
491
	return _get_irn_link(node);
Christian Schäfer's avatar
Christian Schäfer committed
492
493
}

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

499
500
op_pin_state
(is_irn_pinned_in_irg) (const ir_node *node) {
501
	return _is_irn_pinned_in_irg(node);
502
503
}

Michael Beck's avatar
Michael Beck committed
504
void set_irn_pinned(ir_node *node, op_pin_state state) {
505
506
507
	/* 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
508

509
510
	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
511

512
	node->attr.except.pin_state = state;
Michael Beck's avatar
Michael Beck committed
513
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
514
515
516
517
518

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


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

550
const_attr
551
552
553
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
554
555
}

556
long
557
558
559
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
560
561
}

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

568
free_attr
569
570
571
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
572
573
}

574
symconst_attr
575
576
577
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
578
579
}

Michael Beck's avatar
Michael Beck committed
580
ir_type *
581
582
583
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
584
585
}

586
sel_attr
587
588
589
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
590
591
}

592
int
593
594
595
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
596
597
}

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

604
load_attr
605
get_irn_load_attr(ir_node *node)
606
{
607
  assert(node->op == op_Load);
608
609
610
611
  return node->attr.load;
}

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

except_attr
619
620
621
622
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;
623
624
}

625
void *
626
627
get_irn_generic_attr(ir_node *node) {
	return &node->attr;
628
629
}

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

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

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

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

654
void
655
656
657
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
658
659
}

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

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

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

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

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

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

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

726
void
727
728
729
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
730
731
}

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

737
int
738
739
740
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
741
742
}

743
void
744
745
746
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
747
}
Michael Beck's avatar
Michael Beck committed
748

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

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

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

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

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

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

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

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

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

812
813
814
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;
815
816
817
}

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

822
823
824
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];
825
826
}

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

832
ir_node *(set_Block_dead)(ir_node *block) {
833
	return _set_Block_dead(block);
834
835
836
}

int (is_Block_dead)(const ir_node *block) {
837
	return _is_Block_dead(block);
838
839
}

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

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

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

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

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

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

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

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

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

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

901
	NEW_ARR_A(ir_node *, in, n);
902

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

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

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

915
void
916
free_End (ir_node *end) {
917
918
919
920
921
	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 ... */
922
923
}

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

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

Götz Lindenmaier's avatar
Götz Lindenmaier committed
936
937
938
939
940
941
942
943
944
/*
> 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
945
 - determining the biggest case constant to know the proj number for
Götz Lindenmaier's avatar
Götz Lindenmaier committed
946
947
948
949
950
951
952
953
954
955
956
957
   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.,