irnode.c 52.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"
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
 * Calculates the negated (Complement(R)) pnc condition.
Michael Beck's avatar
Michael Beck committed
58
 */
Christian Schäfer's avatar
Christian Schäfer committed
59
60
61
int
get_negated_pnc(int pnc) {
  switch (pnc) {
Michael Beck's avatar
Michael Beck committed
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
  case pn_Cmp_False: return pn_Cmp_True;
  case pn_Cmp_Eq:    return pn_Cmp_Ne;
  case pn_Cmp_Lt:    return pn_Cmp_Uge;
  case pn_Cmp_Le:    return pn_Cmp_Ug;
  case pn_Cmp_Gt:    return pn_Cmp_Ule;
  case pn_Cmp_Ge:    return pn_Cmp_Ul;
  case pn_Cmp_Lg:    return pn_Cmp_Ue;
  case pn_Cmp_Leg:   return pn_Cmp_Uo;
  case pn_Cmp_Uo:    return pn_Cmp_Leg;
  case pn_Cmp_Ue:    return pn_Cmp_Lg;
  case pn_Cmp_Ul:    return pn_Cmp_Ge;
  case pn_Cmp_Ule:   return pn_Cmp_Gt;
  case pn_Cmp_Ug:    return pn_Cmp_Le;
  case pn_Cmp_Uge:   return pn_Cmp_Lt;
  case pn_Cmp_Ne:    return pn_Cmp_Eq;
  case pn_Cmp_True:  return pn_Cmp_False;
Christian Schäfer's avatar
Christian Schäfer committed
78
79
80
81
  }
  return 99; /* to shut up gcc */
}

82
/* Calculates the inversed (R^-1) pnc condition, i.e., "<" --> ">" */
Michael Beck's avatar
Michael Beck committed
83
int
84
get_inversed_pnc(int pnc) {
Michael Beck's avatar
Michael Beck committed
85
86
87
88
89
90
91
92
93
  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;
}

94
const char *pns_name_arr [] = {
95
96
97
  "initial_exec", "global_store",
  "frame_base", "globals", "args"
};
Christian Schäfer's avatar
Christian Schäfer committed
98

99
const char *symconst_name_arr [] = {
Beyhan's avatar
Beyhan committed
100
  "type_tag", "size", "addr_name", "addr_ent"
101
};
Christian Schäfer's avatar
Christian Schäfer committed
102

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


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

120
121
  if (forbid_new_data)
    return 0;
122

123
  return firm_add_node_size += size;
124
125
126
}


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

133
134
135
136
137
138
/*
 * 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.
 */
139
ir_node *
Götz Lindenmaier's avatar
Götz Lindenmaier committed
140
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
141
         int arity, ir_node **in)
Christian Schäfer's avatar
Christian Schäfer committed
142
143
{
  ir_node *res;
144
  size_t node_size = offsetof(ir_node, attr) + op->attr_size + firm_add_node_size;
145
	char *p;
Christian Schäfer's avatar
Christian Schäfer committed
146

147
  assert(irg && op && mode);
148
149
  p = obstack_alloc (irg->obst, node_size);
  memset(p, 0, node_size);
150
	res = (ir_node *) (p + firm_add_node_size);
Christian Schäfer's avatar
Christian Schäfer committed
151

Michael Beck's avatar
Michael Beck committed
152
153
154
  res->kind    = k_ir_node;
  res->op      = op;
  res->mode    = mode;
155
  res->visited = 0;
Michael Beck's avatar
Michael Beck committed
156
  res->link    = NULL;
Christian Schäfer's avatar
Christian Schäfer committed
157
  if (arity < 0) {
158
    res->in = NEW_ARR_F (ir_node *, 1);  /* 1: space for block */
Christian Schäfer's avatar
Christian Schäfer committed
159
160
161
162
  } 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
163

Christian Schäfer's avatar
Christian Schäfer committed
164
  res->in[0] = block;
Götz Lindenmaier's avatar
Götz Lindenmaier committed
165
  set_irn_dbg_info(res, db);
166
  res->out = NULL;
Götz Lindenmaier's avatar
Götz Lindenmaier committed
167
168
169
170
171

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

172
173
174
175
#if FIRM_EDGES_INPLACE
  {
    int i, n;
    int not_a_block = is_no_Block(res);
Sebastian Hack's avatar
Sebastian Hack committed
176

177
    INIT_LIST_HEAD(&res->edge_info.outs_head);
Sebastian Hack's avatar
Sebastian Hack committed
178

179
180
181
    for (i = 0, n = arity + not_a_block; i < n; ++i)
      edges_notify_edge(res, i - not_a_block, res->in[i], NULL, irg);
  }
Sebastian Hack's avatar
Sebastian Hack committed
182
183
184
#endif

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

Christian Schäfer's avatar
Christian Schäfer committed
186
187
188
  return res;
}

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

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

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

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

