irnode_t.h 14.5 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
2
/*
 * This file is part of libFirm.
3
 * Copyright (C) 2012 University of Karlsruhe.
Christian Würdig's avatar
Christian Würdig committed
4
5
 */

Michael Beck's avatar
Michael Beck committed
6
/**
Matthias Braun's avatar
Matthias Braun committed
7
8
9
 * @file
 * @brief   Representation of an intermediate operation -- private header.
 * @author  Martin Trapp, Christian Schaefer, Goetz Lindenmaier, Michael Beck
Michael Beck's avatar
Michael Beck committed
10
 */
Matthias Braun's avatar
Matthias Braun committed
11
12
#ifndef FIRM_IR_IRNODE_T_H
#define FIRM_IR_IRNODE_T_H
Götz Lindenmaier's avatar
Götz Lindenmaier committed
13

14
#include "irtypes.h"
15
16
17
18
19
#include "irnode.h"
#include "irop_t.h"
#include "irgraph_t.h"
#include "irflag_t.h"
#include "array.h"
20
#include "iredges_t.h"
Götz Lindenmaier's avatar
Götz Lindenmaier committed
21

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/* This section MUST come first, so the inline functions get used in this header. */
#define get_irn_arity(node)                   get_irn_arity_(node)
#define get_irn_n(node, n)                    get_irn_n_(node, n)
#define get_irn_mode(node)                    get_irn_mode_(node)
#define set_irn_mode(node, mode)              set_irn_mode_(node, mode)
#define get_irn_irg(node)                     get_irn_irg_(node)
#define get_nodes_block(node)                 get_nodes_block_(node)
#define get_irn_op(node)                      get_irn_op_(node)
#define get_irn_opcode(node)                  get_irn_opcode_(node)
#define get_irn_visited(node)                 get_irn_visited_(node)
#define set_irn_visited(node, v)              set_irn_visited_(node, v)
#define mark_irn_visited(node)                mark_irn_visited_(node)
#define irn_visited(node)                     irn_visited_(node)
#define irn_visited_else_mark(node)           irn_visited_else_mark_(node)
#define set_irn_link(node, link)              set_irn_link_(node, link)
#define get_irn_link(node)                    get_irn_link_(node)
#define get_irn_pinned(node)                  get_irn_pinned_(node)
#define is_binop(node)                        is_binop_(node)
#define get_Block_n_cfgpreds(node)            get_Block_n_cfgpreds_(node)
#define get_Block_cfgpred(node, pos)          get_Block_cfgpred_(node, pos)
#define get_Block_cfgpred_block(node, pos)    get_Block_cfgpred_block_(node, pos)
#define get_Block_block_visited(node)         get_Block_block_visited_(node)
#define set_Block_block_visited(node, visit)  set_Block_block_visited_(node, visit)
#define mark_Block_block_visited(node)        mark_Block_block_visited_(node)
#define Block_block_visited(node)             Block_block_visited_(node)
#define is_Const_null(node)                   is_Const_null_(node)
#define is_Const_one(node)                    is_Const_one_(node)
#define is_Const_all_one(node)                is_Const_all_one_(node)
#define is_irn_forking(node)                  is_irn_forking_(node)
#define copy_node_attr(irg,oldn,newn)         copy_node_attr_(irg,oldn,newn)
#define get_irn_type_attr(node)               get_irn_type_attr_(node)
#define get_irn_entity_attr(node)             get_irn_entity_attr_(node)
#define is_irn_constlike(node)                is_irn_constlike_(node)
#define is_irn_keep(node)                     is_irn_keep_(node)
#define is_irn_start_block_placed(node)       is_irn_start_block_placed_(node)
#define get_irn_generic_attr(node)            get_irn_generic_attr_(node)
#define get_irn_generic_attr_const(node)      get_irn_generic_attr_const_(node)
#define get_irn_idx(node)                     get_irn_idx_(node)

#define get_irn_dbg_info(node)                get_irn_dbg_info_(node)
#define set_irn_dbg_info(node, db)            set_irn_dbg_info_(node, db)

#define set_Block_phis(block, phi)            set_Block_phis_(block, phi)
#define get_Block_phis(block)                 get_Block_phis_(block)
#define add_Block_phi(block, phi)             add_Block_phi_(block, phi)
#define get_Block_mark(block)                 get_Block_mark_(block)
#define set_Block_mark(block, mark)           set_Block_mark_(block, mark)

