irnode.c 48.9 KB
Newer Older
Götz Lindenmaier's avatar
Götz Lindenmaier committed
1
2
3
4
5
6
7
8
9
10
11
/*
 * Project:     libFIRM
 * File name:   ir/ir/irnode.c
 * Purpose:     Representation of an intermediate operation.
 * Author:      Martin Trapp, Christian Schaefer
 * Modified by: Goetz Lindenmaier
 * Created:
 * CVS-ID:      $Id$
 * Copyright:   (c) 1998-2003 Universitt Karlsruhe
 * 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 "iredges_t.h"
Götz Lindenmaier's avatar
Götz Lindenmaier committed
31

32
#include "irhooks.h"
Michael Beck's avatar
Michael Beck committed
33

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

42
43
44
45
46
47
static const char *pnc_name_arr [] = {
  "False", "Eq", "Lt", "Le",
  "Gt", "Ge", "Lg", "Leg", "Uo",
  "Ue", "Ul", "Ule", "Ug", "Uge",
  "Ne", "True"
};
Christian Schäfer's avatar
Christian Schäfer committed
48

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

Michael Beck's avatar
Michael Beck committed
56
57
58
/**
 * Calculates the negated pnc condition.
 */
Christian Schäfer's avatar
Christian Schäfer committed
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
int
get_negated_pnc(int pnc) {
  switch (pnc) {
  case False: return True;  break;
  case Eq:    return Ne;    break;
  case Lt:    return Uge;   break;
  case Le:    return Ug;    break;
  case Gt:    return Ule;   break;
  case Ge:    return Ul;    break;
  case Lg:    return Ue;    break;
  case Leg:   return Uo;    break;
  case Uo:    return Leg;   break;
  case Ue:    return Lg;    break;
  case Ul:    return Ge;    break;
  case Ule:   return Gt;    break;
  case Ug:    return Le;    break;
  case Uge:   return Lt;    break;
  case Ne:    return Eq;    break;
  case True:  return False; break;
  }
  return 99; /* to shut up gcc */
}

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

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

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


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

108
109
  if (forbid_new_data)
    return 0;
110

111
  return firm_add_node_size += size;
112
113
114
}


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

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

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

Michael Beck's avatar
Michael Beck committed
140
141
142
  res->kind    = k_ir_node;
  res->op      = op;
  res->mode    = mode;
143
  res->visited = 0;
Michael Beck's avatar
Michael Beck committed
144
  res->link    = NULL;
Christian Schäfer's avatar
Christian Schäfer committed
145
  if (arity < 0) {
146
    res->in = NEW_ARR_F (ir_node *, 1);  /* 1: space for block */
Christian Schäfer's avatar
Christian Schäfer committed
147
148
149
150
  } 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
151

Christian Schäfer's avatar
Christian Schäfer committed
152
  res->in[0] = block;
Götz Lindenmaier's avatar
Götz Lindenmaier committed
153
  set_irn_dbg_info(res, db);
154
  res->out = NULL;
Götz Lindenmaier's avatar
Götz Lindenmaier committed
155
156
157
158
159

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

Sebastian Hack's avatar
Sebastian Hack committed
160
161
162
163
164
165
166
167
168
169
170
171
172
#ifdef FIRM_EDGES_INPLACE
	{
		int i, n;
		int not_a_block = !is_Block(res);

		INIT_LIST_HEAD(&res->edge_info.outs_head);

		for(i = 0, n = arity + not_a_block; i < n; ++i)
			edges_notify_edge(res, i - not_a_block, res->in[i], NULL, irg);
	}
#endif

  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
  ir_node *** arr;
225
  assert(node);
226
  if (get_interprocedural_view()) { /* handle Filter and Block specially */
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
    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;
  }
  if (arity != ARR_LEN(*arr) - 1) {
    ir_node * block = (*arr)[0];
    *arr = NEW_ARR_D(ir_node *, current_ir_graph->obst, arity + 1);
    (*arr)[0] = block;
242
  }
243
  fix_backedges(current_ir_graph->obst, node);
244
  memcpy((*arr) + 1, in, sizeof(ir_node *) * arity);
245
246
}

247
ir_node *
Sebastian Hack's avatar
Sebastian Hack committed
248
(get_irn_intra_n)(const ir_node *node, int n) {
249
  return _get_irn_intra_n (node, n);
250
251
}

