irnode.c 64.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
 * IR node constructor.
 * Create a new IR node in irg, with an op, mode, arity and
 * some incoming IR nodes.
125
126
 * If arity is negative, a node with a dynamic array is created.
 */
127
ir_node *
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;
135
  op_pin_state state;
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
148
149
150
  state = get_op_pinned(op);

  res->kind      = k_ir_node;
  res->op        = op;
  res->mode      = mode;
  res->visited   = 0;
  res->node_idx  = irg_register_node_idx(irg, res);
  res->pinned    = state != op_pin_state_floats;
  res->link      = NULL;
Christian Schäfer's avatar
Christian Schäfer committed
151
  if (arity < 0) {
152
    res->in = NEW_ARR_F (ir_node *, 1);  /* 1: space for block */
Christian Schäfer's avatar
Christian Schäfer committed
153
154
155
156
  } 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
157

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

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

166
167
168
169
  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
170

171

172
173
  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
174
175

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

Christian Schäfer's avatar
Christian Schäfer committed
177
178
179
  return res;
}

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

Sebastian Felis's avatar
Sebastian Felis committed
182
int
183
(is_ir_node)(const void *thing) {
184
  return _is_ir_node(thing);
Sebastian Felis's avatar
Sebastian Felis committed
185
186
}

187
int
188
(get_irn_intra_arity)(const ir_node *node) {
189
  return _get_irn_intra_arity(node);
Christian Schäfer's avatar
Christian Schäfer committed
190
191
}

192
int
193
(get_irn_inter_arity)(const ir_node *node) {
194
  return _get_irn_inter_arity(node);
195
196
}

197
int (*_get_irn_arity)(const ir_node *node) = _get_irn_intra_arity;
198

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

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

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

244
245
246
247
248
249
250
251
  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);
252
253
  }

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

261
  memcpy((*arr) + 1, in, sizeof(ir_node *) * arity);
262
263
}

264
ir_node *
Sebastian Hack's avatar
Sebastian Hack committed
265
(get_irn_intra_n)(const ir_node *node, int n) {
266
  return _get_irn_intra_n (node, n);
267
268
}

269
ir_node *
Sebastian Hack's avatar
Sebastian Hack committed
270
(get_irn_inter_n)(const ir_node *node, int n) {
271
  return _get_irn_inter_n (node, n);
272
273
}

274
ir_node *(*_get_irn_n)(const ir_node *node, int n) = _get_irn_intra_n;
275

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

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

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

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

310
311
  /* 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
312

313
  node->in[n + 1] = in;
Christian Schäfer's avatar
Christian Schäfer committed
314
315
}

316
ir_mode *
317
(get_irn_mode)(const ir_node *node) {
318
  return _get_irn_mode(node);
Christian Schäfer's avatar
Christian Schäfer committed
319
320
}

321
void
322
(set_irn_mode)(ir_node *node, ir_mode *mode)
Till Riedel's avatar
Till Riedel committed
323
{
324
  _set_irn_mode(node, mode);
Till Riedel's avatar
Till Riedel committed
325
326
}

327
modecode
328
get_irn_modecode (const ir_node *node)
Christian Schäfer's avatar
Christian Schäfer committed
329
330
331
332
333
{
  assert (node);
  return node->mode->code;
}

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

342
ident *
343
get_irn_modeident (const ir_node *node)
Götz Lindenmaier's avatar
Götz Lindenmaier committed
344
345
{
  assert(node);
346
  return get_mode_ident(node->mode);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
347
348
}

349
ir_op *
350
(get_irn_op)(const ir_node *node) {
351
  return _get_irn_op(node);
Christian Schäfer's avatar
Christian Schäfer committed
352
353
354
}

/* should be private to the library: */
355
void
356
357
(set_irn_op)(ir_node *node, ir_op *op) {
	_set_irn_op(node, op);
Christian Schäfer's avatar
Christian Schäfer committed
358
359
}

