irnode.c 63.3 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"
33
#include "irtools.h"
Michael Beck's avatar
Michael Beck committed
34

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

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

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

Michael Beck's avatar
Michael Beck committed
57
/*
58
 * Calculates the negated (Complement(R)) pnc condition.
Michael Beck's avatar
Michael Beck committed
59
 */
60
61
62
63
64
65
66
67
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
68
69
}

70
/* Calculates the inversed (R^-1) pnc condition, i.e., "<" --> ">" */
Michael Beck's avatar
Michael Beck committed
71
int
72
get_inversed_pnc(int pnc) {
Michael Beck's avatar
Michael Beck committed
73
74
75
76
77
78
79
80
81
  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;
}

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
134
  char *p;
  int i, is_bl;
Christian Schäfer's avatar
Christian Schäfer committed
135

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

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

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

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

162
163
164
165
  INIT_LIST_HEAD(&res->edge_info.outs_head);
  is_bl = is_Block(res);
  if (is_bl)
    INIT_LIST_HEAD(&res->attr.block.succ_head);
Sebastian Hack's avatar
Sebastian Hack committed
166

167

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

306
307
  /* 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
308

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

312
ir_mode *
313
(get_irn_mode)(const ir_node *node) {
314
  return _get_irn_mode(node);
Christian Schäfer's avatar
Christian Schäfer committed
315
316
}

317
void
318
(set_irn_mode)(ir_node *node, ir_mode *mode)
Till Riedel's avatar
Till Riedel committed
319
{
320
  _set_irn_mode(node, mode);
Till Riedel's avatar
Till Riedel committed
321
322
}

323
modecode
324
get_irn_modecode (const ir_node *node)
Christian Schäfer's avatar
Christian Schäfer committed
325
326
327
328
329
{
  assert (node);
  return node->mode->code;
}

330
/** Gets the string representation of the mode .*/
331
const char *
332
333
334
335
336
get_irn_modename (const ir_node *node)
{
  assert(node);
  return get_mode_name(node->mode);
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
337

338
ident *
339
get_irn_modeident (const ir_node *node)
Götz Lindenmaier's avatar
Götz Lindenmaier committed
340
341
{
  assert(node);
342
  return get_mode_ident(node->mode);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
343
344
}

345
ir_op *
346
(get_irn_op)(const ir_node *node) {
347
  return _get_irn_op(node);
Christian Schäfer's avatar
Christian Schäfer committed
348
349
350
}

/* should be private to the library: */
351
void
352
353
(set_irn_op)(ir_node *node, ir_op *op) {
	_set_irn_op(node, op);
Christian Schäfer's avatar
Christian Schäfer committed
354
355
}

356
opcode
357
(get_irn_opcode)(const ir_node *node)
358
{
359
  return _get_irn_opcode(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
360
361
}

362
const char *
363
get_irn_opname (const ir_node *node)
Götz Lindenmaier's avatar
Götz Lindenmaier committed
364
365
{
  assert(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
366
367
368
  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";
369
  return get_id_str(node->op->name);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
370
371
}

372
ident *
373
get_irn_opident (const ir_node *node)
Götz Lindenmaier's avatar
Götz Lindenmaier committed
374
375
376
{
  assert(node);
  return node->op->name;
377
378
}

379
unsigned long
380
(get_irn_visited)(const ir_node *node)
381
{
382
  return _get_irn_visited(node);
383
384
}

385
void
386
(set_irn_visited)(ir_node *node, unsigned long visited)
Christian Schäfer's avatar
Christian Schäfer committed
387
{
388
  _set_irn_visited(node, visited);
Christian Schäfer's avatar
Christian Schäfer committed
389
}
390

391
void
392
(mark_irn_visited)(ir_node *node) {
393
  _mark_irn_visited(node);
394
395
}

396
int
397
(irn_not_visited)(const ir_node *node) {
398
  return _irn_not_visited(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
399
400
}

401
int
402
(irn_visited)(const ir_node *node) {
403
  return _irn_visited(node);
404
405
}

406
void
407
(set_irn_link)(ir_node *node, void *link) {
408
  _set_irn_link(node, link);
Christian Schäfer's avatar
Christian Schäfer committed
409
410
}

411
void *
412
(get_irn_link)(const ir_node *node) {
413
  return _get_irn_link(node);
Christian Schäfer's avatar
Christian Schäfer committed
414
415
}

416
417
op_pin_state
(get_irn_pinned)(const ir_node *node) {
418
  return _get_irn_pinned(node);
419
420
}

421
422
423
424
425
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
426
427
428
429
430
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;

431
  assert(node && get_op_pinned(get_irn_op(node)) >= op_pin_state_exc_pinned);
Michael Beck's avatar
Michael Beck committed
432
433
434
435
  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
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452

#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;
}
453
454
455
456
457
458
#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
459
460
461
#endif /* DO_HEAPANALYSIS */


Götz Lindenmaier's avatar
Götz Lindenmaier committed
462
/* Outputs a unique number for this node */
463
long get_irn_node_nr(const ir_node *node) {
Götz Lindenmaier's avatar
Götz Lindenmaier committed
464
  assert(node);
465
#ifdef DEBUG_libfirm
Götz Lindenmaier's avatar
Götz Lindenmaier committed
466
  return node->node_nr;
467
#else
468
  return (long)PTR_TO_INT(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
469
#endif
470
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
471

472
const_attr
Christian Schäfer's avatar
Christian Schäfer committed
473
474
475
476
477
478
get_irn_const_attr (ir_node *node)
{
  assert (node->op == op_Const);
  return node->attr.con;
}

479
long
Christian Schäfer's avatar
Christian Schäfer committed
480
481
482
483
484
485
get_irn_proj_attr (ir_node *node)
{
  assert (node->op == op_Proj);
  return node->attr.proj;
}

486
alloc_attr
Christian Schäfer's avatar
Christian Schäfer committed
487
488
489
490
491
492
get_irn_alloc_attr (ir_node *node)
{
  assert (node->op == op_Alloc);
  return node->attr.a;
}

493
free_attr
Christian Schäfer's avatar
Christian Schäfer committed
494
495
496
get_irn_free_attr     (ir_node *node)
{
  assert (node->op == op_Free);
497
  return node->attr.f;
Christian Schäfer's avatar
Christian Schäfer committed
498
499
}

500
symconst_attr
Christian Schäfer's avatar
Christian Schäfer committed
501
502
503
504
505
506
get_irn_symconst_attr (ir_node *node)
{
  assert (node->op == op_SymConst);
  return node->attr.i;
}

Michael Beck's avatar
Michael Beck committed
507
ir_type *
Christian Schäfer's avatar
Christian Schäfer committed
508
509
510
get_irn_call_attr (ir_node *node)
{
  assert (node->op == op_Call);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
511
  return node->attr.call.cld_tp = skip_tid(node->attr.call.cld_tp);
Christian Schäfer's avatar
Christian Schäfer committed
512
513
}

514
sel_attr
Christian Schäfer's avatar
Christian Schäfer committed
515
516
517
518
519
520
get_irn_sel_attr (ir_node *node)
{
  assert (node->op == op_Sel);
  return node->attr.s;
}

521
int
Christian Schäfer's avatar
Christian Schäfer committed
522
523
524
525
526
527
get_irn_phi_attr (ir_node *node)
{
  assert (node->op == op_Phi);
  return node->attr.phi0_pos;
}

528
block_attr
Christian Schäfer's avatar
Christian Schäfer committed
529
530
531
532
533
534
get_irn_block_attr (ir_node *node)
{
  assert (node->op == op_Block);
  return node->attr.block;
}

535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
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 ||
553
          node->op == op_DivMod || node->op == op_Mod || node->op == op_Call || node->op == op_Alloc);
554
555
556
  return node->attr.except;
}

557
558
559
560
561
void *
get_irn_generic_attr (ir_node *node) {
  return &node->attr;
}

562
563
564
565
566
unsigned (get_irn_idx)(const ir_node *node) {
  assert(is_ir_node(node));
  return _get_irn_idx(node);
}

567
568
569
570
571
572
573
574
575
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
576
577
578
579
/** manipulate fields of individual nodes **/

/* this works for all except Block */
ir_node *
Sebastian Hack's avatar
Sebastian Hack committed
580
get_nodes_block (const ir_node *node) {
Christian Schäfer's avatar
Christian Schäfer committed
581
  assert (!(node->op == op_Block));
582
	assert (is_irn_pinned_in_irg(node) && "block info may be incorrect");
Christian Schäfer's avatar
Christian Schäfer committed
583
584
585
  return get_irn_n(node, -1);
}

586
void
587
set_nodes_block (ir_node *node, ir_node *block) {
Christian Schäfer's avatar
Christian Schäfer committed
588
589
590
591
  assert (!(node->op == op_Block));
  set_irn_n(node, -1, block);
}

592
593
/* 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
594
ir_type *is_frame_pointer(ir_node *n) {
595
596
597
598
599
600
601
602
603
604
605
606
  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. */
Michael Beck's avatar
Michael Beck committed
607
ir_type *is_globals_pointer(ir_node *n) {
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
  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;
}

628
/* Returns an array with the predecessors of the Block. Depending on
629
   the implementation of the graph data structure this can be a copy of
630
631
   the internal representation of predecessors as well as the internal
   array itself. Therefore writing to this array might obstruct the ir. */
632
ir_node **
633
634
635
get_Block_cfgpred_arr (ir_node *node)
{
  assert ((node->op == op_Block));
Götz Lindenmaier's avatar
Götz Lindenmaier committed
636
  return (ir_node **)&(get_irn_in(node)[1]);
637
638
}

639
int
640
(get_Block_n_cfgpreds)(ir_node *node) {
Michael Beck's avatar
Michael Beck committed
641
  return _get_Block_n_cfgpreds(node);
Christian Schäfer's avatar
Christian Schäfer committed
642
643
}

644
ir_node *
645
(get_Block_cfgpred)(ir_node *node, int pos) {
Michael Beck's avatar
Michael Beck committed
646
  return _get_Block_cfgpred(node, pos);
Christian Schäfer's avatar
Christian Schäfer committed
647
648
}

649
void
Christian Schäfer's avatar
Christian Schäfer committed
650
651
652
653
654
set_Block_cfgpred (ir_node *node, int pos, ir_node *pred) {
  assert (node->op == op_Block);
  set_irn_n(node, pos, pred);
}

655
656
657
658
659
ir_node  *
(get_Block_cfgpred_block)(ir_node *node, int pos) {
  return _get_Block_cfgpred_block(node, pos);
}

660
int
Christian Schäfer's avatar
Christian Schäfer committed
661
662
get_Block_matured (ir_node *node) {
  assert (node->op == op_Block);
663
  return (int)node->attr.block.matured;
Christian Schäfer's avatar
Christian Schäfer committed
664
665
}

666
void
667
set_Block_matured (ir_node *node, int matured) {
Christian Schäfer's avatar
Christian Schäfer committed
668
669
670
  assert (node->op == op_Block);
  node->attr.block.matured = matured;
}
Michael Beck's avatar
Michael Beck committed
671

672
unsigned long
Michael Beck's avatar
Michael Beck committed
673
674
(get_Block_block_visited)(ir_node *node) {
  return _get_Block_block_visited(node);
Christian Schäfer's avatar
Christian Schäfer committed
675
676
}

677
void
Michael Beck's avatar
Michael Beck committed
678
679
(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
680
681
}

Götz Lindenmaier's avatar
Götz Lindenmaier committed
682
/* For this current_ir_graph must be set. */
683
void
Michael Beck's avatar
Michael Beck committed
684
685
(mark_Block_block_visited)(ir_node *node) {
  _mark_Block_block_visited(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
686
687
}

688
int
Michael Beck's avatar
Michael Beck committed
689
690
(Block_not_block_visited)(ir_node *node) {
  return _Block_not_block_visited(node);
691
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
692

693
ir_node *
Christian Schäfer's avatar
Christian Schäfer committed
694
695
696
697
698
get_Block_graph_arr (ir_node *node, int pos) {
  assert (node->op == op_Block);
  return node->attr.block.graph_arr[pos+1];
}

699
void
Christian Schäfer's avatar
Christian Schäfer committed
700
701
702
703
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;
}
704

705
706
707
708
709
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;
710
    node->attr.block.cg_backedge = new_backedge_arr(current_ir_graph->obst, arity);
711
    {
712
      /* Fix backedge array.  fix_backedges() operates depending on
Florian Liekweg's avatar
Florian Liekweg committed
713
     interprocedural_view. */
714
      int ipv = get_interprocedural_view();
715
      set_interprocedural_view(1);
716
      fix_backedges(current_ir_graph->obst, node);
717
      set_interprocedural_view(ipv);
718
    }
719
720
721
722
723
  }
  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
724
  assert(node->op == op_Block &&
Florian Liekweg's avatar
Florian Liekweg committed
725
726
     node->attr.block.in_cg &&
     0 <= pos && pos < ARR_LEN(node->attr.block.in_cg) - 1);
727
728
729
730
731
732
733
734
735
  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) {
736
737
  assert(node->op == op_Block);
  return node->attr.block.in_cg == NULL ? 0 : ARR_LEN(node->attr.block.in_cg) - 1;
738
739
}

740
741
742
743
744
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];
}

