irnode.c 59.1 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
 */
59
60
61
62
63
64
65
66
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
67
68
}

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

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

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

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


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

107
108
  if (forbid_new_data)
    return 0;
109

110
  return firm_add_node_size += size;
111
112
113
}


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

120
121
122
123
124
125
/*
 * 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.
 */
126
ir_node *
Götz Lindenmaier's avatar
Götz Lindenmaier committed
127
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
128
         int arity, ir_node **in)
Christian Schäfer's avatar
Christian Schäfer committed
129
130
{
  ir_node *res;
131
  size_t node_size = offsetof(ir_node, attr) + op->attr_size + firm_add_node_size;
132
	char *p;
Christian Schäfer's avatar
Christian Schäfer committed
133

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

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

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

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

159
160
161
162
#if FIRM_EDGES_INPLACE
  {
    int i, n;
    int not_a_block = is_no_Block(res);
Sebastian Hack's avatar
Sebastian Hack committed
163

164
    INIT_LIST_HEAD(&res->edge_info.outs_head);
165
166
167
    if(!not_a_block)
      INIT_LIST_HEAD(&res->attr.block.succ_head);

Sebastian Hack's avatar
Sebastian Hack committed
168

169
170
171
    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
172
173
174
#endif

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

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

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

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

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

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

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

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

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

224
void
225
set_irn_in (ir_node *node, int arity, ir_node **in) {
226
  int i;
227
  ir_node *** arr;
228
  assert(node);
229
  if (get_interprocedural_view()) { /* handle Filter and Block specially */
230
231
232
233
234
235
236
237
238
239
240
    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;
  }
241
242
243
244
245
246
247
248
249
250
251
252

	for (i = 0; i < arity; i++) {
		if (i < ARR_LEN(*arr)-1)
    	edges_notify_edge(node, i, in[i], (*arr)[i+1], current_ir_graph);
		else
	    edges_notify_edge(node, i, in[i], NULL,        current_ir_graph);
  }
	for(;i < ARR_LEN(*arr)-1; i++) {
		edges_notify_edge(node, i, NULL, (*arr)[i+1], current_ir_graph);
	}

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

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

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

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

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

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

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

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

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

308
309
  /* 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
310

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

#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;
}
458
459
460
461
462
463
#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
464
465
466
#endif /* DO_HEAPANALYSIS */


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

478
const_attr
Christian Schäfer's avatar
Christian Schäfer committed
479
480
481
482
483
484
get_irn_const_attr (ir_node *node)
{
  assert (node->op == op_Const);
  return node->attr.con;
}

485
long
Christian Schäfer's avatar
Christian Schäfer committed
486
487
488
489
490
491
get_irn_proj_attr (ir_node *node)
{
  assert (node->op == op_Proj);
  return node->attr.proj;
}

492
alloc_attr
Christian Schäfer's avatar
Christian Schäfer committed
493
494
495
496
497
498
get_irn_alloc_attr (ir_node *node)
{
  assert (node->op == op_Alloc);
  return node->attr.a;
}

499
free_attr
Christian Schäfer's avatar
Christian Schäfer committed
500
501
502
get_irn_free_attr     (ir_node *node)
{
  assert (node->op == op_Free);
503
  return node->attr.f;
Christian Schäfer's avatar
Christian Schäfer committed
504
505
}

506
symconst_attr
Christian Schäfer's avatar
Christian Schäfer committed
507
508
509
510
511
512
get_irn_symconst_attr (ir_node *node)
{
  assert (node->op == op_SymConst);
  return node->attr.i;
}

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

520
sel_attr
Christian Schäfer's avatar
Christian Schäfer committed
521
522
523
524
525
526
get_irn_sel_attr (ir_node *node)
{
  assert (node->op == op_Sel);
  return node->attr.s;
}

527
int
Christian Schäfer's avatar
Christian Schäfer committed
528
529
530
531
532
533
get_irn_phi_attr (ir_node *node)
{
  assert (node->op == op_Phi);
  return node->attr.phi0_pos;
}

534
block_attr
Christian Schäfer's avatar
Christian Schäfer committed
535
536
537
538
539
540
get_irn_block_attr (ir_node *node)
{
  assert (node->op == op_Block);
  return node->attr.block;
}

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

563
564
565
566
567
void *
get_irn_generic_attr (ir_node *node) {
  return &node->attr;
}

Christian Schäfer's avatar
Christian Schäfer committed
568
569
570
571
/** manipulate fields of individual nodes **/

/* this works for all except Block */
ir_node *
Sebastian Hack's avatar
Sebastian Hack committed
572
get_nodes_block (const ir_node *node) {
Christian Schäfer's avatar
Christian Schäfer committed
573
  assert (!(node->op == op_Block));
574
	assert (is_irn_pinned_in_irg(node) && "block info may be incorrect");
Christian Schäfer's avatar
Christian Schäfer committed
575
576
577
  return get_irn_n(node, -1);
}

578
void
579
set_nodes_block (ir_node *node, ir_node *block) {
Christian Schäfer's avatar
Christian Schäfer committed
580
581
582
583
  assert (!(node->op == op_Block));
  set_irn_n(node, -1, block);
}

584
585
/* 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
586
ir_type *is_frame_pointer(ir_node *n) {
587
588
589
590
591
592
593
594
595
596
597
598
  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
599
ir_type *is_globals_pointer(ir_node *n) {
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
  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;
}

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

631
int
632
633
(get_Block_n_cfgpreds)(ir_node *node) {
  return get_Block_n_cfgpreds(node);
Christian Schäfer's avatar
Christian Schäfer committed
634
635
}

636
ir_node *
637
638
(get_Block_cfgpred)(ir_node *node, int pos) {
  return get_Block_cfgpred(node, pos);
Christian Schäfer's avatar
Christian Schäfer committed
639
640
}

641
void
Christian Schäfer's avatar
Christian Schäfer committed
642
643
644
645
646
set_Block_cfgpred (ir_node *node, int pos, ir_node *pred) {
  assert (node->op == op_Block);
  set_irn_n(node, pos, pred);
}

647
648
649
650
651
ir_node  *
(get_Block_cfgpred_block)(ir_node *node, int pos) {
  return _get_Block_cfgpred_block(node, pos);
}

652
int
Christian Schäfer's avatar
Christian Schäfer committed
653
654
get_Block_matured (ir_node *node) {
  assert (node->op == op_Block);
655
  return (int)node->attr.block.matured;
Christian Schäfer's avatar
Christian Schäfer committed
656
657
}

658
void
659
set_Block_matured (ir_node *node, int matured) {
Christian Schäfer's avatar
Christian Schäfer committed
660
661
662
  assert (node->op == op_Block);
  node->attr.block.matured = matured;
}
Michael Beck's avatar
Michael Beck committed
663

664
unsigned long
Michael Beck's avatar
Michael Beck committed
665
666
(get_Block_block_visited)(ir_node *node) {
  return _get_Block_block_visited(node);
Christian Schäfer's avatar
Christian Schäfer committed
667
668
}

669
void
Michael Beck's avatar
Michael Beck committed
670
671
(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
672
673
}

Götz Lindenmaier's avatar
Götz Lindenmaier committed
674
/* For this current_ir_graph must be set. */
675
void
Michael Beck's avatar
Michael Beck committed
676
677
(mark_Block_block_visited)(ir_node *node) {
  _mark_Block_block_visited(node);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
678
679
}

680
int
Michael Beck's avatar
Michael Beck committed
681
682
(Block_not_block_visited)(ir_node *node) {
  return _Block_not_block_visited(node);
683
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
684

685
ir_node *
Christian Schäfer's avatar
Christian Schäfer committed
686
687
688
689
690
get_Block_graph_arr (ir_node *node, int pos) {
  assert (node->op == op_Block);
  return node->attr.block.graph_arr[pos+1];
}

691
void
Christian Schäfer's avatar
Christian Schäfer committed
692
693
694
695
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;
}
696

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

732
733
734
735
736
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];
}

737
738
739
740
741
void remove_Block_cg_cfgpred_arr(ir_node * node) {
  assert(node->op == op_Block);
  node->attr.block.in_cg = NULL;
}

742
ir_node *(set_Block_dead)(ir_node *block) {
743
  return _set_Block_dead(block);
744
745
746
}

int (is_Block_dead)(const ir_node *block) {
747
  return _is_Block_dead(block);
748
749
}

750
751
752
753
754
755
756
757
758
759
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;
}