252
ir_node *
Sebastian Hack's avatar
Sebastian Hack committed
253
(get_irn_inter_n)(const ir_node *node, int n) {
254
  return _get_irn_inter_n (node, n);
255
256
}

257
ir_node *(*_get_irn_n)(const ir_node *node, int n) = _get_irn_intra_n;
258

259
ir_node *
Sebastian Hack's avatar
Sebastian Hack committed
260
(get_irn_n)(const ir_node *node, int n) {
261
  return _get_irn_n(node, n);
Christian Schäfer's avatar
Christian Schäfer committed
262
263
}

264
void
265
set_irn_n (ir_node *node, int n, ir_node *in) {
Sebastian Hack's avatar
Sebastian Hack committed
266
267
268
  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
269
  assert(in && in->kind == k_ir_node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
270

271
272
273
274
275
276
277
  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;
  }
278
  if (get_interprocedural_view()) { /* handle Filter and Block specially */
279
280
281
282
283
284
285
286
287
288
    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
289
290
291
292
293
294
295
296
297

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

#ifdef FIRM_EDGES_INPLACE
	/* 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);
#endif

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

301
ir_mode *
302
(get_irn_mode)(const ir_node *node) {
303
  return _get_irn_mode(node);
Christian Schäfer's avatar
Christian Schäfer committed
304
305
}

306
void
307
(set_irn_mode)(ir_node *node, ir_mode *mode)
Till Riedel's avatar
Till Riedel committed
308
{
309
  _set_irn_mode(node, mode);
Till Riedel's avatar
Till Riedel committed
310
311
}

312
modecode
313
get_irn_modecode (const ir_node *node)
Christian Schäfer's avatar
Christian Schäfer committed
314
315
316
317
318
{
  assert (node);
  return node->mode->code;
}

319
/** Gets the string representation of the mode .*/
320
const char *
321
322
323
324
325
get_irn_modename (const ir_node *node)
{
  assert(node);
  return get_mode_name(node->mode);
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
326

327
ident *
328
get_irn_modeident (const ir_node *node)
Götz Lindenmaier's avatar
Götz Lindenmaier committed
329
330
{
  assert(node);
331
  return get_mode_ident(node->mode);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
332
333
}

334
ir_op *
335
(get_irn_op)(const ir_node *node)
Christian Schäfer's avatar
Christian Schäfer committed
336
{
337
  return _get_irn_op(node);
Christian Schäfer's avatar
Christian Schäfer committed
338
339
340
}

/* should be private to the library: */
341
void
Christian Schäfer's avatar
Christian Schäfer committed
342
343
344
345
346
347
set_irn_op (ir_node *node, ir_op *op)
{
  assert (node);
  node->op = op;
}

348
opcode
349
(get_irn_opcode)(const ir_node *node)
350
{
351
  return _get_irn_opcode(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
352
353
}

354
const char *
355
get_irn_opname (const ir_node *node)
Götz Lindenmaier's avatar
Götz Lindenmaier committed
356
357
{
  assert(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
358
359
360
  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";
361
  return get_id_str(node->op->name);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
362
363
}

364
ident *
365
get_irn_opident (const ir_node *node)
Götz Lindenmaier's avatar
Götz Lindenmaier committed
366
367
368
{
  assert(node);
  return node->op->name;
369
370
}

371
unsigned long
372
(get_irn_visited)(const ir_node *node)
373
{
374
  return _get_irn_visited(node);
375
376
}

377
void
378
(set_irn_visited)(ir_node *node, unsigned long visited)
Christian Schäfer's avatar
Christian Schäfer committed
379
{
380
  _set_irn_visited(node, visited);
Christian Schäfer's avatar
Christian Schäfer committed
381
}
382

383
void
384
(mark_irn_visited)(ir_node *node) {
385
  _mark_irn_visited(node);
386
387
}

388
int
389
(irn_not_visited)(const ir_node *node) {
390
  return _irn_not_visited(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
391
392
}

393
int
394
(irn_visited)(const ir_node *node) {
395
  return _irn_visited(node);
396
397
}

398
void
399
(set_irn_link)(ir_node *node, void *link) {
400
  _set_irn_link(node, link);
Christian Schäfer's avatar
Christian Schäfer committed
401
402
}

403
void *
404
(get_irn_link)(const ir_node *node) {
405
  return _get_irn_link(node);
Christian Schäfer's avatar
Christian Schäfer committed
406
407
}

408
409
op_pin_state
(get_irn_pinned)(const ir_node *node) {
410
  return _get_irn_pinned(node);
411
412
}

Michael Beck's avatar
Michael Beck committed
413
414
415
416
417
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;

418
  assert(node && get_op_pinned(get_irn_op(node)) >= op_pin_state_exc_pinned);
Michael Beck's avatar
Michael Beck committed
419
420
421
422
  assert(state == op_pin_state_pinned || state == op_pin_state_floats);

  node->attr.except.pin_state = state;
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439

#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;
}
440
441
442
443
444
445
#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
446
447
448
#endif /* DO_HEAPANALYSIS */


Götz Lindenmaier's avatar
Götz Lindenmaier committed
449
/* Outputs a unique number for this node */
450
long
451
get_irn_node_nr(const ir_node *node) {
Götz Lindenmaier's avatar
Götz Lindenmaier committed
452
  assert(node);
453
#ifdef DEBUG_libfirm
Götz Lindenmaier's avatar
Götz Lindenmaier committed
454
  return node->node_nr;
455
#else
456
  return (long)node;
Götz Lindenmaier's avatar
Götz Lindenmaier committed
457
#endif
458
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
459

460
const_attr
Christian Schäfer's avatar
Christian Schäfer committed
461
462
463
464
465
466
get_irn_const_attr (ir_node *node)
{
  assert (node->op == op_Const);
  return node->attr.con;
}

467
long
Christian Schäfer's avatar
Christian Schäfer committed
468
469
470
471
472
473
get_irn_proj_attr (ir_node *node)
{
  assert (node->op == op_Proj);
  return node->attr.proj;
}

474
alloc_attr
Christian Schäfer's avatar
Christian Schäfer committed
475
476
477
478
479
480
get_irn_alloc_attr (ir_node *node)
{
  assert (node->op == op_Alloc);
  return node->attr.a;
}

481
free_attr
Christian Schäfer's avatar
Christian Schäfer committed
482
483
484
get_irn_free_attr     (ir_node *node)
{
  assert (node->op == op_Free);
485
  return node->attr.f;
Christian Schäfer's avatar
Christian Schäfer committed
486
487
}

488
symconst_attr
Christian Schäfer's avatar
Christian Schäfer committed
489
490
491
492
493
494
get_irn_symconst_attr (ir_node *node)
{
  assert (node->op == op_SymConst);
  return node->attr.i;
}

495
type *
Christian Schäfer's avatar
Christian Schäfer committed
496
497
498
get_irn_call_attr (ir_node *node)
{
  assert (node->op == op_Call);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
499
  return node->attr.call.cld_tp = skip_tid(node->attr.call.cld_tp);
Christian Schäfer's avatar
Christian Schäfer committed
500
501
}

502
sel_attr
Christian Schäfer's avatar
Christian Schäfer committed
503
504
505
506
507
508
get_irn_sel_attr (ir_node *node)
{
  assert (node->op == op_Sel);
  return node->attr.s;
}

509
int
Christian Schäfer's avatar
Christian Schäfer committed
510
511
512
513
514
515
get_irn_phi_attr (ir_node *node)
{
  assert (node->op == op_Phi);
  return node->attr.phi0_pos;
}

516
block_attr
Christian Schäfer's avatar
Christian Schäfer committed
517
518
519
520
521
522
get_irn_block_attr (ir_node *node)
{
  assert (node->op == op_Block);
  return node->attr.block;
}

523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
load_attr
get_irn_load_attr (ir_node *node)
{
  assert (node->op == op_Load);
  return node->attr.load;
}

store_attr
get_irn_store_attr (ir_node *node)
{
  assert (node->op == op_Store);
  return node->attr.store;
}

except_attr
get_irn_except_attr (ir_node *node)
{
  assert (node->op == op_Div || node->op == op_Quot ||
541
          node->op == op_DivMod || node->op == op_Mod || node->op == op_Call || node->op == op_Alloc);
542
543
544
  return node->attr.except;
}

Christian Schäfer's avatar
Christian Schäfer committed
545
546
547
548
/** manipulate fields of individual nodes **/

/* this works for all except Block */
ir_node *
Sebastian Hack's avatar
Sebastian Hack committed
549
get_nodes_block (const ir_node *node) {
Christian Schäfer's avatar
Christian Schäfer committed
550
551
552
553
  assert (!(node->op == op_Block));
  return get_irn_n(node, -1);
}

554
void
555
set_nodes_block (ir_node *node, ir_node *block) {
Christian Schäfer's avatar
Christian Schäfer committed
556
557
558
559
  assert (!(node->op == op_Block));
  set_irn_n(node, -1, block);
}

560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
/* Test whether arbitrary node is frame pointer, i.e. Proj(pn_Start_P_frame_base)
 * from Start.  If so returns frame type, else Null. */
type *is_frame_pointer(ir_node *n) {
  if ((get_irn_op(n) == op_Proj) &&
      (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;
}

/* Test whether arbitrary node is globals pointer, i.e. Proj(pn_Start_P_globals)
 * from Start.  If so returns global type, else Null. */
type *is_globals_pointer(ir_node *n) {
  if ((get_irn_op(n) == op_Proj) &&
      (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;
}

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

596
/* Returns an array with the predecessors of the Block. Depending on
597
   the implementation of the graph data structure this can be a copy of
598
599
   the internal representation of predecessors as well as the internal
   array itself. Therefore writing to this array might obstruct the ir. */
600
ir_node **
601
602
603
get_Block_cfgpred_arr (ir_node *node)
{
  assert ((node->op == op_Block));
Götz Lindenmaier's avatar
Götz Lindenmaier committed
604
  return (ir_node **)&(get_irn_in(node)[1]);
605
606
607
}


608
int
Christian Schäfer's avatar
Christian Schäfer committed
609
610
get_Block_n_cfgpreds (ir_node *node) {
  assert ((node->op == op_Block));
611
  return get_irn_arity(node);
Christian Schäfer's avatar
Christian Schäfer committed
612
613
}

614
ir_node *
Christian Schäfer's avatar
Christian Schäfer committed
615
get_Block_cfgpred (ir_node *node, int pos) {
616
  assert(-1 <= pos && pos < get_irn_arity(node));
617
  assert(node->op == op_Block);
Christian Schäfer's avatar
Christian Schäfer committed
618
619
620
  return get_irn_n(node, pos);
}

621
void
Christian Schäfer's avatar
Christian Schäfer committed
622
623
624
625
626
set_Block_cfgpred (ir_node *node, int pos, ir_node *pred) {
  assert (node->op == op_Block);
  set_irn_n(node, pos, pred);
}

627
bool
Christian Schäfer's avatar
Christian Schäfer committed
628
629
630
631
632
get_Block_matured (ir_node *node) {
  assert (node->op == op_Block);
  return node->attr.block.matured;
}

633
void
Christian Schäfer's avatar
Christian Schäfer committed
634
635
636
637
set_Block_matured (ir_node *node, bool matured) {
  assert (node->op == op_Block);
  node->attr.block.matured = matured;
}
638
unsigned long
639
get_Block_block_visited (ir_node *node) {
Christian Schäfer's avatar
Christian Schäfer committed
640
  assert (node->op == op_Block);
641
  return node->attr.block.block_visited;
Christian Schäfer's avatar
Christian Schäfer committed
642
643
}

644
void
645
set_Block_block_visited (ir_node *node, unsigned long visit) {
Christian Schäfer's avatar
Christian Schäfer committed
646
  assert (node->op == op_Block);
647
  node->attr.block.block_visited = visit;
Christian Schäfer's avatar
Christian Schäfer committed
648
649
}

Götz Lindenmaier's avatar
Götz Lindenmaier committed
650
/* For this current_ir_graph must be set. */
651
void
652
mark_Block_block_visited (ir_node *node) {
Götz Lindenmaier's avatar
Götz Lindenmaier committed
653
654
655
656
  assert (node->op == op_Block);
  node->attr.block.block_visited = get_irg_block_visited(current_ir_graph);
}

657
int
658
Block_not_block_visited(ir_node *node) {
659
660
661
  assert (node->op == op_Block);
  return (node->attr.block.block_visited < get_irg_block_visited(current_ir_graph));
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
662

663
ir_node *
Christian Schäfer's avatar
Christian Schäfer committed
664
665
666
667
668
get_Block_graph_arr (ir_node *node, int pos) {
  assert (node->op == op_Block);
  return node->attr.block.graph_arr[pos+1];
}

669
void
Christian Schäfer's avatar
Christian Schäfer committed
670
671
672
673
set_Block_graph_arr (ir_node *node, int pos, ir_node *value) {
  assert (node->op == op_Block);
  node->attr.block.graph_arr[pos+1] = value;
}
674

675
676
677
678
679
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;
680
    node->attr.block.cg_backedge = new_backedge_arr(current_ir_graph->obst, arity);
681
682
    {
      /* Fix backedge array.  fix_backedges operates depending on
Florian Liekweg's avatar
Florian Liekweg committed
683
     interprocedural_view. */
684
685
      int ipv = get_interprocedural_view();
      set_interprocedural_view(true);
686
      fix_backedges(current_ir_graph->obst, node);
687
      set_interprocedural_view(ipv);
688
    }
689
690
691
692
693
  }
  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
694
  assert(node->op == op_Block &&
Florian Liekweg's avatar
Florian Liekweg committed
695
696
     node->attr.block.in_cg &&
     0 <= pos && pos < ARR_LEN(node->attr.block.in_cg) - 1);
697
698
699
700
701
702
703
704
705
  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) {
706
707
  assert(node->op == op_Block);
  return node->attr.block.in_cg == NULL ? 0 : ARR_LEN(node->attr.block.in_cg) - 1;
708
709
}

710
711
712
713
714
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];
}

715
716
717
718
719
void remove_Block_cg_cfgpred_arr(ir_node * node) {
  assert(node->op == op_Block);
  node->attr.block.in_cg = NULL;
}

720
ir_node *(set_Block_dead)(ir_node *block) {
721
  return _set_Block_dead(block);
722
723
724
}

int (is_Block_dead)(const ir_node *block) {
725
  return _is_Block_dead(block);
726
727
}

728
void
729
730
731
set_Start_irg(ir_node *node, ir_graph *irg) {
  assert(node->op == op_Start);
  assert(is_ir_graph(irg));
Götz Lindenmaier's avatar
Götz Lindenmaier committed
732
  assert(0 && " Why set irg? -- use set_irn_irg");
733
734
}

735
int
736
737
738
739
740
get_End_n_keepalives(ir_node *end) {
  assert (end->op == op_End);
  return (get_irn_arity(end) - END_KEEPALIVE_OFFSET);
}

741
ir_node *
742
743
744
745
746
get_End_keepalive(ir_node *end, int pos) {
  assert (end->op == op_End);
  return get_irn_n(end, pos + END_KEEPALIVE_OFFSET);
}

747
void
748
749
750
751
752
add_End_keepalive (ir_node *end, ir_node *ka) {
  assert (end->op == op_End);
  ARR_APP1 (ir_node *, end->in, ka);
}

753
void
754
755
756
757
758
set_End_keepalive(ir_node *end, int pos, ir_node *ka) {
  assert (end->op == op_End);
  set_irn_n(end, pos + END_KEEPALIVE_OFFSET, ka);
}

759
void
760
free_End (ir_node *end) {
761
  assert (end->op == op_End);
762
  end->kind = k_BAD;
763
  DEL_ARR_F(end->in);  /* GL @@@ tut nicht ! */
764
  end->in = NULL;   /* @@@ make sure we get an error if we use the
Florian Liekweg's avatar
Florian Liekweg committed
765
               in array afterwards ... */
766
767
}

768

Götz Lindenmaier's avatar
Götz Lindenmaier committed
769
770
771
772
773
774
775
776
777
/*
> 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
778
 - determining the biggest case constant to know the proj number for
Götz Lindenmaier's avatar
Götz Lindenmaier committed
779
780
781
782
783
784
785
786
787
788
789
790
   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.,
791
libFIRM can implement a routine that transforms between the two
Götz Lindenmaier's avatar
Götz Lindenmaier committed
792
793
794
795
796
797
798
799
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).
*/
800
ir_node *
Christian Schäfer's avatar
Christian Schäfer committed
801
802
803
804
805
get_Cond_selector (ir_node *node) {
  assert (node->op == op_Cond);
  return get_irn_n(node, 0);
}

806
void
Christian Schäfer's avatar
Christian Schäfer committed
807
808
809
810
811
set_Cond_selector (ir_node *node, ir_node *selector) {
  assert (node->op == op_Cond);
  set_irn_n(node, 0, selector);
}

812
cond_kind
813
814
get_Cond_kind (ir_node *node) {
  assert (node->op == op_Cond);
815
  return node->attr.c.kind;
816
817
}

818
void
819
820
set_Cond_kind (ir_node *node, cond_kind kind) {
  assert (node->op == op_Cond);
821
  node->attr.c.kind = kind;
822
823
}

824
825
826
827
828
829
long
get_Cond_defaultProj (ir_node *node) {
  assert (node->op == op_Cond);
  return node->attr.c.default_proj;
}

830
ir_node *
Christian Schäfer's avatar
Christian Schäfer committed
831
get_Return_mem (ir_node *node) {
832
  assert (node->op == op_Return);
Christian Schäfer's avatar
Christian Schäfer committed
833
834
835
  return get_irn_n(node, 0);
}

836
void
Christian Schäfer's avatar
Christian Schäfer committed
837
838
839
840
841
set_Return_mem (ir_node *node, ir_node *mem) {
  assert (node->op == op_Return);
  set_irn_n(node, 0, mem);
}

842
int
843
get_Return_n_ress (ir_node *node) {
844
845
846
847
  assert (node->op == op_Return);
  return (get_irn_arity(node) - RETURN_RESULT_OFFSET);
}

848
ir_node **
849
850
851
get_Return_res_arr (ir_node *node)
{
  assert ((node->op == op_Return));
852
  if (get_Return_n_ress(node) > 0)
Götz Lindenmaier's avatar
Götz Lindenmaier committed
853
    return (ir_node **)&(get_irn_in(node)[1 + RETURN_RESULT_OFFSET]);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
854
855
  else
    return NULL;
856
857
}

Christian Schäfer's avatar
Christian Schäfer committed
858
/*
859
void
Christian Schäfer's avatar
Christian Schäfer committed
860
861
862
863
864
set_Return_n_res (ir_node *node, int results) {
  assert (node->op == op_Return);
}
*/

865
ir_node *
Christian Schäfer's avatar
Christian Schäfer committed
866
867
get_Return_res (ir_node *node, int pos) {
  assert (node->op == op_Return);
868
  assert (get_Return_n_ress(node) > pos);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
869
  return get_irn_n(node, pos + RETURN_RESULT_OFFSET);
Christian Schäfer's avatar
Christian Schäfer committed
870
871
}

872
void
Christian Schäfer's avatar
Christian Schäfer committed
873
set_Return_res (ir_node *node, int pos, ir_node *res){
874
  assert (node->op == op_Return);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
875
  set_irn_n(node, pos + RETURN_RESULT_OFFSET, res);
Christian Schäfer's avatar
Christian Schäfer committed
876
877
}

878
ir_node *
Christian Schäfer's avatar
Christian Schäfer committed
879
get_Raise_mem (ir_node *node) {
Till Riedel's avatar
Till Riedel committed
880
  assert (node->op == op_Raise);
Christian Schäfer's avatar
Christian Schäfer committed
881
882
883
  return get_irn_n(node, 0);
}

884
void
Christian Schäfer's avatar
Christian Schäfer committed
885
886
887
888
889
set_Raise_mem (ir_node *node, ir_node *mem) {
  assert (node->op == op_Raise);
  set_irn_n(node, 0, mem);
}

890
ir_node *
Christian Schäfer's avatar
Christian Schäfer committed
891
892
893
894
895
get_Raise_exo_ptr (ir_node *node) {
  assert (node->op == op_Raise);
  return get_irn_n(node, 1);
}

896
void
Christian Schäfer's avatar
Christian Schäfer committed
897
898
899
900
901
set_Raise_exo_ptr (ir_node *node, ir_node *exo_ptr) {
  assert (node->op == op_Raise);
  set_irn_n(node, 1, exo_ptr);
}

Sebastian Hack's avatar
Sebastian Hack committed
902
903
tarval *(get_Const_tarval)(ir_node *node) {
	return _get_Const_tarval(node);
Christian Schäfer's avatar
Christian Schäfer committed
904
905
}

906
void
Christian Schäfer's avatar
Christian Schäfer committed
907
908
set_Const_tarval (ir_node *node, tarval *con) {
  assert (node->op == op_Const);
909
  node->attr.con.tv = con;
Christian Schäfer's avatar
Christian Schäfer committed
910
911
}

Sebastian Hack's avatar
Sebastian Hack committed
912
913
914
915
916
cnst_classify_t (classify_Const)(ir_node *node)
{
	return _classify_Const(node);
}

917
918
919
920

/* The source language type.  Must be an atomic type.  Mode of type must
   be mode of node. For tarvals from entities type must be pointer to
   entity type. */
921
type *
922
923
924
925
926
get_Const_type (ir_node *node) {
  assert (node->op == op_Const);
  return node->attr.con.tp;
}

927
void
928
929
set_Const_type (ir_node *node, type *tp) {
  assert (node->op == op_Const);
930
  if (tp != firm_unknown_type) {
Götz Lindenmaier's avatar
Götz Lindenmaier committed
931
    assert (is_atomic_type(tp));
932
933
934
935
936
937
    assert (get_type_mode(tp) == get_irn_mode(node));
  }
  node->attr.con.tp = tp;
}


938
symconst_kind
939
get_SymConst_kind (const ir_node *node) {
Christian Schäfer's avatar
Christian Schäfer committed
940
941
942
943
  assert (node->op == op_SymConst);
  return node->attr.i.num;
}

944
void
Christian Schäfer's avatar
Christian Schäfer committed
945
946
947
948
949
set_SymConst_kind (ir_node *node, symconst_kind num) {
  assert (node->op == op_SymConst);
  node->attr.i.num = num;
}

950
type *
Christian Schäfer's avatar
Christian Schäfer committed
951
952
get_SymConst_type (ir_node *node) {
  assert (   (node->op == op_SymConst)
Beyhan's avatar
Beyhan committed
953
954
955
          && (   get_SymConst_kind(node) == symconst_type_tag
              || get_SymConst_kind(node) == symconst_size));
  return node->attr.i.sym.type_p = skip_tid(node->attr.i.sym.type_p);
Christian Schäfer's avatar
Christian Schäfer committed
956
957
}

958
void
959
set_SymConst_type (ir_node *node, type *tp) {
Christian Schäfer's avatar
Christian Schäfer committed
960
  assert (   (node->op == op_SymConst)
Beyhan's avatar
Beyhan committed
961
962
963
          && (   get_SymConst_kind(node) == symconst_type_tag
              || get_SymConst_kind(node) == symconst_size));
  node->attr.i.sym.type_p = tp;
Christian Schäfer's avatar
Christian Schäfer committed
964
965
}

966
ident *
Beyhan's avatar
Beyhan committed
967
get_SymConst_name (ir_node *node) {
Christian Schäfer's avatar
Christian Schäfer committed
968
  assert (   (node->op == op_SymConst)
Beyhan's avatar
Beyhan committed
969
970
          && (get_SymConst_kind(node) == symconst_addr_name));
  return node->attr.i.sym.ident_p;
Christian Schäfer's avatar
Christian Schäfer committed
971
972
}

973
void
Beyhan's avatar
Beyhan committed
974
set_SymConst_name (ir_node *node, ident *name) {
Christian Schäfer's avatar
Christian Schäfer committed
975
  assert (   (node->op == op_SymConst)
Beyhan's avatar
Beyhan committed
976
977
          && (get_SymConst_kind(node) == symconst_addr_name));
  node->attr.i.sym.ident_p = name;
Christian Schäfer's avatar
Christian Schäfer committed
978
979
}

Beyhan's avatar
Beyhan committed
980
981
982
983

/* Only to access SymConst of kind symconst_addr_ent.  Else assertion: */
entity   *get_SymConst_entity (ir_node *node) {
  assert (   (node->op == op_SymConst)
Florian Liekweg's avatar
Florian Liekweg committed
984
          && (get_SymConst_kind (node) == symconst_addr_ent));
Beyhan's avatar
Beyhan committed
985
986
987
988
989
990
991
992
993
  return node->attr.i.sym.entity_p;
}

void     set_SymConst_entity (ir_node *node, entity *ent) {
  assert (   (node->op == op_SymConst)
          && (get_SymConst_kind(node) == symconst_addr_ent));
  node->attr.i.sym.entity_p  = ent;