745
746
747
748
749
void remove_Block_cg_cfgpred_arr(ir_node * node) {
  assert(node->op == op_Block);
  node->attr.block.in_cg = NULL;
}

750
ir_node *(set_Block_dead)(ir_node *block) {
751
  return _set_Block_dead(block);
752
753
754
}

int (is_Block_dead)(const ir_node *block) {
755
  return _is_Block_dead(block);
756
757
}

758
ir_extblk *get_Block_extbb(const ir_node *block) {
Michael Beck's avatar
Michael Beck committed
759
	ir_extblk *res;
760
  assert(is_Block(block));
Michael Beck's avatar
Michael Beck committed
761
762
763
	res = block->attr.block.extblk;
	assert(res == NULL || is_ir_extbb(res));
  return res;
764
765
766
767
}

void set_Block_extbb(ir_node *block, ir_extblk *extblk) {
  assert(is_Block(block));
Michael Beck's avatar
Michael Beck committed
768
	assert(extblk == NULL || is_ir_extbb(extblk));
769
770
771
  block->attr.block.extblk = extblk;
}

772
int
773
774
775
776
777
get_End_n_keepalives(ir_node *end) {
  assert (end->op == op_End);
  return (get_irn_arity(end) - END_KEEPALIVE_OFFSET);
}