360
opcode
361
(get_irn_opcode)(const ir_node *node)
362
{
363
  return _get_irn_opcode(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
364
365
}

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

376
ident *
377
get_irn_opident (const ir_node *node)
Götz Lindenmaier's avatar
Götz Lindenmaier committed
378
379
380
{
  assert(node);
  return node->op->name;
381
382
}

383
unsigned long
384
(get_irn_visited)(const ir_node *node)
385
{
386
  return _get_irn_visited(node);
387
388
}

389
void
390
(set_irn_visited)(ir_node *node, unsigned long visited)
Christian Schäfer's avatar
Christian Schäfer committed
391
{
392
  _set_irn_visited(node, visited);
Christian Schäfer's avatar
Christian Schäfer committed
393
}
394

395
void
396
(mark_irn_visited)(ir_node *node) {
397
  _mark_irn_visited(node);
398
399
}

400
int
401
(irn_not_visited)(const ir_node *node) {
402
  return _irn_not_visited(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
403
404
}

405
int
406
(irn_visited)(const ir_node *node) {
407
  return _irn_visited(node);
408
409
}

410
void
411
(set_irn_link)(ir_node *node, void *link) {
412
  _set_irn_link(node, link);
Christian Schäfer's avatar
Christian Schäfer committed
413
414
}

415
void *
416
(get_irn_link)(const ir_node *node) {
417
  return _get_irn_link(node);
Christian Schäfer's avatar
Christian Schäfer committed
418
419
}

420
421
op_pin_state
(get_irn_pinned)(const ir_node *node) {
422
  return _get_irn_pinned(node);
423
424
}

425
426
427
428
429
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
430
431
432
433
434
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;

435
436
437
438
439
440
441
  assert(node);
  assert(
    /* the node is exception/memory pinned OR */
    (get_op_pinned(get_irn_op(node)) >= op_pin_state_exc_pinned) ||
    /* a floating point node can be pinned if fp_exceptions are enabled */
    (mode_is_float(get_irn_mode(node)) && get_irg_fp_model(get_irn_irg(node)) & fp_exceptions)
  );
Michael Beck's avatar
Michael Beck committed
442
443
  assert(state == op_pin_state_pinned || state == op_pin_state_floats);

444
  node->pinned = state != op_pin_state_floats;
Michael Beck's avatar
Michael Beck committed
445
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462

#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;
}
463
464
465
466
467
468
#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
469
470
471
#endif /* DO_HEAPANALYSIS */


Götz Lindenmaier's avatar
Götz Lindenmaier committed
472
/* Outputs a unique number for this node */
473
long get_irn_node_nr(const ir_node *node) {
Götz Lindenmaier's avatar
Götz Lindenmaier committed
474
  assert(node);
475
#ifdef DEBUG_libfirm
Götz Lindenmaier's avatar
Götz Lindenmaier committed
476
  return node->node_nr;
477
#else
478
  return (long)PTR_TO_INT(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
479
#endif
480
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
481

482
const_attr
Christian Schäfer's avatar
Christian Schäfer committed
483
484
485
486
487
488
get_irn_const_attr (ir_node *node)
{
  assert (node->op == op_Const);
  return node->attr.con;
}

489
long
Christian Schäfer's avatar
Christian Schäfer committed
490
491
492
493
494
495
get_irn_proj_attr (ir_node *node)
{
  assert (node->op == op_Proj);
  return node->attr.proj;
}

496
alloc_attr
Christian Schäfer's avatar
Christian Schäfer committed
497
498
499
get_irn_alloc_attr (ir_node *node)
{
  assert (node->op == op_Alloc);
500
  return node->attr.alloc;
Christian Schäfer's avatar
Christian Schäfer committed
501
502
}

503
free_attr
Christian Schäfer's avatar
Christian Schäfer committed
504
505
506
get_irn_free_attr     (ir_node *node)
{
  assert (node->op == op_Free);
507
  return node->attr.free;
Christian Schäfer's avatar
Christian Schäfer committed
508
509
}

510
symconst_attr
Christian Schäfer's avatar
Christian Schäfer committed
511
512
513
get_irn_symconst_attr (ir_node *node)
{
  assert (node->op == op_SymConst);
514
  return node->attr.symc;
Christian Schäfer's avatar
Christian Schäfer committed
515
516
}

Michael Beck's avatar
Michael Beck committed
517
ir_type *
Christian Schäfer's avatar
Christian Schäfer committed
518
519
520
get_irn_call_attr (ir_node *node)
{
  assert (node->op == op_Call);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
521
  return node->attr.call.cld_tp = skip_tid(node->attr.call.cld_tp);
Christian Schäfer's avatar
Christian Schäfer committed
522
523
}

524
sel_attr
Christian Schäfer's avatar
Christian Schäfer committed
525
526
527
get_irn_sel_attr (ir_node *node)
{
  assert (node->op == op_Sel);
528
  return node->attr.sel;
Christian Schäfer's avatar
Christian Schäfer committed
529
530
}

531
int
Christian Schäfer's avatar
Christian Schäfer committed
532
533
534
535
536
537
get_irn_phi_attr (ir_node *node)
{
  assert (node->op == op_Phi);
  return node->attr.phi0_pos;
}

538
block_attr
Christian Schäfer's avatar
Christian Schäfer committed
539
540
541
542
543
544
get_irn_block_attr (ir_node *node)
{
  assert (node->op == op_Block);
  return node->attr.block;
}

545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
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 ||
563
          node->op == op_DivMod || node->op == op_Mod || node->op == op_Call || node->op == op_Alloc);
564
565
566
  return node->attr.except;
}

567
568
569
570
571
void *
get_irn_generic_attr (ir_node *node) {
  return &node->attr;
}

572
573
574
575
576
unsigned (get_irn_idx)(const ir_node *node) {
  assert(is_ir_node(node));
  return _get_irn_idx(node);
}

577
578
579
580
581
582
583
584
585
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
586
587
588
589
/** manipulate fields of individual nodes **/

/* this works for all except Block */
ir_node *
Sebastian Hack's avatar
Sebastian Hack committed
590
get_nodes_block (const ir_node *node) {
Christian Schäfer's avatar
Christian Schäfer committed
591
  assert (!(node->op == op_Block));
592
	assert (is_irn_pinned_in_irg(node) && "block info may be incorrect");
Christian Schäfer's avatar
Christian Schäfer committed
593
594
595
  return get_irn_n(node, -1);
}

596
void
597
set_nodes_block (ir_node *node, ir_node *block) {
Christian Schäfer's avatar
Christian Schäfer committed
598
599
600
601
  assert (!(node->op == op_Block));
  set_irn_n(node, -1, block);
}

602
603
/* 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
604
ir_type *is_frame_pointer(ir_node *n) {
605
  if (is_Proj(n) && (get_Proj_proj(n) == pn_Start_P_frame_base)) {
606
607
608
609
610
611
612
613
614
615
    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
616
ir_type *is_globals_pointer(ir_node *n) {
617
  if (is_Proj(n) && (get_Proj_proj(n) == pn_Start_P_globals)) {
618
619
620
621
622
623
624
625
    ir_node *start = get_Proj_pred(n);
    if (get_irn_op(start) == op_Start) {
      return get_glob_type();
    }
  }
  return NULL;
}

626
627
628
629
630
631
632
633
634
635
636
637
/* 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;
}

638
639
640
641
642
643
644
645
646
647
/* 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;
}

648
/* Returns an array with the predecessors of the Block. Depending on
649
   the implementation of the graph data structure this can be a copy of
650
651
   the internal representation of predecessors as well as the internal
   array itself. Therefore writing to this array might obstruct the ir. */
652
ir_node **
653
654
655
get_Block_cfgpred_arr (ir_node *node)
{
  assert ((node->op == op_Block));
Götz Lindenmaier's avatar
Götz Lindenmaier committed
656
  return (ir_node **)&(get_irn_in(node)[1]);
657
658
}

659
int
660
(get_Block_n_cfgpreds)(ir_node *node) {
Michael Beck's avatar
Michael Beck committed
661
  return _get_Block_n_cfgpreds(node);
Christian Schäfer's avatar
Christian Schäfer committed
662
663
}

664
ir_node *
665
(get_Block_cfgpred)(ir_node *node, int pos) {
Michael Beck's avatar
Michael Beck committed
666
  return _get_Block_cfgpred(node, pos);
Christian Schäfer's avatar
Christian Schäfer committed
667
668
}

669
void
Christian Schäfer's avatar
Christian Schäfer committed
670
671
672
673
674
set_Block_cfgpred (ir_node *node, int pos, ir_node *pred) {
  assert (node->op == op_Block);
  set_irn_n(node, pos, pred);
}

675
676
677
678
679
ir_node  *
(get_Block_cfgpred_block)(ir_node *node, int pos) {
  return _get_Block_cfgpred_block(node, pos);
}

680
int
Christian Schäfer's avatar
Christian Schäfer committed
681
682
get_Block_matured (ir_node *node) {
  assert (node->op == op_Block);
683
  return (int)node->attr.block.matured;
Christian Schäfer's avatar
Christian Schäfer committed
684
685
}

686
void
687
set_Block_matured (ir_node *node, int matured) {
Christian Schäfer's avatar
Christian Schäfer committed
688
689
690
  assert (node->op == op_Block);
  node->attr.block.matured = matured;
}
Michael Beck's avatar
Michael Beck committed
691

692
unsigned long
Michael Beck's avatar
Michael Beck committed
693
694
(get_Block_block_visited)(ir_node *node) {
  return _get_Block_block_visited(node);
Christian Schäfer's avatar
Christian Schäfer committed
695
696
}

697
void
Michael Beck's avatar
Michael Beck committed
698
699
(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
700
701
}

Götz Lindenmaier's avatar
Götz Lindenmaier committed
702
/* For this current_ir_graph must be set. */
703
void
Michael Beck's avatar
Michael Beck committed
704
705
(mark_Block_block_visited)(ir_node *node) {
  _mark_Block_block_visited(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
706
707
}

708
int
Michael Beck's avatar
Michael Beck committed
709
710
(Block_not_block_visited)(ir_node *node) {
  return _Block_not_block_visited(node);
711
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
712

713
ir_node *
Christian Schäfer's avatar
Christian Schäfer committed
714
715
716
717
718
get_Block_graph_arr (ir_node *node, int pos) {
  assert (node->op == op_Block);
  return node->attr.block.graph_arr[pos+1];
}

719
void
Christian Schäfer's avatar
Christian Schäfer committed
720
721
722
723
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;
}
724

725
726
727
728
729
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;
730
    node->attr.block.cg_backedge = new_backedge_arr(current_ir_graph->obst, arity);
731
    {
732
      /* Fix backedge array.  fix_backedges() operates depending on
Florian Liekweg's avatar
Florian Liekweg committed
733
     interprocedural_view. */
734
      int ipv = get_interprocedural_view();
735
      set_interprocedural_view(1);
736
      fix_backedges(current_ir_graph->obst, node);
737
      set_interprocedural_view(ipv);
738
    }
739
740
741
742
743
  }
  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
744
  assert(node->op == op_Block &&
Florian Liekweg's avatar
Florian Liekweg committed
745
746
     node->attr.block.in_cg &&
     0 <= pos && pos < ARR_LEN(node->attr.block.in_cg) - 1);
747
748
749
750
751
752
753
754
755
  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) {
756
757
  assert(node->op == op_Block);
  return node->attr.block.in_cg == NULL ? 0 : ARR_LEN(node->attr.block.in_cg) - 1;
758
759
}