206
int (*_get_irn_arity)(const ir_node *node) = _get_irn_intra_arity;
207

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

213
214
215
216
217
218
/* 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. */
219
ir_node **
220
get_irn_in (const ir_node *node) {
221
  assert(node);
222
  if (get_interprocedural_view()) { /* handle Filter and Block specially */
223
224
225
226
227
228
229
230
231
    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
232
233
}

234
void
235
set_irn_in (ir_node *node, int arity, ir_node **in) {
236
  ir_node *** arr;
237
  assert(node);
238
  if (get_interprocedural_view()) { /* handle Filter and Block specially */
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
    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;
254
  }
255
  fix_backedges(current_ir_graph->obst, node);
256
  memcpy((*arr) + 1, in, sizeof(ir_node *) * arity);
257
258
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

344
ir_op *
345
(get_irn_op)(const ir_node *node)
Christian Schäfer's avatar
Christian Schäfer committed
346
{
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
Christian Schäfer's avatar
Christian Schäfer committed
352
353
354
355
356
357
set_irn_op (ir_node *node, ir_op *op)
{
  assert (node);
  node->op = op;
}

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

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

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

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

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

393
void
394
(mark_irn_visited)(ir_node *node) {
395
  _mark_irn_visited(node);
396
397
}

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

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

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

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

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

Michael Beck's avatar
Michael Beck committed
423
424
425
426
427
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;

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

#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;
}
450
451
452
453
454
455
#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
456
457
458
#endif /* DO_HEAPANALYSIS */


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

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

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

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

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

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

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

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

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

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

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

Christian Schäfer's avatar
Christian Schäfer committed
555
556
557
558
/** manipulate fields of individual nodes **/

/* this works for all except Block */
ir_node *
Sebastian Hack's avatar
Sebastian Hack committed
559
get_nodes_block (const ir_node *node) {
Christian Schäfer's avatar
Christian Schäfer committed
560
561
562
563
  assert (!(node->op == op_Block));
  return get_irn_n(node, -1);
}

564
void
565
set_nodes_block (ir_node *node, ir_node *block) {
Christian Schäfer's avatar
Christian Schäfer committed
566
567
568
569
  assert (!(node->op == op_Block));
  set_irn_n(node, -1, block);
}

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
596
597
598
599
600
601
602
603
604
605
/* 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;
}

606
/* Returns an array with the predecessors of the Block. Depending on
607
   the implementation of the graph data structure this can be a copy of
608
609
   the internal representation of predecessors as well as the internal
   array itself. Therefore writing to this array might obstruct the ir. */
610
ir_node **
611
612
613
get_Block_cfgpred_arr (ir_node *node)
{
  assert ((node->op == op_Block));
Götz Lindenmaier's avatar
Götz Lindenmaier committed
614
  return (ir_node **)&(get_irn_in(node)[1]);
615
616
}

617
int
Christian Schäfer's avatar
Christian Schäfer committed
618
619
get_Block_n_cfgpreds (ir_node *node) {
  assert ((node->op == op_Block));
620
  return get_irn_arity(node);
Christian Schäfer's avatar
Christian Schäfer committed
621
622
}

623
ir_node *
Christian Schäfer's avatar
Christian Schäfer committed
624
get_Block_cfgpred (ir_node *node, int pos) {
625
  assert(-1 <= pos && pos < get_irn_arity(node));
626
  assert(node->op == op_Block);
Christian Schäfer's avatar
Christian Schäfer committed
627
628
629
  return get_irn_n(node, pos);
}

630
void
Christian Schäfer's avatar
Christian Schäfer committed
631
632
633
634
635
set_Block_cfgpred (ir_node *node, int pos, ir_node *pred) {
  assert (node->op == op_Block);
  set_irn_n(node, pos, pred);
}

636
bool
Christian Schäfer's avatar
Christian Schäfer committed
637
638
639
640
641
get_Block_matured (ir_node *node) {
  assert (node->op == op_Block);
  return node->attr.block.matured;
}

642
void
Christian Schäfer's avatar
Christian Schäfer committed
643
644
645
646
set_Block_matured (ir_node *node, bool matured) {
  assert (node->op == op_Block);
  node->attr.block.matured = matured;
}
Michael Beck's avatar
Michael Beck committed
647

648
unsigned long
Michael Beck's avatar
Michael Beck committed
649
650
(get_Block_block_visited)(ir_node *node) {
  return _get_Block_block_visited(node);
Christian Schäfer's avatar
Christian Schäfer committed
651
652
}

653
void
Michael Beck's avatar
Michael Beck committed
654
655
(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
656
657
}

Götz Lindenmaier's avatar
Götz Lindenmaier committed
658
/* For this current_ir_graph must be set. */
659
void
Michael Beck's avatar
Michael Beck committed
660
661
(mark_Block_block_visited)(ir_node *node) {
  _mark_Block_block_visited(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
662
663
}

664
int
Michael Beck's avatar
Michael Beck committed
665
666
(Block_not_block_visited)(ir_node *node) {
  return _Block_not_block_visited(node);
667
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
668

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

675
void
Christian Schäfer's avatar
Christian Schäfer committed
676
677
678
679
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;
}
680

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

716
717
718
719
720
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];
}

721
722
723
724
725
void remove_Block_cg_cfgpred_arr(ir_node * node) {
  assert(node->op == op_Block);
  node->attr.block.in_cg = NULL;
}

726
ir_node *(set_Block_dead)(ir_node *block) {
727
  return _set_Block_dead(block);
728
729
730
}

int (is_Block_dead)(const ir_node *block) {
731
  return _is_Block_dead(block);
732
733
}

734
735
736
737
738
739
740
741
742
743
ir_extblk *get_Block_extbb(const ir_node *block) {
  assert(is_Block(block));
  return block->attr.block.extblk;
}

void set_Block_extbb(ir_node *block, ir_extblk *extblk) {
  assert(is_Block(block));
  block->attr.block.extblk = extblk;
}

744
void
745
746
747
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
748
  assert(0 && " Why set irg? -- use set_irn_irg");
749
750
}