778
ir_node *
779
780
781
782
783
get_End_keepalive(ir_node *end, int pos) {
  assert (end->op == op_End);
  return get_irn_n(end, pos + END_KEEPALIVE_OFFSET);
}

784
void
785
add_End_keepalive (ir_node *end, ir_node *ka) {
Michael Beck's avatar
Michael Beck committed
786
787
788
789
790
791
792
  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);
  edges_notify_edge(end, l, end->in[l], NULL, irg);
793
794
}

795
void
796
797
798
799
800
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);
}

801
802
803
804
805
806
/* 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 */
807
808
  for (i = 1 + END_KEEPALIVE_OFFSET; i < ARR_LEN(end->in); ++i) {
    edges_notify_edge(end, i, end->in[i], NULL, irg);
809
  }
810
  ARR_RESIZE(ir_node *, end->in, n + 1 + END_KEEPALIVE_OFFSET);
811
812

  for (i = 0; i < n; ++i) {
813
814
    end->in[1 + END_KEEPALIVE_OFFSET + i] = in[i];
    edges_notify_edge(end, 1 + END_KEEPALIVE_OFFSET + i, NULL, end->in[1 + END_KEEPALIVE_OFFSET + i], irg);
815
816
817
  }
}

818
void
819
free_End (ir_node *end) {
820
  assert (end->op == op_End);
821
  end->kind = k_BAD;
822
  DEL_ARR_F(end->in);
823
  end->in = NULL;   /* @@@ make sure we get an error if we use the
Florian Liekweg's avatar
Florian Liekweg committed
824
               in array afterwards ... */
825
826
}