760
761
762
763
764
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];
}

765
766
767
768
769
void remove_Block_cg_cfgpred_arr(ir_node * node) {
  assert(node->op == op_Block);
  node->attr.block.in_cg = NULL;
}

770
ir_node *(set_Block_dead)(ir_node *block) {
771
  return _set_Block_dead(block);
772
773
774
}

int (is_Block_dead)(const ir_node *block) {
775
  return _is_Block_dead(block);
776
777
}

778
ir_extblk *get_Block_extbb(const ir_node *block) {
Michael Beck's avatar
Michael Beck committed
779
	ir_extblk *res;
780
  assert(is_Block(block));
Michael Beck's avatar
Michael Beck committed
781
782
783
	res = block->attr.block.extblk;
	assert(res == NULL || is_ir_extbb(res));
  return res;
784
785
786
787
}

void set_Block_extbb(ir_node *block, ir_extblk *extblk) {
  assert(is_Block(block));
Michael Beck's avatar
Michael Beck committed
788
	assert(extblk == NULL || is_ir_extbb(extblk));
789
790
791
  block->attr.block.extblk = extblk;
}

792
int
793
794
795
796
797
get_End_n_keepalives(ir_node *end) {
  assert (end->op == op_End);
  return (get_irn_arity(end) - END_KEEPALIVE_OFFSET);
}