760
void
761
762
763
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
764
  assert(0 && " Why set irg? -- use set_irn_irg");
765
766
}

767
int
768
769
770
771
772
get_End_n_keepalives(ir_node *end) {
  assert (end->op == op_End);
  return (get_irn_arity(end) - END_KEEPALIVE_OFFSET);
}

773
ir_node *
774
775
776
777
778
get_End_keepalive(ir_node *end, int pos) {
  assert (end->op == op_End);
  return get_irn_n(end, pos + END_KEEPALIVE_OFFSET);
}

779
void
780
781
782
783
784
add_End_keepalive (ir_node *end, ir_node *ka) {
  assert (end->op == op_End);
  ARR_APP1 (ir_node *, end->in, ka);
}

785
void
786
787
788
789
790
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);
}

791
void
792
free_End (ir_node *end) {
793
  assert (end->op == op_End);
794
  end->kind = k_BAD;
795
  DEL_ARR_F(end->in);  /* GL @@@ tut nicht ! */
796
  end->in = NULL;   /* @@@ make sure we get an error if we use the
Florian Liekweg's avatar
Florian Liekweg committed
797
               in array afterwards ... */
798
799
}

800
801
802
803
804
805
806
807
808
809
810
/* 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);
}
811

Götz Lindenmaier's avatar
Götz Lindenmaier committed
812
813
814
815
816
817
818
819
820
/*
> 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
821
 - determining the biggest case constant to know the proj number for
Götz Lindenmaier's avatar
Götz Lindenmaier committed
822
823
824
825
826
827
828
829
830
831
832
833
   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.,
834
libFIRM can implement a routine that transforms between the two
Götz Lindenmaier's avatar
Götz Lindenmaier committed
835
836
837
838
839
840
841
842
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).
*/
843
ir_node *
Christian Schäfer's avatar
Christian Schäfer committed
844
845
846
847
848
get_Cond_selector (ir_node *node) {
  assert (node->op == op_Cond);
  return get_irn_n(node, 0);
}

