irnode.c 66.7 KB
Newer Older
Götz Lindenmaier's avatar
Götz Lindenmaier committed
1
2
3
4
5
/*
 * Project:     libFIRM
 * File name:   ir/ir/irnode.c
 * Purpose:     Representation of an intermediate operation.
 * Author:      Martin Trapp, Christian Schaefer
6
 * Modified by: Goetz Lindenmaier, Michael Beck
Götz Lindenmaier's avatar
Götz Lindenmaier committed
7
8
 * Created:
 * CVS-ID:      $Id$
9
 * Copyright:   (c) 1998-2006 Universitt Karlsruhe
Götz Lindenmaier's avatar
Götz Lindenmaier committed
10
11
 * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
 */
Boris Boesler's avatar
Boris Boesler committed
12

Boris Boesler's avatar
added    
Boris Boesler committed
13
#ifdef HAVE_CONFIG_H
Michael Beck's avatar
Michael Beck committed
14
15
16
17
18
# include "config.h"
#endif

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

21
#include "ident.h"
Götz Lindenmaier's avatar
Götz Lindenmaier committed
22
#include "irnode_t.h"
Götz Lindenmaier's avatar
Götz Lindenmaier committed
23
#include "irgraph_t.h"
Götz Lindenmaier's avatar
Götz Lindenmaier committed
24
#include "irmode_t.h"
25
#include "typegmod.h"
26
#include "irbackedge_t.h"
27
#include "irdump.h"
28
#include "irop_t.h"
29
#include "irprog_t.h"
Sebastian Hack's avatar
Sebastian Hack committed
30
#include "iredgekinds.h"
Sebastian Hack's avatar
Sebastian Hack committed
31
#include "iredges_t.h"
Götz Lindenmaier's avatar
Götz Lindenmaier committed
32

33
#include "irhooks.h"
34
#include "irtools.h"
Michael Beck's avatar
Michael Beck committed
35

Götz Lindenmaier's avatar
Götz Lindenmaier committed
36
37
/* some constants fixing the positions of nodes predecessors
   in the in array */
Michael Beck's avatar
Michael Beck committed
38
39
40
41
42
#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
43

44
static const char *pnc_name_arr [] = {
Michael Beck's avatar
Michael Beck committed
45
46
47
48
  "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"
49
};
Christian Schäfer's avatar
Christian Schäfer committed
50

Michael Beck's avatar
Michael Beck committed
51
52
53
/**
 * returns the pnc name from an pnc constant
 */
54
const char *get_pnc_string(int pnc) {
Christian Schäfer's avatar
Christian Schäfer committed
55
56
57
  return pnc_name_arr[pnc];
}

Michael Beck's avatar
Michael Beck committed
58
/*
59
 * Calculates the negated (Complement(R)) pnc condition.
Michael Beck's avatar
Michael Beck committed
60
 */
61
62
63
64
65
66
67
68
int get_negated_pnc(int pnc, ir_mode *mode) {
  pnc ^= pn_Cmp_True;

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

  return pnc;
Christian Schäfer's avatar
Christian Schäfer committed
69
70
}

71
/* Calculates the inversed (R^-1) pnc condition, i.e., "<" --> ">" */
Michael Beck's avatar
Michael Beck committed
72
int
73
get_inversed_pnc(int pnc) {
Michael Beck's avatar
Michael Beck committed
74
75
76
77
78
79
80
81
82
  int code    = pnc & ~(pn_Cmp_Lt|pn_Cmp_Gt);
  int lesser  = pnc & pn_Cmp_Lt;
  int greater = pnc & pn_Cmp_Gt;

  code |= (lesser ? pn_Cmp_Gt : 0) | (greater ? pn_Cmp_Lt : 0);

  return code;
}

83
const char *pns_name_arr [] = {
84
85
86
  "initial_exec", "global_store",
  "frame_base", "globals", "args"
};
Christian Schäfer's avatar
Christian Schäfer committed
87