827
828
829
830
831
832
833
834
835
836
837
/* Return the target address of an IJmp */
ir_node *get_IJmp_target(ir_node *ijmp) {
  assert(ijmp->op == op_IJmp);
  return get_irn_n(ijmp, 0);
}

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

Götz Lindenmaier's avatar
Götz Lindenmaier committed
839
840
841
842
843
844
845
846
847
/*
> 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
848
 - determining the biggest case constant to know the proj number for
Götz Lindenmaier's avatar
Götz Lindenmaier committed
849
850
851
852
853
854
855
856
857
858
859
860
   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.,
861
libFIRM can implement a routine that transforms between the two
Götz Lindenmaier's avatar
Götz Lindenmaier committed
862
863
864
865
866
867
868
869
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).
*/
870
ir_node *
Christian Schäfer's avatar
Christian Schäfer committed
871
872
873
874
875
get_Cond_selector (ir_node *node) {
  assert (node->op == op_Cond);
  return get_irn_n(node, 0);
}

876
void
Christian Schäfer's avatar
Christian Schäfer committed
877
878
879
880
881
set_Cond_selector (ir_node *node, ir_node *selector) {
  assert (node->op == op_Cond);
  set_irn_n(node, 0, selector);
}

882
cond_kind
883
884
get_Cond_kind (ir_node *node) {
  assert (node->op == op_Cond);
885
  return node->attr.c.kind;
886
887
}