849
void
Christian Schäfer's avatar
Christian Schäfer committed
850
851
852
853
854
set_Cond_selector (ir_node *node, ir_node *selector) {
  assert (node->op == op_Cond);
  set_irn_n(node, 0, selector);
}

855
cond_kind
856
857
get_Cond_kind (ir_node *node) {
  assert (node->op == op_Cond);
858
  return node->attr.c.kind;
859
860
}

861
void
862
863
set_Cond_kind (ir_node *node, cond_kind kind) {
  assert (node->op == op_Cond);
864
  node->attr.c.kind = kind;
865
866
}

867
868
869
870
871
872
long
get_Cond_defaultProj (ir_node *node) {
  assert (node->op == op_Cond);
  return node->attr.c.default_proj;
}

873
ir_node *
Christian Schäfer's avatar
Christian Schäfer committed
874
get_Return_mem (ir_node *node) {
875
  assert (node->op == op_Return);
Christian Schäfer's avatar
Christian Schäfer committed
876
877
878
  return get_irn_n(node, 0);
}

879
void
Christian Schäfer's avatar
Christian Schäfer committed
880
881
882
883
884
set_Return_mem (ir_node *node, ir_node *mem) {
  assert (node->op == op_Return);
  set_irn_n(node, 0, mem);
}

885
int
886
get_Return_n_ress (ir_node *node) {
887
888
889
890
  assert (node->op == op_Return);
  return (get_irn_arity(node) - RETURN_RESULT_OFFSET);
}

891
ir_node **
892
893
894
get_Return_res_arr (ir_node *node)
{
  assert ((node->op == op_Return));
895
  if (get_Return_n_ress(node) > 0)
Götz Lindenmaier's avatar
Götz Lindenmaier committed
896
    return (ir_node **)&(get_irn_in(node)[1 + RETURN_RESULT_OFFSET]);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
897
898
  else
    return NULL;
899
900
}

Christian Schäfer's avatar
Christian Schäfer committed
901
/*
902
void
Christian Schäfer's avatar
Christian Schäfer committed
903
904
905
906
907
set_Return_n_res (ir_node *node, int results) {
  assert (node->op == op_Return);
}
*/

908
ir_node *
Christian Schäfer's avatar
Christian Schäfer committed
909
910
get_Return_res (ir_node *node, int pos) {
  assert (node->op == op_Return);
911
  assert (get_Return_n_ress(node) > pos);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
912
  return get_irn_n(node, pos + RETURN_RESULT_OFFSET);
Christian Schäfer's avatar
Christian Schäfer committed
913
914
}

915
void
Christian Schäfer's avatar
Christian Schäfer committed
916
set_Return_res (ir_node *node, int pos, ir_node *res){
917
  assert (node->op == op_Return);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
918
  set_irn_n(node, pos + RETURN_RESULT_OFFSET, res);
Christian Schäfer's avatar
Christian Schäfer committed
919
920
}

921
ir_node *
Christian Schäfer's avatar
Christian Schäfer committed
922
get_Raise_mem (ir_node *node) {
Till Riedel's avatar
Till Riedel committed
923
  assert (node->op == op_Raise);
Christian Schäfer's avatar
Christian Schäfer committed
924
925
926
  return get_irn_n(node, 0);
}

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

933
ir_node *
Christian Schäfer's avatar
Christian Schäfer committed
934
935
936
937
938
get_Raise_exo_ptr (ir_node *node) {
  assert (node->op == op_Raise);
  return get_irn_n(node, 1);
}

939
void
Christian Schäfer's avatar
Christian Schäfer committed
940
941
942
943
944
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
945
946
tarval *(get_Const_tarval)(ir_node *node) {
	return _get_Const_tarval(node);
Christian Schäfer's avatar
Christian Schäfer committed
947
948
}

949
void
Christian Schäfer's avatar
Christian Schäfer committed
950
951
set_Const_tarval (ir_node *node, tarval *con) {
  assert (node->op == op_Const);
952
  node->attr.con.tv = con;
Christian Schäfer's avatar
Christian Schäfer committed
953
954
}

Sebastian Hack's avatar
Sebastian Hack committed
955
956
957
958
959
cnst_classify_t (classify_Const)(ir_node *node)
{
	return _classify_Const(node);
}

960
961
962
963

/* 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. */
Michael Beck's avatar
Michael Beck committed
964
ir_type *
965
966
967
968
969
get_Const_type (ir_node *node) {
  assert (node->op == op_Const);
  return node->attr.con.tp;
}

970
void
Michael Beck's avatar
Michael Beck committed
971
set_Const_type (ir_node *node, ir_type *tp) {
972
  assert (node->op == op_Const);