2 * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
4 * This file is part of libFirm.
6 * This file may be distributed and/or modified under the terms of the
7 * GNU General Public License version 2 as published by the Free Software
8 * Foundation and appearing in the file LICENSE.GPL included in the
9 * packaging of this file.
11 * Licensees holding valid libFirm Professional Edition licenses may use
12 * this file in accordance with the libFirm Commercial License.
13 * Agreement provided with the Software.
15 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * @brief Representation of an intermediate operation -- private header.
23 * @author Martin Trapp, Christian Schaefer, Goetz Lindenmaier, Michael Beck
26 #ifndef FIRM_IR_IRNODE_T_H
27 #define FIRM_IR_IRNODE_T_H
32 #include "irgraph_t.h"
37 * Returns the array with the ins. The content of the array may not be
39 * Note that this function returns the whole in array including the
40 * block predecessor. So, it is NOT symmetric with set_irn_in().
42 ir_node **get_irn_in (const ir_node *node);
45 * The amount of additional space for custom data to be allocated upon creating a new node.
47 extern unsigned firm_add_node_size;
50 * Sets the get_type operation for an ir_op_ops.
52 * @param code the opcode for the default operation
53 * @param ops the operations initialized
58 ir_op_ops *firm_set_default_get_type(ir_opcode code, ir_op_ops *ops);
61 * Sets the get_type_attr operation for an ir_op_ops.
63 * @param code the opcode for the default operation
64 * @param ops the operations initialized
69 ir_op_ops *firm_set_default_get_type_attr(ir_opcode code, ir_op_ops *ops);
72 * Sets the get_entity_attr operation for an ir_op_ops.
74 * @param code the opcode for the default operation
75 * @param ops the operations initialized
80 ir_op_ops *firm_set_default_get_entity_attr(ir_opcode code, ir_op_ops *ops);
83 * Returns an array with the predecessors of the Block. Depending on
84 * the implementation of the graph data structure this can be a copy of
85 * the internal representation of predecessors as well as the internal
86 * array itself. Therefore writing to this array might obstruct the IR.
88 ir_node **get_Block_cfgpred_arr(ir_node *node);
90 /*-------------------------------------------------------------------*/
91 /* These function are most used in libfirm. Give them as static */
92 /* functions so they can be inlined. */
93 /*-------------------------------------------------------------------*/
96 * Checks whether a pointer points to a ir node.
97 * Intern version for libFirm.
99 static inline int _is_ir_node(const void *thing)
101 return (get_kind(thing) == k_ir_node);
105 * Gets the op of a node.
106 * Intern version for libFirm.
108 static inline ir_op *_get_irn_op(const ir_node *node)
114 static inline void _set_irn_op(ir_node *node, ir_op *op)
120 /** Copies all attributes stored in the old node to the new node.
121 Assumes both have the same opcode and sufficient size. */
122 static inline void _copy_node_attr(ir_graph *irg, const ir_node *old_node,
125 ir_op *op = _get_irn_op(old_node);
127 /* must always exist */
128 op->ops.copy_attr(irg, old_node, new_node);
132 * Gets the opcode of a node.
133 * Intern version for libFirm.
135 static inline unsigned _get_irn_opcode(const ir_node *node)
137 assert(k_ir_node == get_kind(node));
139 return node->op->code;
143 * Returns the number of predecessors without the block predecessor.
144 * Intern version for libFirm.
146 static inline int _get_irn_intra_arity(const ir_node *node)
149 return ARR_LEN(node->in) - 1;
153 * Returns the number of predecessors without the block predecessor.
154 * Intern version for libFirm.
156 static inline int _get_irn_inter_arity(const ir_node *node)
159 if (_get_irn_op(node) == op_Filter) {
160 assert(node->attr.filter.in_cg);
161 return ARR_LEN(node->attr.filter.in_cg) - 1;
162 } else if (_get_irn_op(node) == op_Block && node->attr.block.in_cg) {
163 return ARR_LEN(node->attr.block.in_cg) - 1;
165 return _get_irn_intra_arity(node);
168 #ifdef INTERPROCEDURAL_VIEW
170 * Returns the number of predecessors without the block predecessor.
171 * Intern version for libFirm.
173 extern int (*_get_irn_arity)(const ir_node *node);
177 #define _get_irn_arity(n) _get_irn_intra_arity(n)
181 * Intern version for libFirm.
183 static inline ir_node *_get_irn_intra_n(const ir_node *node, int n)
188 assert(-1 <= n && n < _get_irn_intra_arity(node));
190 nn = node->in[n + 1];
192 /* only block and Anchor inputs are allowed to be NULL */
193 assert((node->op == op_Anchor || n == -1) && "NULL input of a node");
196 if (nn->op != op_Id) return nn;
198 return (node->in[n + 1] = skip_Id(nn));
202 * Intern version for libFirm.
204 static inline ir_node *_get_irn_inter_n(const ir_node *node, int n)
206 assert(node); assert(-1 <= n && n < _get_irn_inter_arity(node));
208 /* handle Filter and Block specially */
209 if (_get_irn_op(node) == op_Filter) {
210 assert(node->attr.filter.in_cg);
211 return (node->attr.filter.in_cg[n + 1] = skip_Id(node->attr.filter.in_cg[n + 1]));
212 } else if (_get_irn_op(node) == op_Block && node->attr.block.in_cg) {
213 return (node->attr.block.in_cg[n + 1] = skip_Id(node->attr.block.in_cg[n + 1]));
216 return _get_irn_intra_n(node, n);
220 * returns a hash value for a node
222 static inline unsigned hash_irn(const ir_node *node)
224 return (unsigned) get_irn_idx(node);
228 * Access to the predecessors of a node.
229 * To iterate over the operands iterate from 0 to i < get_irn_arity(),
230 * to iterate including the Block predecessor iterate from i = -1 to
232 * If it is a block, the entry -1 is NULL.
233 * Intern version for libFirm.
235 #ifdef INTERPROCEDURAL_VIEW
236 extern ir_node *(*_get_irn_n)(const ir_node *node, int n);
238 #define _get_irn_n(n,i) _get_irn_intra_n(n,i)
241 static inline int _get_irn_deps(const ir_node *node) {
242 return node->deps ? ARR_LEN(node->deps) : 0;
245 static inline ir_node *_get_irn_dep(const ir_node *node, int pos) {
246 assert(node->deps && "dependency array node yet allocated. use add_irn_dep()");
247 assert(pos >= 0 && pos < ARR_LEN(node->deps) && "dependency index out of range");
248 return node->deps[pos];
251 static inline void _set_irn_dep(ir_node *node, int pos, ir_node *dep)
255 assert(node->deps && "dependency array node yet allocated. use add_irn_dep()");
256 assert(pos >= 0 && pos < ARR_LEN(node->deps) && "dependency index out of range");
257 old = node->deps[pos];
258 node->deps[pos] = dep;
259 edges_notify_edge_kind(node, pos, dep, old, EDGE_KIND_DEP, get_irn_irg(node));
263 static inline int _get_irn_ins_or_deps(const ir_node *irn)
265 return _get_irn_deps(irn) + _get_irn_arity(irn);
268 static inline ir_node *_get_irn_in_or_dep(const ir_node *irn, int pos)
270 int n_in = get_irn_arity(irn);
271 return pos < n_in ? get_irn_n(irn, pos) : get_irn_dep(irn, pos - n_in);
275 * Gets the mode of a node.
276 * Intern version for libFirm.
278 static inline ir_mode *_get_irn_mode(const ir_node *node)
285 * Sets the mode of a node.
286 * Intern version of libFirm.
288 static inline void _set_irn_mode(ir_node *node, ir_mode *mode)
294 static inline ir_graph *_get_irn_irg(const ir_node *node)
297 * Do not use get_nodes_Block() here, because this
298 * will check the pinned state.
299 * However even a 'wrong' block is always in the proper
302 if (! is_Block(node))
303 node = get_irn_n(node, -1);
304 /* note that get_Block_irg() can handle Bad nodes */
305 return get_Block_irg(node);
309 * Gets the visited counter of a node.
310 * Intern version for libFirm.
312 static inline ir_visited_t _get_irn_visited(const ir_node *node)
315 return node->visited;
319 * Sets the visited counter of a node.
320 * Intern version for libFirm.
322 static inline void _set_irn_visited(ir_node *node, ir_visited_t visited)
325 node->visited = visited;
329 * Mark a node as visited in a graph.
330 * Intern version for libFirm.
332 static inline void _mark_irn_visited(ir_node *node)
334 node->visited = get_irn_irg(node)->visited;
338 * Returns non-zero if a node of was visited.
339 * Intern version for libFirm.
341 static inline int _irn_visited(const ir_node *node)
343 ir_graph *irg = get_irn_irg(node);
344 return node->visited >= irg->visited;
347 static inline int _irn_visited_else_mark(ir_node *node)
349 if (_irn_visited(node))
351 _mark_irn_visited(node);
356 * Sets the link of a node.
357 * Intern version of libFirm.
359 static inline void _set_irn_link(ir_node *node, void *link)
366 * Returns the link of a node.
367 * Intern version of libFirm.
369 static inline void *_get_irn_link(const ir_node *node)
371 assert(node && _is_ir_node(node));
376 * Returns whether the node _always_ must be pinned.
377 * I.e., the node is not floating after global cse.
379 * Intern version of libFirm.
381 static inline op_pin_state _get_irn_pinned(const ir_node *node)
384 assert(node && _is_ir_node(node));
386 state = _get_op_pinned(_get_irn_op(node));
388 if (state >= op_pin_state_exc_pinned)
389 return get_opt_fragile_ops() ? node->attr.except.pin_state : op_pin_state_pinned;
393 static inline op_pin_state _is_irn_pinned_in_irg(const ir_node *node)
395 if (get_irg_pinned(get_irn_irg(node)) == op_pin_state_floats)
396 return get_irn_pinned(node);
397 return op_pin_state_pinned;
400 /* include generated code */
401 #include "gen_irnode.h"
403 static inline int _is_unop(const ir_node *node)
405 assert(node && _is_ir_node(node));
406 return (node->op->opar == oparity_unary);
409 static inline int _is_binop(const ir_node *node)
411 assert(node && _is_ir_node(node));
412 return (node->op->opar == oparity_binary);
415 static inline int _is_Phi(const ir_node *node)
420 op = get_irn_op(node);
421 #ifdef INTERPROCEDURAL_VIEW
422 if (op == op_Filter) return get_interprocedural_view();
424 return (op == op_Phi);
427 static inline int _is_Proj(const ir_node *node)
432 op = _get_irn_op(node);
433 #ifdef INTERPROCEDURAL_VIEW
434 if (op == op_Filter) return !get_interprocedural_view();
436 return (op == op_Proj);
439 static inline int _is_strictConv(const ir_node *node)
441 return _is_Conv(node) && get_Conv_strict(node);
444 static inline int _is_SymConst_addr_ent(const ir_node *node)
446 return is_SymConst(node) && get_SymConst_kind(node) == symconst_addr_ent;
449 static inline int _is_no_Block(const ir_node *node)
451 assert(node && _is_ir_node(node));
452 return (_get_irn_op(node) != op_Block);
455 static inline int _get_Block_n_cfgpreds(const ir_node *node)
457 assert(_is_Block(node));
458 return _get_irn_arity(node);
461 static inline ir_node *_get_Block_cfgpred(const ir_node *node, int pos)
463 assert(0 <= pos && pos < get_irn_arity(node));
464 assert(_is_Block(node));
465 return _get_irn_n(node, pos);
468 /* Get the predecessor block.
470 * Returns the block corresponding to the predecessor pos.
472 * There are several ambiguities we resolve with this function:
473 * - The direct predecessor can be a Proj, which is not pinned.
474 * We walk from the predecessor to the next pinned node
475 * (skip_Proj) and return the block that node is in.
476 * - If we encounter the Bad node, this function does not return
477 * the Start block, but the Bad node.
479 static inline ir_node *_get_Block_cfgpred_block(const ir_node *node, int pos)
481 ir_node *res = skip_Proj(get_Block_cfgpred(node, pos));
483 res = get_nodes_block(res);
487 static inline ir_visited_t _get_Block_block_visited(const ir_node *node)
489 assert(node->op == op_Block);
490 return node->attr.block.block_visited;
493 static inline void _set_Block_block_visited(ir_node *node, ir_visited_t visit)
495 assert(node->op == op_Block);
496 node->attr.block.block_visited = visit;
499 /* For this current_ir_graph must be set. */
500 static inline void _mark_Block_block_visited(ir_node *node)
502 ir_graph *irg = get_Block_irg(node);
503 node->attr.block.block_visited = get_irg_block_visited(irg);
506 static inline int _Block_block_visited(const ir_node *node)
508 ir_graph *irg = get_Block_irg(node);
509 return node->attr.block.block_visited >= get_irg_block_visited(irg);
512 static inline ir_node *_set_Block_dead(ir_node *block)
514 assert(_get_irn_op(block) == op_Block);
515 block->attr.block.dom.dom_depth = -1;
516 block->attr.block.is_dead = 1;
520 static inline int _is_Block_dead(const ir_node *block)
522 ir_op *op = _get_irn_op(block);
527 assert(op == op_Block);
528 return block->attr.block.is_dead;
532 static inline ir_graph *_get_Block_irg(const ir_node *block)
534 assert(is_Block(block) || is_Bad(block));
535 return block->attr.irg.irg;
538 static inline tarval *_get_Const_tarval(const ir_node *node) {
539 assert(_get_irn_op(node) == op_Const);
540 return node->attr.con.tarval;
543 static inline int _is_Const_null(const ir_node *node) {
544 return tarval_is_null(_get_Const_tarval(node));
547 static inline int _is_Const_one(const ir_node *node) {
548 return tarval_is_one(_get_Const_tarval(node));
551 static inline int _is_Const_all_one(const ir_node *node) {
552 return tarval_is_all_one(_get_Const_tarval(node));
555 static inline int _is_irn_forking(const ir_node *node) {
556 return is_op_forking(_get_irn_op(node));
559 static inline ir_type *_get_irn_type(ir_node *node) {
560 return _get_irn_op(node)->ops.get_type(node);
563 static inline ir_type *_get_irn_type_attr(ir_node *node) {
564 return _get_irn_op(node)->ops.get_type_attr(node);
567 static inline ir_entity *_get_irn_entity_attr(ir_node *node) {
568 return _get_irn_op(node)->ops.get_entity_attr(node);
571 static inline int _is_irn_constlike(const ir_node *node) {
572 return is_op_constlike(_get_irn_op(node));
575 static inline int _is_irn_always_opt(const ir_node *node) {
576 return is_op_always_opt(_get_irn_op(node));
579 static inline int _is_irn_keep(const ir_node *node) {
580 return is_op_keep(_get_irn_op(node));
583 static inline int _is_irn_start_block_placed(const ir_node *node) {
584 return is_op_start_block_placed(_get_irn_op(node));
587 static inline int _is_irn_machine_op(const ir_node *node) {
588 return is_op_machine(_get_irn_op(node));
591 static inline int _is_irn_machine_operand(const ir_node *node) {
592 return is_op_machine_operand(_get_irn_op(node));
595 static inline int _is_irn_machine_user(const ir_node *node, unsigned n) {
596 return is_op_machine_user(_get_irn_op(node), n);
599 static inline int _is_irn_cse_neutral(const ir_node *node) {
600 return is_op_cse_neutral(_get_irn_op(node));
603 static inline cond_jmp_predicate _get_Cond_jmp_pred(const ir_node *node) {
604 assert(_get_irn_op(node) == op_Cond);
605 return node->attr.cond.jmp_pred;
608 static inline void _set_Cond_jmp_pred(ir_node *node, cond_jmp_predicate pred) {
609 assert(_get_irn_op(node) == op_Cond);
610 node->attr.cond.jmp_pred = pred;
613 static inline void *_get_irn_generic_attr(ir_node *node) {
617 static inline const void *_get_irn_generic_attr_const(const ir_node *node) {
621 static inline unsigned _get_irn_idx(const ir_node *node) {
622 return node->node_idx;
625 static inline dbg_info *_get_irn_dbg_info(const ir_node *n) {
627 } /* get_irn_dbg_info */
629 static inline void _set_irn_dbg_info(ir_node *n, dbg_info *db) {
634 * Sets the Phi list of a block.
636 static inline void _set_Block_phis(ir_node *block, ir_node *phi)
638 assert(_is_Block(block));
639 assert(phi == NULL || _is_Phi(phi));
640 block->attr.block.phis = phi;
644 * Returns the link of a node.
645 * Intern version of libFirm.
647 static inline ir_node *_get_Block_phis(const ir_node *block)
649 assert(_is_Block(block));
650 return block->attr.block.phis;
653 static inline void _set_Phi_next(ir_node *phi, ir_node *next)
655 assert(_is_Phi(phi));
656 phi->attr.phi.next = next;
659 static inline ir_node *_get_Phi_next(const ir_node *phi)
661 assert(_is_Phi(phi));
662 return phi->attr.phi.next;
665 /** Add a Phi node to the list of Block Phi's. */
666 static inline void _add_Block_phi(ir_node *block, ir_node *phi)
668 _set_Phi_next(phi, _get_Block_phis(block));
669 _set_Block_phis(block, phi);
672 /** Get the Block mark (single bit). */
673 static inline unsigned _get_Block_mark(const ir_node *block)
675 assert(_is_Block(block));
676 return block->attr.block.marked;
679 /** Set the Block mark (single bit). */
680 static inline void _set_Block_mark(ir_node *block, unsigned mark)
682 assert(_is_Block(block));
683 block->attr.block.marked = mark;
686 /** Returns non-zero if a node is a routine parameter. */
687 static inline int _is_arg_Proj(const ir_node *node)
691 node = get_Proj_pred(node);
694 return pn_Start_T_args == get_Proj_proj(node) && is_Start(get_Proj_pred(node));
697 /** initialize ir_node module */
698 void init_irnode(void);
700 /* this section MUST contain all inline functions */
701 #define is_ir_node(thing) _is_ir_node(thing)
702 #define get_irn_intra_arity(node) _get_irn_intra_arity(node)
703 #define get_irn_inter_arity(node) _get_irn_inter_arity(node)
704 #define get_irn_arity(node) _get_irn_arity(node)
705 #define get_irn_intra_n(node, n) _get_irn_intra_n(node, n)
706 #define get_irn_inter_n(node, n) _get_irn_inter_n(node, n)
707 #define get_irn_n(node, n) _get_irn_n(node, n)
708 #define get_irn_mode(node) _get_irn_mode(node)
709 #define set_irn_mode(node, mode) _set_irn_mode(node, mode)
710 #define get_irn_irg(node) _get_irn_irg(node)
711 #define get_irn_op(node) _get_irn_op(node)
712 #define set_irn_op(node, op) _set_irn_op(node, op)
713 #define get_irn_opcode(node) _get_irn_opcode(node)
714 #define get_irn_visited(node) _get_irn_visited(node)
715 #define set_irn_visited(node, v) _set_irn_visited(node, v)
716 #define mark_irn_visited(node) _mark_irn_visited(node)
717 #define irn_visited(node) _irn_visited(node)
718 #define irn_visited_else_mark(node) _irn_visited_else_mark(node)
719 #define set_irn_link(node, link) _set_irn_link(node, link)
720 #define get_irn_link(node) _get_irn_link(node)
721 #define get_irn_pinned(node) _get_irn_pinned(node)
722 #define is_irn_pinned_in_irg(node) _is_irn_pinned_in_irg(node)
723 #define is_unop(node) _is_unop(node)
724 #define is_binop(node) _is_binop(node)
725 #define is_Proj(node) _is_Proj(node)
726 #define is_Phi(node) _is_Phi(node)
727 #define is_strictConv(node) _is_strictConv(node)
728 #define is_SymConst_addr_ent(node) _is_SymConst_addr_ent(node)
729 #define is_no_Block(node) _is_no_Block(node)
730 #define get_Block_n_cfgpreds(node) _get_Block_n_cfgpreds(node)
731 #define get_Block_cfgpred(node, pos) _get_Block_cfgpred(node, pos)
732 #define get_Block_cfgpred_block(node, pos) _get_Block_cfgpred_block(node, pos)
733 #define get_Block_block_visited(node) _get_Block_block_visited(node)
734 #define set_Block_block_visited(node, visit) _set_Block_block_visited(node, visit)
735 #define mark_Block_block_visited(node) _mark_Block_block_visited(node)
736 #define Block_block_visited(node) _Block_block_visited(node)
737 #define set_Block_dead(block) _set_Block_dead(block)
738 #define is_Block_dead(block) _is_Block_dead(block)
739 #define get_Block_irg(block) _get_Block_irg(block)
740 #define get_Const_tarval(node) _get_Const_tarval(node)
741 #define is_Const_null(node) _is_Const_null(node)
742 #define is_Const_one(node) _is_Const_one(node)
743 #define is_Const_all_one(node) _is_Const_all_one(node)
744 #define is_irn_forking(node) _is_irn_forking(node)
745 #define copy_node_attr(irg,oldn,newn) _copy_node_attr(irg,oldn,newn)
746 #define get_irn_type(node) _get_irn_type(node)
747 #define get_irn_type_attr(node) _get_irn_type_attr(node)
748 #define get_irn_entity_attr(node) _get_irn_entity_attr(node)
749 #define is_irn_constlike(node) _is_irn_constlike(node)
750 #define is_irn_always_opt(node) _is_irn_always_opt(node)
751 #define is_irn_keep(node) _is_irn_keep(node)
752 #define is_irn_start_block_placed(node) _is_irn_start_block_placed(node)
753 #define is_irn_machine_op(node) _is_irn_machine_op(node)
754 #define is_irn_machine_operand(node) _is_irn_machine_operand(node)
755 #define is_irn_machine_user(node, n) _is_irn_machine_user(node, n)
756 #define is_irn_cse_neutral(node) _is_irn_cse_neutral(node)
757 #define get_Cond_jmp_pred(node) _get_Cond_jmp_pred(node)
758 #define set_Cond_jmp_pred(node, pred) _set_Cond_jmp_pred(node, pred)
759 #define get_irn_generic_attr(node) _get_irn_generic_attr(node)
760 #define get_irn_generic_attr_const(node) _get_irn_generic_attr_const(node)
761 #define get_irn_idx(node) _get_irn_idx(node)
763 #define get_irn_deps(node) _get_irn_deps(node)
764 #define set_irn_dep(node, pos, dep) _set_irn_dep(node, pos, dep)
765 #define get_irn_dep(node, pos) _get_irn_dep(node, pos)
767 #define get_irn_ins_or_deps(node) _get_irn_ins_or_deps(node)
768 #define get_irn_in_or_dep(node, pos) _get_irn_in_or_dep(node, pos)
770 #define get_irn_dbg_info(node) _get_irn_dbg_info(node)
771 #define set_irn_dbg_info(node, db) _set_irn_dbg_info(node, db)
773 #define set_Block_phis(block, phi) _set_Block_phis(block, phi)
774 #define get_Block_phis(block) _get_Block_phis(block)
775 #define add_Block_phi(block, phi) _add_Block_phi(block, phi)
776 #define get_Block_mark(block) _get_Block_mark(block)
777 #define set_Block_mark(block, mark) _set_Block_mark(block, mark)
779 #define set_Phi_next(node, phi) _set_Phi_next(node, phi)
780 #define get_Phi_next(node) _get_Phi_next(node)
782 #define is_arg_Proj(node) _is_arg_Proj(node)