88
const char *symconst_name_arr [] = {
Beyhan's avatar
Beyhan committed
89
  "type_tag", "size", "addr_name", "addr_ent"
90
};
Christian Schäfer's avatar
Christian Schäfer committed
91

92
93
94
95
96
97
98
99
100
101
/**
 * 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.
 */
102
unsigned firm_add_node_size = 0;
103
104


105
106
107
/* register new space for every node */
unsigned register_additional_node_data(unsigned size) {
  assert(!forbid_new_data && "Too late to register additional node data");
108

109
110
  if (forbid_new_data)
    return 0;
111

112
  return firm_add_node_size += size;
113
114
115
}


Christian Schäfer's avatar
Christian Schäfer committed
116
void
117
init_irnode(void) {
118
119
  /* Forbid the addition of new data to an ir node. */
  forbid_new_data = 1;
Christian Schäfer's avatar
Christian Schäfer committed
120
121
}

122
/*
123
124
125
 * irnode constructor.
 * Create a new irnode in irg, with an op, mode, arity and
 * some incoming irnodes.
126
127
 * If arity is negative, a node with a dynamic array is created.
 */
128
ir_node *
129
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
130
         int arity, ir_node **in)
Christian Schäfer's avatar
Christian Schäfer committed
131
132
{
  ir_node *res;
133
  size_t node_size = offsetof(ir_node, attr) + op->attr_size + firm_add_node_size;
134
135
  char *p;
  int i, is_bl;
Christian Schäfer's avatar
Christian Schäfer committed
136

137
  assert(irg && op && mode);
138
139
  p = obstack_alloc (irg->obst, node_size);
  memset(p, 0, node_size);
140
  res = (ir_node *) (p + firm_add_node_size);
Christian Schäfer's avatar
Christian Schäfer committed
141

142
143
144
145
146
147
  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;
Sebastian Hack's avatar
Sebastian Hack committed
148
149
  res->deps     = NULL;

Christian Schäfer's avatar
Christian Schäfer committed
150
  if (arity < 0) {
151
    res->in = NEW_ARR_F (ir_node *, 1);  /* 1: space for block */
Christian Schäfer's avatar
Christian Schäfer committed
152
153
154
155
  } else {
    res->in = NEW_ARR_D (ir_node *, irg->obst, (arity+1));
    memcpy (&res->in[1], in, sizeof (ir_node *) * arity);
  }
Sebastian Hack's avatar
Sebastian Hack committed
156

Christian Schäfer's avatar
Christian Schäfer committed
157
  res->in[0] = block;
Götz Lindenmaier's avatar
Götz Lindenmaier committed
158
  set_irn_dbg_info(res, db);
159
  res->out = NULL;
Götz Lindenmaier's avatar
Götz Lindenmaier committed
160
161
162
163
164

#ifdef DEBUG_libfirm
  res->node_nr = get_irp_new_node_nr();
#endif

Sebastian Hack's avatar
Sebastian Hack committed
165
166
  for(i = 0; i < EDGE_KIND_LAST; ++i)
	  INIT_LIST_HEAD(&res->edge_info[i].outs_head);
167

Sebastian Hack's avatar
Sebastian Hack committed
168
  is_bl = is_Block(res);
169
170
  for (i = is_bl; i <= arity; ++i)
    edges_notify_edge(res, i - 1, res->in[i], NULL, irg);
Sebastian Hack's avatar
Sebastian Hack committed
171
172

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

Christian Schäfer's avatar
Christian Schäfer committed
174
175
176
  return res;
}

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

Sebastian Felis's avatar
Sebastian Felis committed
179
int
180
(is_ir_node)(const void *thing) {
181
  return _is_ir_node(thing);
Sebastian Felis's avatar
Sebastian Felis committed
182
183
}

184
int
185
(get_irn_intra_arity)(const ir_node *node) {
186
  return _get_irn_intra_arity(node);
Christian Schäfer's avatar
Christian Schäfer committed
187
188
}