798
ir_node *
799
800
801
802
803
get_End_keepalive(ir_node *end, int pos) {
  assert (end->op == op_End);
  return get_irn_n(end, pos + END_KEEPALIVE_OFFSET);
}

804
void
805
add_End_keepalive (ir_node *end, ir_node *ka) {
Michael Beck's avatar
Michael Beck committed
806
807
808
809
810
811
  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);
812
  edges_notify_edge(end, l - 1, end->in[l], NULL, irg);
813
814
}

815
void
816
817
818
819
820
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);
}

821
822
823
824
825
826
/* 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 */
827
828
  for (i = 1 + END_KEEPALIVE_OFFSET; i < ARR_LEN(end->in); ++i) {
    edges_notify_edge(end, i, end->in[i], NULL, irg);
829
  }
830
  ARR_RESIZE(ir_node *, end->in, n + 1 + END_KEEPALIVE_OFFSET);
831
832

  for (i = 0; i < n; ++i) {
833
    end->in[1 + END_KEEPALIVE_OFFSET + i] = in[i];
834
    edges_notify_edge(end, END_KEEPALIVE_OFFSET + i, NULL, end->in[1 + END_KEEPALIVE_OFFSET + i], irg);
835
836
837
  }
}

838
void
839
free_End (ir_node *end) {
840
  assert (end->op == op_End);
841
  end->kind = k_BAD;
842
  DEL_ARR_F(end->in);
843
  end->in = NULL;   /* @@@ make sure we get an error if we use the
Florian Liekweg's avatar
Florian Liekweg committed
844
               in array afterwards ... */
845
846
}