#define set_Phi_next(node, phi)               set_Phi_next_(node, phi)
#define get_Phi_next(node)                    get_Phi_next_(node)

#define ir_switch_table_get_n_entries(table)  ir_switch_table_get_n_entries_(table)

75
/**
76
 * Returns the array with the ins.  The content of the array must not be
77
78
 * changed.
 * Note that this function returns the whole in array including the
79
 * block predecessor. So, it is NOT symmetric to set_irn_in().
80
 */
81
82
83
84
static inline ir_node **get_irn_in(ir_node const *const node)
{
	return node->in;
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
85

Michael Beck's avatar
Michael Beck committed
86
/*-------------------------------------------------------------------*/
Götz Lindenmaier's avatar
Götz Lindenmaier committed
87
88
/*  These function are most used in libfirm.  Give them as static    */
/*  functions so they can be inlined.                                */
Michael Beck's avatar
Michael Beck committed
89
/*-------------------------------------------------------------------*/
Götz Lindenmaier's avatar
Götz Lindenmaier committed
90

91
92
93
94
95
static inline unsigned get_irn_idx_(const ir_node *node)
{
	return node->node_idx;
}

96
97
98
99
/**
 * Gets the op of a node.
 * Intern version for libFirm.
 */
100
static inline ir_op *get_irn_op_(const ir_node *node)
101
{
Michael Beck's avatar
Michael Beck committed
102
	return node->op;
103
104
}

105
106
107
108
/**
 * Sets the opcode struct of the node.
 */
static inline void set_irn_op(ir_node *node, ir_op *op)
109
{
Michael Beck's avatar
Michael Beck committed
110
	node->op = op;
111
112
}

113
114
/** Copies all attributes stored in the old node  to the new node.
    Assumes both have the same opcode and sufficient size. */
115
static inline void copy_node_attr_(ir_graph *irg, const ir_node *old_node,
116
                                   ir_node *new_node)
117
{
118
	ir_op *op = get_irn_op_(old_node);
119

Michael Beck's avatar
Michael Beck committed
120
	/* must always exist */
121
	op->ops.copy_attr(irg, old_node, new_node);
122
123
}

124
125
126
127
/**
 * Gets the opcode of a node.
 * Intern version for libFirm.
 */
128
static inline unsigned get_irn_opcode_(const ir_node *node)
129
{
Michael Beck's avatar
Michael Beck committed
130
131
	assert(k_ir_node == get_kind(node));
	return node->op->code;
132
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
133

Michael Beck's avatar
Michael Beck committed
134
135
136
137
/**
 * Returns the number of predecessors without the block predecessor.
 * Intern version for libFirm.
 */
138
static inline int get_irn_arity_(const ir_node *node)
139
{
140
	return (int)(ARR_LEN(node->in) - 1);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
141
142
}

143
144
145
146
/* forward decl... */
#define is_Id(node) is_Id_(node)
static inline int is_Id_(const ir_node *node);

Michael Beck's avatar
Michael Beck committed
147
148
149
/**
 * Intern version for libFirm.
 */
150
static inline ir_node *get_irn_n_(const ir_node *node, int n)
151
{
Michael Beck's avatar
Michael Beck committed
152
	ir_node *nn;
Michael Beck's avatar
Michael Beck committed
153

154
	assert(-1 <= n && n < get_irn_arity_(node));
155

Michael Beck's avatar
Michael Beck committed
156
	nn = node->in[n + 1];
157
	if (!is_Id(nn)) return nn;
Michael Beck's avatar
Michael Beck committed
158

Michael Beck's avatar
Michael Beck committed
159
	return (node->in[n + 1] = skip_Id(nn));
Götz Lindenmaier's avatar
Götz Lindenmaier committed
160
161
}

162
163
164
/* include generated code */
#include "gen_irnode.h"

165
166
167
/**
 * returns a hash value for a node
 */
168
static inline unsigned hash_irn(const ir_node *node)
169
170
171
172
{
	return (unsigned) get_irn_idx(node);
}

Michael Beck's avatar
Michael Beck committed
173
174
175
176
/**
 * Gets the mode of a node.
 * Intern version for libFirm.
 */
177
static inline ir_mode *get_irn_mode_(const ir_node *node)
178
{
Michael Beck's avatar
Michael Beck committed
179
	return node->mode;
Götz Lindenmaier's avatar
Götz Lindenmaier committed
180
181
}

Michael Beck's avatar
Michael Beck committed
182
/**
183
184
185
 * Sets the mode of a node.
 * Intern version of libFirm.
 */
186
static inline void set_irn_mode_(ir_node *node, ir_mode *mode)
187
{
Michael Beck's avatar
Michael Beck committed
188
	node->mode = mode;
189
190
}

191
192
193
194
195
196
static inline ir_node *get_nodes_block_(const ir_node *node)
{
	assert(!is_Block(node));
	return get_irn_n(node, -1);
}

197
static inline ir_graph *get_irn_irg_(const ir_node *node)
198
{
199
	return node->irg;
200
201
}

202
203
/**
 * Gets the visited counter of a node.
Michael Beck's avatar
Michael Beck committed
204
205
 * Intern version for libFirm.
 */
206
static inline ir_visited_t get_irn_visited_(const ir_node *node)
207
{
Michael Beck's avatar
Michael Beck committed
208
	return node->visited;
Götz Lindenmaier's avatar
Götz Lindenmaier committed
209
210
}

Michael Beck's avatar
Michael Beck committed
211
/**
212
 * Sets the visited counter of a node.
Michael Beck's avatar
Michael Beck committed
213
214
 * Intern version for libFirm.
 */
215
static inline void set_irn_visited_(ir_node *node, ir_visited_t visited)
216
{
Michael Beck's avatar
Michael Beck committed
217
	node->visited = visited;
218
219
220
221
222
223
}

/**
 * Mark a node as visited in a graph.
 * Intern version for libFirm.
 */
224
static inline void mark_irn_visited_(ir_node *node)
225
{
226
	node->visited = get_irn_irg(node)->visited;
227
228
229
230
231
232
}

/**
 * Returns non-zero if a node of was visited.
 * Intern version for libFirm.
 */
233
static inline int irn_visited_(const ir_node *node)
234
{
235
236
	ir_graph *irg = get_irn_irg(node);
	return node->visited >= irg->visited;
Götz Lindenmaier's avatar
Götz Lindenmaier committed
237
238
}

239
static inline int irn_visited_else_mark_(ir_node *node)
240
{
241
	if (irn_visited_(node))
242
		return 1;
243
	mark_irn_visited_(node);
244
245
246
	return 0;
}

247
248
249
250
/**
 * Sets the link of a node.
 * Intern version of libFirm.
 */
251
static inline void set_irn_link_(ir_node *node, void *link)
252
{
253
	assert(ir_resources_reserved(get_irn_irg(node)) & IR_RESOURCE_IRN_LINK);
Michael Beck's avatar
Michael Beck committed
254
	node->link = link;
255
256
257
258
259
260
}

/**
 * Returns the link of a node.
 * Intern version of libFirm.
 */
261
static inline void *get_irn_link_(const ir_node *node)
262
{
263
	assert(node->kind == k_ir_node);
264
	assert(ir_resources_reserved(get_irn_irg(node)) & IR_RESOURCE_IRN_LINK);
Michael Beck's avatar
Michael Beck committed
265
	return node->link;
266
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
267

Michael Beck's avatar
Michael Beck committed
268
/**
269
270
271
 * Returns whether the node _always_ must be pinned.
 * I.e., the node is not floating after global cse.
 *
Michael Beck's avatar
Michael Beck committed
272
273
 * Intern version of libFirm.
 */
274
static inline op_pin_state get_irn_pinned_(const ir_node *node)
275
{
Michael Beck's avatar
Michael Beck committed
276
	op_pin_state state;
277
	assert(node->kind == k_ir_node);
Michael Beck's avatar
Michael Beck committed
278
	/* Check opcode */
279
	state = get_op_pinned_(get_irn_op_(node));
280

Michael Beck's avatar
Michael Beck committed
281
	if (state >= op_pin_state_exc_pinned)
282
		return (op_pin_state)node->attr.except.pin_state;
283

Michael Beck's avatar
Michael Beck committed
284
	return state;
Michael Beck's avatar
Michael Beck committed
285
286
}

287
static inline int is_binop_(const ir_node *node)
288
{
289
	assert(node->kind == k_ir_node);
Michael Beck's avatar
Michael Beck committed
290
	return (node->op->opar == oparity_binary);
Michael Beck's avatar
Michael Beck committed
291
292
}

293
294
295
296
297
static inline bool is_irn_dynamic(ir_node const *const n)
{
	return get_irn_op(n)->opar == oparity_dynamic;
}

298
299
/**
 * Get the predecessor block.
300
 *
301
 * Returns the block corresponding to the predecessor pos.
302
 *
303
 * If we encounter the Bad node, this function returns NULL.
304
 */
305
static inline ir_node *get_Block_cfgpred_block_(const ir_node *node, int pos)
306
{
307
308
	ir_node *res = get_Block_cfgpred(node, pos);
	if (is_Bad(res)) {
309
		return NULL;
310
	} else {
311
		return get_nodes_block(res);
312
	}
313
314
}

315
static inline ir_visited_t get_Block_block_visited_(const ir_node *node)
316
{
317
	assert(is_Block(node));
Michael Beck's avatar
Michael Beck committed
318
	return node->attr.block.block_visited;
Michael Beck's avatar
Michael Beck committed
319
320
}

321
static inline void set_Block_block_visited_(ir_node *node, ir_visited_t visit)
322
{
323
	assert(is_Block(node));
Michael Beck's avatar
Michael Beck committed
324
	node->attr.block.block_visited = visit;
Michael Beck's avatar
Michael Beck committed
325
326
}

327
static inline void mark_Block_block_visited_(ir_node *node)
328
{
329
	node->attr.block.block_visited = get_irg_block_visited(node->irg);
Michael Beck's avatar
Michael Beck committed
330
331
}

332
static inline int Block_block_visited_(const ir_node *node)
333
{
334
	return node->attr.block.block_visited >= get_irg_block_visited(node->irg);
335
336
}

337
338
339
340
341
static inline long get_Const_long(ir_node const *const node)
{
	return get_tarval_long(get_Const_tarval_(node));
}

342
343
344
static inline int is_Const_null_(const ir_node *node)
{
	return tarval_is_null(get_Const_tarval_(node));
345
}
Sebastian Hack's avatar
Sebastian Hack committed
346

347
348
349
static inline int is_Const_one_(const ir_node *node)
{
	return tarval_is_one(get_Const_tarval_(node));
350
}
Sebastian Hack's avatar
Sebastian Hack committed
351

352
353
354
static inline int is_Const_all_one_(const ir_node *node)
{
	return tarval_is_all_one(get_Const_tarval_(node));
Sebastian Hack's avatar
Sebastian Hack committed
355
356
}

357
358
359
static inline int is_irn_forking_(const ir_node *node)
{
	return is_op_forking(get_irn_op_(node));
Michael Beck's avatar
Michael Beck committed
360
361
}

362
363
364
static inline ir_type *get_irn_type_attr_(ir_node *node)
{
	return get_irn_op_(node)->ops.get_type_attr(node);
Michael Beck's avatar
Michael Beck committed
365
366
}

367
368
369
static inline ir_entity *get_irn_entity_attr_(ir_node *node)
{
	return get_irn_op_(node)->ops.get_entity_attr(node);
Michael Beck's avatar
Michael Beck committed
370
371
}

372
373
374
static inline int is_irn_constlike_(const ir_node *node)
{
	return is_op_constlike(get_irn_op_(node));
Michael Beck's avatar
Michael Beck committed
375
376
}

377
378
379
static inline int is_irn_keep_(const ir_node *node)
{
	return is_op_keep(get_irn_op_(node));
Michael Beck's avatar
Michael Beck committed
380
381
}

382
383
static inline int is_irn_start_block_placed_(const ir_node *node)
{
384
	return is_op_start_block_placed(get_irn_op_(node));
385
386
}

387
388
static inline void *get_irn_generic_attr_(ir_node *node)
{
389
390
391
	return &node->attr;
}

392
393
static inline const void *get_irn_generic_attr_const_(const ir_node *node)
{
394
395
396
	return &node->attr;
}

397
398
static inline dbg_info *get_irn_dbg_info_(const ir_node *n)
{
399
	return n->dbi;
400
}
401

402
403
static inline void set_irn_dbg_info_(ir_node *n, dbg_info *db)
{
404
405
406
	n->dbi = db;
}

407
408
409
/**
 * Sets the Phi list of a block.
 */
410
static inline void set_Block_phis_(ir_node *block, ir_node *phi)
411
{
412
	assert(ir_resources_reserved(get_irn_irg(block)) & IR_RESOURCE_PHI_LIST);
413
414
	assert(is_Block_(block));
	assert(phi == NULL || is_Phi_(phi));
415
416
417
418
419
420
421
	block->attr.block.phis = phi;
}

/**
 * Returns the link of a node.
 * Intern version of libFirm.
 */
422
static inline ir_node *get_Block_phis_(const ir_node *block)
423
{
424
	assert(ir_resources_reserved(get_irn_irg(block)) & IR_RESOURCE_PHI_LIST);
425
	assert(is_Block_(block));
426
427
428
	return block->attr.block.phis;
}

429
static inline void set_Phi_next_(ir_node *phi, ir_node *next)
430
{
431
	assert(ir_resources_reserved(get_irn_irg(phi)) & IR_RESOURCE_PHI_LIST);
432
	assert(is_Phi_(phi));
433
434
435
	phi->attr.phi.next = next;
}

436
static inline ir_node *get_Phi_next_(const ir_node *phi)
437
{
438
	assert(ir_resources_reserved(get_irn_irg(phi)) & IR_RESOURCE_PHI_LIST);
439
	assert(is_Phi_(phi));
440
441
442
	return phi->attr.phi.next;
}

Michael Beck's avatar
Michael Beck committed
443
/** Add a Phi node to the list of Block Phi's. */
444
static inline void add_Block_phi_(ir_node *block, ir_node *phi)
445
{
446
447
448
	assert(is_Block_(block));
	set_Phi_next_(phi, get_Block_phis_(block));
	set_Block_phis_(block, phi);
Michael Beck's avatar
Michael Beck committed
449
450
}

451
/** Get the Block mark (single bit). */
452
static inline unsigned get_Block_mark_(const ir_node *block)
453
{
454
	assert(is_Block_(block));
455
456
457
458
	return block->attr.block.marked;
}

/** Set the Block mark (single bit). */
459
static inline void set_Block_mark_(ir_node *block, unsigned mark)
460
{
461
	assert(is_Block_(block));
462
463
	block->attr.block.marked = mark;
}
Michael Beck's avatar
Michael Beck committed
464

Matthias Braun's avatar
Matthias Braun committed
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
static inline size_t ir_switch_table_get_n_entries_(const ir_switch_table *table)
{
	return table->n_entries;
}

static inline ir_switch_table_entry *ir_switch_table_get_entry(
		ir_switch_table *table, size_t entry)
{
	assert(entry < table->n_entries);
	return &table->entries[entry];
}

static inline const ir_switch_table_entry *ir_switch_table_get_entry_const(
		const ir_switch_table *table, size_t entry)
{
	assert(entry < table->n_entries);
	return &table->entries[entry];
}

484
485
void ir_register_getter_ops(void);

486
487
/** remove keep alive edge to node by rerouting the edge to a Bad node.
 * (rerouting is preferable to removing when we are in a walker which also
488
489
 *  accesses the End node) */
void remove_keep_alive(const ir_node *kept_node);
490

491
492
493
494
495
496
/**
 * Create a node similar to @p old.  Except for @p block and @p in all aspects
 * are copied from @p old.
 */
ir_node *new_similar_node(ir_node *old, ir_node *block, ir_node **in);

497
498
499
500
501
/**
 * Gets the Proj with number pn from irn.
 */
ir_node *get_Proj_for_pn(ir_node const *irn, unsigned pn);

502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
/**
 * Convenient block getter.
 * Works also, if the given node is a block.
 * @param  irn The node.
 * @return The block of the node, or the node itself, if the node is a
 *         block.
 */
static inline ir_node *get_block(ir_node *const irn)
{
	return is_Block(irn) ? irn : get_nodes_block(irn);
}

static inline ir_node const *get_block_const(ir_node const *const irn)
{
	return is_Block(irn) ? irn : get_nodes_block(irn);
}

519
520
521
522
523
524
525
526
527
528
529
530
#define foreach_irn_in(irn, idx, pred) \
	for (bool pred##__b = true; pred##__b;) \
		for (ir_node const *const pred##__irn = (irn); pred##__b; pred##__b = false) \
			for (int idx = 0, pred##__n = get_irn_arity(pred##__irn); pred##__b && idx != pred##__n; ++idx) \
				for (ir_node *const pred = (pred##__b = false, get_irn_n(pred##__irn, idx)); !pred##__b; pred##__b = true)

#define foreach_irn_in_r(irn, idx, pred) \
	for (bool pred##__b = true; pred##__b;) \
		for (ir_node const *const pred##__irn = (irn); pred##__b; pred##__b = false) \
			for (int idx = get_irn_arity(pred##__irn); pred##__b && idx-- != 0;) \
				for (ir_node *const pred = (pred##__b = false, get_irn_n(pred##__irn, idx)); !pred##__b; pred##__b = true)

Matthias Braun's avatar
Matthias Braun committed
531
#endif