189
int
190
(get_irn_inter_arity)(const ir_node *node) {
191
  return _get_irn_inter_arity(node);
192
193
}

194
int (*_get_irn_arity)(const ir_node *node) = _get_irn_intra_arity;
195

196
int
197
(get_irn_arity)(const ir_node *node) {
198
  return _get_irn_arity(node);
199
200
}

201
202
203
204
205
206
/* 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. */
207
ir_node **
208
get_irn_in (const ir_node *node) {
209
  assert(node);
210
  if (get_interprocedural_view()) { /* handle Filter and Block specially */
211
212
213
214
215
216
217
218
219
    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;
Christian Schäfer's avatar
Christian Schäfer committed
220
221
}

222
void
223
set_irn_in (ir_node *node, int arity, ir_node **in) {
224
  int i;
225
  ir_node *** arr;
226
  ir_graph *irg = current_ir_graph;
227
  assert(node);
228
  if (get_interprocedural_view()) { /* handle Filter and Block specially */
229
230
231
232
233
234
235
236
237
238
239
    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;
  }
240

241
242
243
244
245
246
247
248
  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);
249
250
  }

251
  if (arity != ARR_LEN(*arr) - 1) {
252
    ir_node * block = (*arr)[0];
253
    *arr = NEW_ARR_D(ir_node *, irg->obst, arity + 1);
254
    (*arr)[0] = block;
255
  }
256
  fix_backedges(irg->obst, node);
257

258
  memcpy((*arr) + 1, in, sizeof(ir_node *) * arity);
259
260
}

261
ir_node *
Sebastian Hack's avatar
Sebastian Hack committed
262
(get_irn_intra_n)(const ir_node *node, int n) {
263
  return _get_irn_intra_n (node, n);
264
265
}

266
ir_node *
Sebastian Hack's avatar
Sebastian Hack committed
267
(get_irn_inter_n)(const ir_node *node, int n) {
268
  return _get_irn_inter_n (node, n);
269
270
}

271
ir_node *(*_get_irn_n)(const ir_node *node, int n) = _get_irn_intra_n;
272

273
ir_node *
Sebastian Hack's avatar
Sebastian Hack committed
274
(get_irn_n)(const ir_node *node, int n) {
275
  return _get_irn_n(node, n);
Christian Schäfer's avatar
Christian Schäfer committed
276
277
}