847
848
849
850
851
852
853
854
855
856
857
/* 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);
}
858

Götz Lindenmaier's avatar
Götz Lindenmaier committed
859
860
861
862
863
864
865
866
867
/*
> 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
868
 - determining the biggest case constant to know the proj number for
Götz Lindenmaier's avatar
Götz Lindenmaier committed
869
870
871
872
873
874
875
876
877
878
879
880
   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.,
881
libFIRM can implement a routine that transforms between the two
Götz Lindenmaier's avatar
Götz Lindenmaier committed
882
883
884
885
886
887
888
889
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).
*/
890
ir_node *
Christian Schäfer's avatar
Christian Schäfer committed
891
892
893
894
895
get_Cond_selector (ir_node *node) {
  assert (node->op == op_Cond);
  return get_irn_n(node, 0);
}

896
void
Christian Schäfer's avatar
Christian Schäfer committed
897
898
899
900
901
set_Cond_selector (ir_node *node, ir_node *selector) {
  assert (node->op == op_Cond);
  set_irn_n(node, 0, selector);
}

902
cond_kind
903
904
get_Cond_kind (ir_node *node) {
  assert (node->op == op_Cond);
905
  return node->attr.cond.kind;
906
907
}

908
void
909
910
set_Cond_kind (ir_node *node, cond_kind kind) {
  assert (node->op == op_Cond);
911
  node->attr.cond.kind = kind;
912
913
}

914
915
916
long
get_Cond_defaultProj (ir_node *node) {
  assert (node->op == op_Cond);
917
  return node->attr.cond.default_proj;
918
919
}

920
ir_node *
Christian Schäfer's avatar
Christian Schäfer committed
921
get_Return_mem (ir_node *node) {
922
  assert (node->op == op_Return);
Christian Schäfer's avatar
Christian Schäfer committed
923
924
925
  return get_irn_n(node, 0);
}

926
void
Christian Schäfer's avatar
Christian Schäfer committed
927
928
929
930
931
set_Return_mem (ir_node *node, ir_node *mem) {
  assert (node->op == op_Return);
  set_irn_n(node, 0, mem);
}

932
int
933
get_Return_n_ress (ir_node *node) {
934
935
936
937
  assert (node->op == op_Return);
  return (get_irn_arity(node) - RETURN_RESULT_OFFSET);
}

938
ir_node **
939
940
941
get_Return_res_arr (ir_node *node)
{
  assert ((node->op == op_Return));
942
  if (get_Return_n_ress(node) > 0)
Götz Lindenmaier's avatar
Götz Lindenmaier committed
943
    return (ir_node **)&(get_irn_in(node)[1 + RETURN_RESULT_OFFSET]);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
944
945
  else
    return NULL;
946
947