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 int get_irn_pinned_(const ir_node *node)
275
{
276
	assert(node->kind == k_ir_node);
Michael Beck's avatar
Michael Beck committed
277
	/* Check opcode */
278
	op_pin_state state = get_op_pinned_(get_irn_op_(node));
Michael Beck's avatar
Michael Beck committed
279
	if (state >= op_pin_state_exc_pinned)
280
		return (op_pin_state)node->attr.except.pinned;
281

Michael Beck's avatar
Michael Beck committed
282
	return state;
Michael Beck's avatar
Michael Beck committed
283
284
}

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

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

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

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

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

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

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

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

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

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

350
351
352
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
353
354
}

355
356
357
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
358
359
}

360
361
362
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
363
364
}

365
366
367
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
368
369
}

370
371
372
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
373
374
}

375
376
377
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
378
379
}

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

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

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

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

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

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

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

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

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

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

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

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

Matthias Braun's avatar
Matthias Braun committed
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
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];
}

482
483
void ir_register_getter_ops(void);

484
485
/** 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
486
487
 *  accesses the End node) */
void remove_keep_alive(const ir_node *kept_node);
488

489
490
491
492
493
494
/**
 * 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);

495
496
/**
 * Gets the Proj with number pn from irn.
497
 * Returns a null pointer, if no such Proj exists.
498
499
500
 */
ir_node *get_Proj_for_pn(ir_node const *irn, unsigned pn);

501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
/**
 * 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);
}

518
519
520
521
522
523
524
525
526
527
528
529
#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
530
#endif