888
void
889
890
set_Cond_kind (ir_node *node, cond_kind kind) {
  assert (node->op == op_Cond);
891
  node->attr.c.kind = kind;
892
893
}

894
895
896
897
898
899
long
get_Cond_defaultProj (ir_node *node) {
  assert (node->op == op_Cond);
  return node->attr.c.default_proj;
}

900
ir_node *
Christian Schäfer's avatar
Christian Schäfer committed
901
get_Return_mem (ir_node *node) {
902
  assert (node->op == op_Return);
Christian Schäfer's avatar
Christian Schäfer committed
903
904
905
  return get_irn_n(node, 0);
}

906
void
Christian Schäfer's avatar
Christian Schäfer committed
907
908
909
910
911
set_Return_mem (ir_node *node, ir_node *mem) {
  assert (node->op == op_Return);
  set_irn_n(node, 0, mem);
}

912
int
913
get_Return_n_ress (ir_node *node) {
914
915
916
917
  assert (node->op == op_Return);
  return (get_irn_arity(node) - RETURN_RESULT_OFFSET);
}

918
ir_node **
919
920
921
get_Return_res_arr (ir_node *node)
{
  assert ((node->op == op_Return));
922
  if (get_Return_n_ress(node) > 0)
Götz Lindenmaier's avatar
Götz Lindenmaier committed
923
    return (ir_node **)&(get_irn_in(node)[1 + RETURN_RESULT_OFFSET]);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
924
925
  else
    return NULL;
926
927
}

Christian Schäfer's avatar
Christian Schäfer committed
928
/*
929
void
Christian Schäfer's avatar
Christian Schäfer committed
930
931
932
933
934
set_Return_n_res (ir_node *node, int results) {
  assert (node->op == op_Return);
}
*/

935
ir_node *
Christian Schäfer's avatar
Christian Schäfer committed
936
937
get_Return_res (ir_node *node, int pos) {
  assert (node->op == op_Return);
938
  assert (get_Return_n_ress(node) > pos);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
939
  return get_irn_n(node, pos + RETURN_RESULT_OFFSET);
Christian Schäfer's avatar
Christian Schäfer committed
940
941
}

942
void
Christian Schäfer's avatar
Christian Schäfer committed
943
set_Return_res (ir_node *node, int pos, ir_node *res){
944
  assert (node->op == op_Return);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
945
  set_irn_n(node, pos + RETURN_RESULT_OFFSET, res);
Christian Schäfer's avatar
Christian Schäfer committed
946
947
}

Sebastian Hack's avatar
Sebastian Hack committed
948
949
tarval *(get_Const_tarval)(ir_node *node) {
	return _get_Const_tarval(node);
Christian Schäfer's avatar
Christian Schäfer committed
950
951
}

952
void
Christian Schäfer's avatar
Christian Schäfer committed
953
954
set_Const_tarval (ir_node *node, tarval *con) {
  assert (node->op == op_Const);</