1 from spec_util import abstract, setnodedefaults
4 """Base class for firm nodes"""
8 """Unary nodes have exactly 1 input"""
16 """Binary nodes have exactly 2 inputs"""
18 ins = [ "left", "right" ]
24 """returns the sum of its operands"""
25 flags = ["commutative"]
28 """allocates a block of memory.
29 It can be specified whether the variable should be allocated to the stack
31 ins = [ "mem", "count" ]
33 ("M", "memory result", "pn_Generic_M"),
34 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
35 ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
36 ("res", "pointer to newly allocated memory", "pn_Generic_other"),
38 flags = [ "fragile", "uses_memory" ]
46 type = "ir_where_alloc"
50 attr_struct = "alloc_attr"
53 """utiliy node used to "hold" nodes in a graph that might possibly not be
54 reachable by other means or which should be reachable immediately without
55 searching through the graph.
56 Each firm-graph contains exactly one anchor node whose address is always
57 known. All other well-known graph-nodes like Start, End, NoMem, Bad, ...
58 are found by looking at the respective Anchor operand."""
61 flags = [ "dump_noblock" ]
63 attr_struct = "irg_attr"
67 customSerializer = True
70 """returns the result of a bitwise and operation of its operands"""
71 flags = [ "commutative" ]
74 """executes assembler fragments of the target machine"""
77 flags = [ "keep", "uses_memory" ]
79 pinned_init = "op_pin_state_pinned"
80 attr_struct = "asm_attr"
82 customSerializer = True
85 """Bad nodes indicate invalid input, which is values which should never be
88 The typical use case for the Bad node is removing unreachable code.
89 Frontends should set the current_block to Bad when it is clear that
90 following code must be unreachable (ie. after a goto or return statement).
91 Optimisations also set block predecessors to Bad when it becomes clear,
92 that a control flow edge can never be executed.
94 The gigo optimisations ensures that nodes with Bad as their block, get
95 replaced by Bad themselfes. Nodes with at least 1 Bad input get exchanged
96 with Bad too. Exception to this rule are Block, Phi, Tuple and End node;
97 This is because removing inputs from a Block is hairy operation (requiring,
98 Phis to be shortened too for example). So instead of removing block inputs
99 they are set to Bad, and the actual removal is left to the control flow
100 optimisation phase. Block, Phi, Tuple with only Bad inputs however are
101 replaced by Bad right away."""
103 flags = [ "cfopcode", "start_block", "dump_noblock" ]
106 block = "get_irg_start_block(irg)"
108 attr_struct = "bad_attr"
110 res->attr.bad.irg.irg = irg;
114 """Internal node which is temporary set to nodes which are already removed
120 customSerializer = True
129 flags = [ "labeled" ]
130 attr_struct = "block_attr"
131 customSerializer = True
134 res->attr.block.irg.irg = irg;
135 res->attr.block.backedge = new_backedge_arr(irg->obst, arity);
136 set_Block_matured(res, 1);
138 /* Create and initialize array for Phi-node construction. */
139 if (get_irg_phase_state(irg) == phase_building) {
140 res->attr.block.graph_arr = NEW_ARR_D(ir_node *, irg->obst, irg->n_loc);
141 memset(res->attr.block.graph_arr, 0, irg->n_loc * sizeof(ir_node*));
146 """Returns the borrow bit from and implied subtractions of its 2 operands"""
150 """Performs a bounds-check: if lower <= index < upper then return index,
151 otherwise throw an exception."""
152 ins = [ "mem", "index", "lower", "upper" ]
154 ("M", "memory result", "pn_Generic_M"),
155 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
156 ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
157 ("res", "the checked index", "pn_Generic_other"),
159 flags = [ "fragile", "highlevel" ]
161 pinned_init = "op_pin_state_pinned"
162 attr_struct = "bound_attr"
166 """performs a backend-specific builtin."""
170 ("M", "memory result", "pn_Generic_M"),
171 ("1_result", "first result", "pn_Generic_other"),
173 flags = [ "uses_memory" ]
176 type = "ir_builtin_kind",
185 pinned_init = "op_pin_state_pinned"
186 attr_struct = "builtin_attr"
188 assert((get_unknown_type() == type) || is_Method_type(type));
192 """Calls other code. Control flow is transfered to ptr, additional
193 operands are passed to the called code. Called code usually performs a
194 return operation. The operands of this return operation are the result
196 ins = [ "mem", "ptr" ]
199 ("M", "memory result", "pn_Generic_M"),
200 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
201 ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
202 ("T_result", "tuple containing all results", "pn_Generic_other"),
203 ("P_value_res_base", "pointer to memory register containing copied results passed by value"),
205 flags = [ "fragile", "uses_memory" ]
214 # the tail call attribute can only be set by analysis
218 attr_struct = "call_attr"
220 pinned_init = "op_pin_state_pinned"
222 assert((get_unknown_type() == type) || is_Method_type(type));
226 """Computes the value of the carry-bit that would result when adding the 2
228 flags = [ "commutative" ]
231 """perform a high-level type cast"""
232 mode = "get_irn_mode(irn_op)"
233 flags = [ "highlevel" ]
240 attr_struct = "cast_attr"
241 init = "assert(is_atomic_type(type));"
244 """Returns the relation of 2 operands"""
246 ("False", "always false", "0"),
247 ("Eq", "equal", "1"),
249 ("Le", "less or equal", "pn_Cmp_Eq|pn_Cmp_Lt"),
250 ("Gt", "greater", "4"),
251 ("Ge", "greater or equal", "pn_Cmp_Eq|pn_Cmp_Gt"),
252 ("Lg", "less or greater ('not equal' for integer numbers)", "pn_Cmp_Lt|pn_Cmp_Gt"),
253 ("Leg", "less, equal or greater ('not unordered')", "pn_Cmp_Lt|pn_Cmp_Eq|pn_Cmp_Gt"),
254 ("Uo", "unordered", "8"),
255 ("Ue", "unordered or equal", "pn_Cmp_Uo|pn_Cmp_Eq"),
256 ("Ul", "unordered or less", "pn_Cmp_Uo|pn_Cmp_Lt"),
257 ("Ule", "unordered, less or equal", "pn_Cmp_Uo|pn_Cmp_Lt|pn_Cmp_Eq"),
258 ("Ug", "unordered or greater", "pn_Cmp_Uo|pn_Cmp_Gt"),
259 ("Uge", "onordered, greater or equal", "pn_Cmp_Uo|pn_Cmp_Gt|pn_Cmp_Eq"),
260 ("Ne", "unordered, less or greater ('not equal' for floatingpoint numbers)", "pn_Cmp_Uo|pn_Cmp_Lt|pn_Cmp_Gt"),
261 ("True", "always true", "15"),
266 """Conditionally change control flow. There are two versions of this node:
269 Input: A value of mode_b
270 Output: A tuple of two control flows. The first is taken if the input is
271 false, the second if it is true.
274 Input: A value of mode_Iu
275 Output: A tuple of n control flows. If the Cond's input is i, control flow
276 will proceed along output i. If the input is >= n control flow proceeds
277 along output def_proj.
281 ("false", "control flow if operand is \"false\""),
282 ("true", "control flow if operand is \"true\""),
284 flags = [ "cfopcode", "forking" ]
288 name = "default_proj",
294 type = "cond_jmp_predicate",
295 init = "COND_JMP_PRED_NONE"
298 attr_struct = "cond_attr"
301 """Specifies constraints for a value. This allows explicit representation
302 of path-sensitive properties. (Example: This value is always >= 0 on 1
303 if-branch then all users within that branch are rerouted to a confirm-node
304 specifying this property).
306 A constraint is specified for the relation between value and bound.
307 value is always returned.
308 Note that this node does NOT check or assert the constraint, it merely
310 ins = [ "value", "bound" ]
311 mode = "get_irn_mode(irn_value)"
312 flags = [ "highlevel" ]
320 attr_struct = "confirm_attr"
321 attrs_name = "confirm"
324 """Returns a constant value."""
326 flags = [ "constlike", "start_block" ]
336 attr_struct = "const_attr"
339 """Converts values between modes"""
348 attr_struct = "conv_attr"
352 """Copies a block of memory"""
353 ins = [ "mem", "dst", "src" ]
355 ("M", "memory result", "pn_Generic_M"),
356 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
357 ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
359 flags = [ "fragile", "uses_memory" ]
366 attr_struct = "copyb_attr"
369 pinned_init = "op_pin_state_pinned"
372 """returns the quotient of its 2 operands, integer version"""
373 ins = [ "mem", "left", "right" ]
375 ("M", "memory result", "pn_Generic_M"),
376 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
377 ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
378 ("res", "result of computation", "pn_Generic_other"),
380 flags = [ "fragile", "uses_memory" ]
381 attrs_name = "divmod"
388 name = "no_remainder",
393 attr_struct = "divmod_attr"
396 arity_override = "oparity_binary"
399 """divides its 2 operands and computes the remainder of the division"""
400 ins = [ "mem", "left", "right" ]
402 ("M", "memory result", "pn_Generic_M"),
403 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
404 ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
405 ("res_div", "result of computation a/b", "pn_Generic_other"),
406 ("res_mod", "result of computation a%b"),
408 flags = [ "fragile", "uses_memory" ]
409 attrs_name = "divmod"
416 attr_struct = "divmod_attr"
419 arity_override = "oparity_binary"
422 """A placeholder value. This is used when constructing cyclic graphs where
423 you have cases where not all predecessors of a phi-node are known. Dummy
424 nodes are used for the unknown predecessors and replaced later."""
426 flags = [ "cfopcode", "start_block", "constlike", "dump_noblock" ]
429 block = "get_irg_start_block(irg)"
432 """Last node of a graph. It references nodes in endless loops (so called
437 flags = [ "cfopcode" ]
439 block = "get_irg_end_block(irg)"
441 customSerializer = True
444 """returns the result of a bitwise exclusive or operation of its operands"""
445 flags = [ "commutative" ]
448 """Frees a block of memory previously allocated by an Alloc node"""
449 ins = [ "mem", "ptr", "size" ]
451 flags = [ "uses_memory" ]
460 type = "ir_where_alloc"
463 attr_struct = "free_attr"
466 """Returns its operand unchanged."""
472 """Jumps to the code in its argument. The code has to be in the same
473 function and the the destination must be one of the blocks reachable
474 by the tuple results"""
478 flags = [ "cfopcode", "forking", "keep" ]
481 """Tests wether an object is an instance of a class-type"""
482 ins = [ "store", "obj" ]
484 ("M", "memory result", "pn_Generic_M"),
485 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
486 ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
487 ("res", "checked object pointer", "pn_Generic_other"),
489 flags = [ "highlevel" ]
496 attr_struct = "io_attr"
498 pinned_init = "op_pin_state_floats"
501 """Jumps to the block connected through the out-value"""
505 flags = [ "cfopcode" ]
508 """Loads a value from memory (heap or stack)."""
509 ins = [ "mem", "ptr" ]
511 ("M", "memory result", "pn_Generic_M"),
512 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
513 ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
514 ("res", "result of load operation", "pn_Generic_other"),
516 flags = [ "fragile", "uses_memory" ]
518 pinned_init = "flags & cons_floats ? op_pin_state_floats : op_pin_state_pinned"
523 java_name = "load_mode"
526 attr_struct = "load_attr"
529 type = "ir_cons_flags",
534 res->attr.load.volatility = flags & cons_volatile ? volatility_is_volatile : volatility_non_volatile;
535 res->attr.load.aligned = flags & cons_unaligned ? align_non_aligned : align_is_aligned;
539 """returns the difference between its operands"""
543 """returns the remainder of its operands from an implied division.
546 * mod(5,3) produces 2
547 * mod(5,-3) produces 2
548 * mod(-5,3) produces -2
549 * mod(-5,-3) produces -2
551 ins = [ "mem", "left", "right" ]
553 ("M", "memory result", "pn_Generic_M"),
554 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
555 ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
556 ("res", "result of computation", "pn_Generic_other"),
558 flags = [ "fragile", "uses_memory" ]
559 attrs_name = "divmod"
566 attr_struct = "divmod_attr"
569 arity_override = "oparity_binary"
572 """returns the product of its operands"""
573 flags = [ "commutative" ]
576 """returns the upper word of the product of its operands (the part which
577 would not fit into the result mode of a normal Mul anymore)"""
578 flags = [ "commutative" ]
581 """returns the false or true operand depending on the value of the sel
583 ins = [ "sel", "false", "true" ]
588 """Placeholder node for cases where you don't need any memory input"""
590 flags = [ "dump_noblock", "dump_noinput" ]
593 block = "get_irg_start_block(irg)"
597 """returns the logical complement of a value. Works for integer values too.
598 If the input is false/zero then true/one is returned, otherwise false/zero
603 """returns the result of a bitwise or operation of its operands"""
604 flags = [ "commutative" ]
607 """Choose a value based on control flow. A phi node has 1 input for each
608 predecessor of its block. If a block is entered from its nth predecessor
609 all phi nodes produce their nth input as result."""
613 attr_struct = "phi_attr"
615 /* Memory Phis in endless loops must be kept alive.
616 As we can't distinguish these easily we keep all of them alive. */
617 if (is_Phi(res) && mode == mode_M)
618 add_End_keepalive(get_irg_end(irg), res);
622 """Pin the value of the node node in the current block. No users of the Pin
623 node can float above the Block of the Pin. The node cannot float behind
624 this block. Often used to Pin the NoMem node."""
626 mode = "get_irn_mode(irn_op)"
627 flags = [ "highlevel" ]
631 """returns an entry of a tuple value"""
637 block = "get_nodes_block(irn_pred)"
638 graph = "get_irn_irg(irn_pred)"
639 customSerializer = True
646 attr_struct = "proj_attr"
649 """returns the quotient of its 2 operands, floatingpoint version"""
650 ins = [ "mem", "left", "right" ]
652 ("M", "memory result", "pn_Generic_M"),
653 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
654 ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
655 ("res", "result of computation", "pn_Generic_other"),
657 flags = [ "fragile", "uses_memory" ]
658 attrs_name = "divmod"
665 attr_struct = "divmod_attr"
668 arity_override = "oparity_binary"
671 """Raises an exception. Unconditional change of control flow. Writes an
672 explicit Except variable to memory to pass it to the exception handler.
673 Must be lowered to a Call to a runtime check function."""
674 ins = [ "mem", "exo_ptr" ]
676 ("M", "memory result", "pn_Generic_M"),
677 ("X", "control flow to exception handler", "pn_Generic_X_regular"),
679 flags = [ "highlevel", "cfopcode" ]
683 """Returns from the current function. Takes memory and return values as
688 flags = [ "cfopcode" ]
692 """Returns its first operand bits rotated left by the amount in the 2nd
697 """Computes the address of a entity of a compound type given the base
698 address of an instance of the compound type."""
699 ins = [ "mem", "ptr" ]
702 mode = "is_Method_type(get_entity_type(entity)) ? mode_P_code : mode_P_data"
710 attr_struct = "sel_attr"
713 """Returns its first operands bits shifted left by the amount of the 2nd
718 """Returns its first operands bits shifted right by the amount of the 2nd
719 operand. No special handling for the sign bit (zero extension)"""
723 """Returns its first operands bits shifted right by the amount of the 2nd
724 operand. The leftmost bit (usually the sign bit) stays the same
729 """The first node of a graph. Execution starts with this node."""
731 ("X_initial_exec", "control flow"),
732 ("M", "initial memory"),
733 ("P_frame_base", "frame base pointer"),
734 ("P_tls", "pointer to thread local storage segment"),
735 ("T_args", "function arguments")
739 flags = [ "cfopcode" ]
742 customSerializer = True
743 block = "get_irg_start_block(irg)"
746 """Stores a value into memory (heap or stack)."""
747 ins = [ "mem", "ptr", "value" ]
749 ("M", "memory result", "pn_Generic_M"),
750 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
751 ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
753 flags = [ "fragile", "uses_memory" ]
755 attr_struct = "store_attr"
756 pinned_init = "flags & cons_floats ? op_pin_state_floats : op_pin_state_pinned"
759 type = "ir_cons_flags",
764 res->attr.store.volatility = flags & cons_volatile ? volatility_is_volatile : volatility_non_volatile;
765 res->attr.store.aligned = flags & cons_unaligned ? align_non_aligned : align_is_aligned;
769 """returns the difference of its operands"""
773 """A symbolic constant.
775 - symconst_type_tag The symbolic constant represents a type tag. The
776 type the tag stands for is given explicitly.
777 - symconst_type_size The symbolic constant represents the size of a type.
778 The type of which the constant represents the size
780 - symconst_type_align The symbolic constant represents the alignment of a
781 type. The type of which the constant represents the
782 size is given explicitly.
783 - symconst_addr_ent The symbolic constant represents the address of an
784 entity (variable or method). The variable is given
785 explicitly by a firm entity.
786 - symconst_ofs_ent The symbolic constant represents the offset of an
787 entity in its owner type.
788 - symconst_enum_const The symbolic constant is a enumeration constant of
789 an enumeration type."""
791 flags = [ "constlike", "start_block" ]
801 attr_struct = "symconst_attr"
802 customSerializer = True
805 """The Sync operation unifies several partial memory blocks. These blocks
806 have to be pairwise disjunct or the values in common locations have to
807 be identical. This operation allows to specify all operations that
808 eventually need several partial memory blocks as input with a single
809 entrance by unifying the memories with a preceding Sync operation."""
816 """Builds a Tuple from single values.
818 This is needed to implement optimizations that remove a node that produced
819 a tuple. The node can be replaced by the Tuple operation so that the
820 following Proj nodes have not to be changed. (They are hard to find due to
821 the implementation with pointers in only one direction.) The Tuple node is
822 smaller than any other node, so that a node can be changed into a Tuple by
823 just changing it's opcode and giving it a new in array."""
827 flags = [ "labeled" ]
830 """Returns an unknown (at compile- and runtime) value. It is a valid
831 optimisation to replace an Unknown by any other constant value."""
834 block = "get_irg_start_block(irg)"
835 flags = [ "cfopcode", "start_block", "constlike", "dump_noblock" ]
839 def getOpList(namespace):
841 for t in namespace.values():
845 if issubclass(t, Op):
850 nodes = getOpList(globals())
851 nodes = sorted(nodes, lambda x,y: cmp(x.name, y.name))