751
int
752
753
754
755
756
get_End_n_keepalives(ir_node *end) {
  assert (end->op == op_End);
  return (get_irn_arity(end) - END_KEEPALIVE_OFFSET);
}

757
ir_node *
758
759
760
761
762
get_End_keepalive(ir_node *end, int pos) {
  assert (end->op == op_End);
  return get_irn_n(end, pos + END_KEEPALIVE_OFFSET);
}

763
void
764
765
766
767
768
add_End_keepalive (ir_node *end, ir_node *ka) {
  assert (end->op == op_End);
  ARR_APP1 (ir_node *, end->in, ka);
}

769
void
770
771
772
773
774
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);
}

775
void
776
free_End (ir_node *end) {
777
  assert (end->op == op_End);
778
  end->kind = k_BAD;
779
  DEL_ARR_F(end->in);  /* GL @@@ tut nicht ! */
780
  end->in = NULL;   /* @@@ make sure we get an error if we use the
Florian Liekweg's avatar
Florian Liekweg committed
781
               in array afterwards ... */
782
783
}

784

Götz Lindenmaier's avatar
Götz Lindenmaier committed
785
786
787
788
789
790
791
792
793
/*
> 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
794
 - determining the biggest case constant to know the proj number for
Götz Lindenmaier's avatar
Götz Lindenmaier committed
795
796
797
798
799
800
801
802
803
804
805
806
   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.,
807
libFIRM can implement a routine that transforms between the two
Götz Lindenmaier's avatar
Götz Lindenmaier committed
808
809
810
811
812
813
814
815
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).
*/
816
ir_node *
Christian Schäfer's avatar
Christian Schäfer committed
817
818
819
820
821
get_Cond_selector (ir_node *node) {
  assert (node->op == op_Cond);
  return get_irn_n(node, 0);
}

822
void
Christian Schäfer's avatar
Christian Schäfer committed
823
824
825
826
827
set_Cond_selector (ir_node *node, ir_node *selector) {
  assert (node->op == op_Cond);
  set_irn_n(node, 0, selector);
}

828
cond_kind
829
830
get_Cond_kind (ir_node *node) {
  assert (node->op == op_Cond);
831
  return node->attr.c.kind;
832
833
}

834
void
835
836
set_Cond_kind (ir_node *node, cond_kind kind) {
  assert (node->op == op_Cond);
837
  node->attr.c.kind = kind;
838
839
}

840
841
842
843
844
845
long
get_Cond_defaultProj (ir_node *node) {
  assert (node->op == op_Cond);
  return node->attr.c.default_proj;
}

846
ir_node *
Christian Schäfer's avatar
Christian Schäfer committed
847
get_Return_mem (ir_node *node) {
848
  assert (node->op == op_Return);
Christian Schäfer's avatar
Christian Schäfer committed
849
850
851
  return get_irn_n(node, 0);
}

852
void
Christian Schäfer's avatar
Christian Schäfer committed
853
854
855
856
857
set_Return_mem (ir_node *node, ir_node *mem) {
  assert (node->op == op_Return);
  set_irn_n(node, 0, mem);
}

858
int
859
get_Return_n_ress (ir_node *node) {
860
861
862
863
  assert (node->op == op_Return);
  return (get_irn_arity(node) - RETURN_RESULT_OFFSET);
}