278
void
279
set_irn_n (ir_node *node, int n, ir_node *in) {
Sebastian Hack's avatar
Sebastian Hack committed
280
281
282
  assert(node && node->kind == k_ir_node);
  assert(-1 <= n);
  assert(n < get_irn_arity(node));
Götz Lindenmaier's avatar
Götz Lindenmaier committed
283
  assert(in && in->kind == k_ir_node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
284

285
286
287
288
289
290
291
  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;
  }
292
  if (get_interprocedural_view()) { /* handle Filter and Block specially */
293
294
295
296
297
298
299
300
301
302
    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 */
  }
Sebastian Hack's avatar
Sebastian Hack committed
303

304
305
  /* Call the hook */
  hook_set_irn_n(node, n, in, node->in[n + 1]);
Sebastian Hack's avatar
Sebastian Hack committed
306

307
308
  /* 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);
Sebastian Hack's avatar
Sebastian Hack committed
309

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

Sebastian Hack's avatar
Sebastian Hack committed
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
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
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
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;
	}
	else {
		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;
		}

		if(first_zero >= 0) {
			node->deps[first_zero] = dep;
			res = first_zero;
		}

		else {
			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));
}


376
ir_mode *
377
(get_irn_mode)(const ir_node *node) {
378
  return _get_irn_mode(node);
Christian Schäfer's avatar
Christian Schäfer committed
379
380
}

381
void
382
(set_irn_mode)(ir_node *node, ir_mode *mode)
Till Riedel's avatar
Till Riedel committed
383
{
384
  _set_irn_mode(node, mode);
Till Riedel's avatar
Till Riedel committed
385
386
}

387
modecode
388
get_irn_modecode (const ir_node *node)
Christian Schäfer's avatar
Christian Schäfer committed
389
{
390
  assert(node);
Christian Schäfer's avatar
Christian Schäfer committed
391
392
393
  return node->mode->code;
}

394
/** Gets the string representation of the mode .*/
395
const char *
396
397
398
399
400
get_irn_modename (const ir_node *node)
{
  assert(node);
  return get_mode_name(node->mode);
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
401

402
ident *
403
get_irn_modeident (const ir_node *node)
Götz Lindenmaier's avatar
Götz Lindenmaier committed
404
405
{
  assert(node);
406
  return get_mode_ident(node->mode);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
407
408
}

409
ir_op *
410
(get_irn_op)(const ir_node *node) {
411
  return _get_irn_op(node);
Christian Schäfer's avatar
Christian Schäfer committed
412
413
414
}

/* should be private to the library: */
415
void
416
417
(set_irn_op)(ir_node *node, ir_op *op) {
	_set_irn_op(node, op);
Christian Schäfer's avatar
Christian Schäfer committed
418
419
}

420
opcode
421
(get_irn_opcode)(const ir_node *node)
422
{
423
  return _get_irn_opcode(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
424
425
}

426
const char *
427
get_irn_opname (const ir_node *node)
Götz Lindenmaier's avatar
Götz Lindenmaier committed
428
429
{
  assert(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
430
431
432
  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";
433
  return get_id_str(node->op->name);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
434
435
}

436
ident *
437
get_irn_opident (const ir_node *node)
Götz Lindenmaier's avatar
Götz Lindenmaier committed
438
439
440
{
  assert(node);
  return node->op->name;
441
442
}

443
unsigned long
444
(get_irn_visited)(const ir_node *node)
445
{
446
  return _get_irn_visited(node);
447
448
}

449
void
450
(set_irn_visited)(ir_node *node, unsigned long visited)
Christian Schäfer's avatar
Christian Schäfer committed
451
{
452
  _set_irn_visited(node, visited);
Christian Schäfer's avatar
Christian Schäfer committed
453
}
454

455
void
456
(mark_irn_visited)(ir_node *node) {
457
  _mark_irn_visited(node);
458
459
}

460
int
461
(irn_not_visited)(const ir_node *node) {
462
  return _irn_not_visited(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
463
464
}

465
int
466
(irn_visited)(const ir_node *node) {
467
  return _irn_visited(node);
468
469
}

470
void
471
(set_irn_link)(ir_node *node, void *link) {
472
  _set_irn_link(node, link);
Christian Schäfer's avatar
Christian Schäfer committed
473
474
}

475
void *
476
(get_irn_link)(const ir_node *node) {
477
  return _get_irn_link(node);
Christian Schäfer's avatar
Christian Schäfer committed
478
479
}

480
481
op_pin_state
(get_irn_pinned)(const ir_node *node) {
482
  return _get_irn_pinned(node);
483
484
}

485
486
487
488
489
op_pin_state
(is_irn_pinned_in_irg) (const ir_node *node) {
  return _is_irn_pinned_in_irg(node);
}

Michael Beck's avatar
Michael Beck committed
490
491
492
493
494
void set_irn_pinned(ir_node *node, op_pin_state state) {
  /* due to optimization an opt may be turned into a Tuple */
  if (get_irn_op(node) == op_Tuple)
    return;

495
  assert(node && get_op_pinned(get_irn_op(node)) >= op_pin_state_exc_pinned);
Michael Beck's avatar
Michael Beck committed
496
497
  assert(state == op_pin_state_pinned || state == op_pin_state_floats);

498
  node->attr.except.pin_state = state;
Michael Beck's avatar
Michael Beck committed
499
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516

#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) {
  return n->av;
}
/* Set the abstract interpretation information of a node. */
void set_irn_abst_value(ir_node *n, struct abstval *os) {
  n->av = os;
}
struct section *firm_get_irn_section(ir_node *n) {
  return n->sec;
}
void firm_set_irn_section(ir_node *n, struct section *s) {
  n->sec = s;
}
517
518
519
520
521
522
#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
523
524
525
#endif /* DO_HEAPANALYSIS */


Götz Lindenmaier's avatar
Götz Lindenmaier committed
526
/* Outputs a unique number for this node */
527
long get_irn_node_nr(const ir_node *node) {
Götz Lindenmaier's avatar
Götz Lindenmaier committed
528
  assert(node);
529
#ifdef DEBUG_libfirm
Götz Lindenmaier's avatar
Götz Lindenmaier committed
530
  return node->node_nr;
531
#else
532
  return (long)PTR_TO_INT(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
533
#endif
534
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
535

536
const_attr
Christian Schäfer's avatar
Christian Schäfer committed
537
538
get_irn_const_attr (ir_node *node)
{
539
  assert(node->op == op_Const);
Christian Schäfer's avatar
Christian Schäfer committed
540
541
542
  return node->attr.con;
}

543
long
Christian Schäfer's avatar
Christian Schäfer committed
544
545
get_irn_proj_attr (ir_node *node)
{
546
  assert(node->op == op_Proj);
Christian Schäfer's avatar
Christian Schäfer committed
547
548
549
  return node->attr.proj;
}

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

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

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

Michael Beck's avatar
Michael Beck committed
571
ir_type *
Christian Schäfer's avatar
Christian Schäfer committed
572
573
get_irn_call_attr (ir_node *node)
{
574
  assert(node->op == op_Call);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
575
  return node->attr.call.cld_tp = skip_tid(node->attr.call.cld_tp);
Christian Schäfer's avatar
Christian Schäfer committed
576
577
}

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

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

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

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

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

except_attr
get_irn_except_attr (ir_node *node)
{
616
  assert(node->op == op_Div || node->op == op_Quot ||
617
          node->op == op_DivMod || node->op == op_Mod || node->op == op_Call || node->op == op_Alloc);
618
619
620
  return node->attr.except;
}

621
622
623
624
625
void *
get_irn_generic_attr (ir_node *node) {
  return &node->attr;
}

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

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

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

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

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

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

/* 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
670
ir_type *is_globals_pointer(ir_node *n) {
671
  if (is_Proj(n) && (get_Proj_proj(n) == pn_Start_P_globals)) {
672
673
674
675
676
677
678
679
    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
685
686
687
688
689
690
691
/* 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) {
  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
697
698
699
700
701
/* 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) {
  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
/* Returns an array with the predecessors of the Block. Depending on
703
   the implementation of the graph data structure this can be a copy of
704
705
   the internal representation of predecessors as well as the internal
   array itself. Therefore writing to this array might obstruct the ir. */
706
ir_node **
707
708
get_Block_cfgpred_arr (ir_node *node)
{
709
  assert((node->op == op_Block));
Götz Lindenmaier's avatar
Götz Lindenmaier committed
710
  return (ir_node **)&(get_irn_in(node)[1]);
711
712
}

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

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

723
void
Christian Schäfer's avatar
Christian Schäfer committed
724
set_Block_cfgpred (ir_node *node, int pos, ir_node *pred) {
725
  assert(node->op == op_Block);
Christian Schäfer's avatar
Christian Schäfer committed
726
727
728
  set_irn_n(node, pos, pred);
}

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

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

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

746
unsigned long
Michael Beck's avatar
Michael Beck committed
747
748
(get_Block_block_visited)(ir_node *node) {
  return _get_Block_block_visited(node);
Christian Schäfer's avatar
Christian Schäfer committed
749
750
}

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

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

762
int
Michael Beck's avatar
Michael Beck committed
763
764
(Block_not_block_visited)(ir_node *node) {
  return _Block_not_block_visited(node);
765
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
766

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

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

779
780
781
782
783
void set_Block_cg_cfgpred_arr(ir_node * node, int arity, ir_node ** in) {
  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;
784
    node->attr.block.cg_backedge = new_backedge_arr(current_ir_graph->obst, arity);
785
    {
786
      /* Fix backedge array.  fix_backedges() operates depending on
Florian Liekweg's avatar
Florian Liekweg committed
787
     interprocedural_view. */
788
      int ipv = get_interprocedural_view();
789
      set_interprocedural_view(1);
790
      fix_backedges(current_ir_graph->obst, node);
791
      set_interprocedural_view(ipv);
792
    }
793
794
795
796
797
  }
  memcpy(node->attr.block.in_cg + 1, in, sizeof(ir_node *) * arity);
}

void set_Block_cg_cfgpred(ir_node * node, int pos, ir_node * pred) {
Götz Lindenmaier's avatar
Götz Lindenmaier committed
798
  assert(node->op == op_Block &&
Florian Liekweg's avatar
Florian Liekweg committed
799
800
     node->attr.block.in_cg &&
     0 <= pos && pos < ARR_LEN(node->attr.block.in_cg) - 1);
801
802
803
804
805
806
807
808
809
  node->attr.block.in_cg[pos + 1] = pred;
}

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;
}

int get_Block_cg_n_cfgpreds(ir_node * node) {
810
811
  assert(node->op == op_Block);
  return node->attr.block.in_cg == NULL ? 0 : ARR_LEN(node->attr.block.in_cg) - 1;
812
813
}

814
815
816
817
818
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];
}

819
820
821
822
823
void remove_Block_cg_cfgpred_arr(ir_node * node) {
  assert(node->op == op_Block);
  node->attr.block.in_cg = NULL;
}

824
ir_node *(set_Block_dead)(ir_node *block) {
825
  return _set_Block_dead(block);
826
827
828
}

int (is_Block_dead)(const ir_node *block) {
829
  return _is_Block_dead(block);
830
831
}

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

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

846
int
847
get_End_n_keepalives(ir_node *end) {
848
  assert(end->op == op_End);
849
850
851
  return (get_irn_arity(end) - END_KEEPALIVE_OFFSET);
}

852
ir_node *
853
get_End_keepalive(ir_node *end, int pos) {
854
  assert(end->op == op_End);
855
856
857
  return get_irn_n(end, pos + END_KEEPALIVE_OFFSET);
}

858
void
859
add_End_keepalive (ir_node *end, ir_node *ka) {
Michael Beck's avatar
Michael Beck committed
860
861
862
863
864
865
  int l;
  ir_graph *irg = get_irn_irg(end);

  assert(end->op == op_End);
  l = ARR_LEN(end->in);
  ARR_APP1(ir_node *, end->in, ka);
866
  edges_notify_edge(end, l - 1, end->in[l], NULL, irg);
867
868
}

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

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

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

  for (i = 0; i < n; ++i) {
887
    end->in[1 + END_KEEPALIVE_OFFSET + i] = in[i];
888
    edges_notify_edge(end, END_KEEPALIVE_OFFSET + i, NULL, end->in[1 + END_KEEPALIVE_OFFSET + i], irg);
889
890
  }
}
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
/* Set new keep-alives from old keep-alives, skipping irn */
void remove_End_keepalive(ir_node *end, ir_node *irn) {
  int     n = get_End_n_keepalives(end);
  ir_node **in;
  int     i, idx;

  NEW_ARR_A(ir_node *, in, n);

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

    /* skip irn */
    if (old_ka != irn)
      in[idx++] = old_ka;
  }

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

911
void
912
free_End (ir_node *end) {
913
  assert(end->op == op_End);
914
  end->kind = k_BAD;
915
  DEL_ARR_F(end->in);
916
  end->in = NULL;   /* @@@ make sure we get an error if we use the