864
ir_node **
865
866
867
get_Return_res_arr (ir_node *node)
{
  assert ((node->op == op_Return));
868
  if (get_Return_n_ress(node) > 0)
Götz Lindenmaier's avatar
Götz Lindenmaier committed
869
    return (ir_node **)&(get_irn_in(node)[1 + RETURN_RESULT_OFFSET]);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
870
871
  else
    return NULL;
872
873
}

Christian Schäfer's avatar
Christian Schäfer committed
874
/*
875
void
Christian Schäfer's avatar
Christian Schäfer committed
876
877
878
879
880
set_Return_n_res (ir_node *node, int results) {
  assert (node->op == op_Return);
}
*/

881
ir_node *
Christian Schäfer's avatar
Christian Schäfer committed
882
883
get_Return_res (ir_node *node, int pos) {
  assert (node->op == op_Return);
884
  assert (get_Return_n_ress(node) > pos);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
885
  return get_irn_n(node, pos + RETURN_RESULT_OFFSET);
Christian Schäfer's avatar
Christian Schäfer committed
886
887
}

888
void
Christian Schäfer's avatar
Christian Schäfer committed
889
set_Return_res (ir_node *node, int pos, ir_node *res){
890
  assert (node->op == op_Return);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
891
  set_irn_n(node, pos + RETURN_RESULT_OFFSET, res);
Christian Schäfer's avatar
Christian Schäfer committed
892
893
}

894
ir_node *
Christian Schäfer's avatar
Christian Schäfer committed
895
get_Raise_mem (ir_node *node) {
Till Riedel's avatar
Till Riedel committed
896
  assert (node->op == op_Raise);
Christian Schäfer's avatar
Christian Schäfer committed
897
898
899
  return get_irn_n(node, 0);
}

900
void
Christian Schäfer's avatar
Christian Schäfer committed
901
902
903
904
905
set_Raise_mem (ir_node *node, ir_node *mem) {
  assert (node->op == op_Raise);
  set_irn_n(node, 0, mem);
}

906
ir_node *
Christian Schäfer's avatar
Christian Schäfer committed
907
908
909
910
911
get_Raise_exo_ptr (ir_node *node) {
  assert (node->op == op_Raise);
  return get_irn_n(node, 1);
}

912
void
Christian Schäfer's avatar
Christian Schäfer committed
913
914
915
916
917
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
918
919
tarval *(get_Const_tarval)(ir_node *node) {
	return _get_Const_tarval(node);
Christian Schäfer's avatar
Christian Schäfer committed
920
921
}

922
void
Christian Schäfer's avatar
Christian Schäfer committed
923
924
set_Const_tarval (ir_node *node, tarval *con) {
  assert (node->op == op_Const);
925
  node->attr.con.tv = con;
Christian Schäfer's avatar
Christian Schäfer committed
926
927
}

Sebastian Hack's avatar
Sebastian Hack committed
928
929
930
931
932
cnst_classify_t (classify_Const)(ir_node *node)
{
	return _classify_Const(node);
}

933
934
935
936

/* 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. */
937
type *
938
939
940
941
942
get_Const_type (ir_node *node) {
  assert (node->op == op_Const);
  return node->attr.con.tp;
}

943
void
944
945
set_Const_type (ir_node *node, type *tp) {
  assert (node->op == op_Const);
946
  if (tp != firm_unknown_type) {
Götz Lindenmaier's avatar
Götz Lindenmaier committed
947
    assert (is_atomic_type(tp));
948
949
950
951
952
953
    assert (get_type_mode(tp) == get_irn_mode(node));
  }
  node->attr.con.tp = tp;
}


954
symconst_kind
955
get_SymConst_kind (const ir_node *node) {
Christian Schäfer's avatar
Christian Schäfer committed
956
957
958
959
  assert (node->op == op_SymConst);
  return node->attr.i.num;
}

960
void
Christian Schäfer's avatar
Christian Schäfer committed
961
962
963
964
965
set_SymConst_kind (ir_node *node, symconst_kind num) {
  assert (node->op == op_SymConst);
  node->attr.i.num = num;
}

966
type *
Christian Schäfer's avatar
Christian Schäfer committed
967
968
get_SymConst_type (ir_node *node) {
  assert (   (node->op == op_SymConst)
Beyhan's avatar
Beyhan committed
969
970
971
          && (   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
972
973
}

974
void
975
set_SymConst_type (ir_node *node, type *tp) {
Christian Schäfer's avatar
Christian Schäfer committed
976
  assert (   (node->op == op_SymConst)
Beyhan's avatar
Beyhan committed
977
978
979
          && (   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
980
981
}