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"""
352 attr_struct = "conv_attr"
356 """Copies a block of memory"""
357 ins = [ "mem", "dst", "src" ]
359 ("M", "memory result", "pn_Generic_M"),
360 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
361 ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
363 flags = [ "fragile", "uses_memory" ]
370 attr_struct = "copyb_attr"
373 pinned_init = "op_pin_state_pinned"
376 """returns the quotient of its 2 operands, integer version"""
377 ins = [ "mem", "left", "right" ]
379 ("M", "memory result", "pn_Generic_M"),
380 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
381 ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
382 ("res", "result of computation", "pn_Generic_other"),
384 flags = [ "fragile", "uses_memory" ]
385 attrs_name = "divmod"
392 name = "no_remainder",
401 attr_struct = "divmod_attr"
404 arity_override = "oparity_binary"
407 """divides its 2 operands and computes the remainder of the division"""
408 ins = [ "mem", "left", "right" ]
410 ("M", "memory result", "pn_Generic_M"),
411 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
412 ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
413 ("res_div", "result of computation a/b", "pn_Generic_other"),
414 ("res_mod", "result of computation a%b"),
416 flags = [ "fragile", "uses_memory" ]
417 attrs_name = "divmod"
424 attr_struct = "divmod_attr"
427 arity_override = "oparity_binary"
430 """A placeholder value. This is used when constructing cyclic graphs where
431 you have cases where not all predecessors of a phi-node are known. Dummy
432 nodes are used for the unknown predecessors and replaced later."""
434 flags = [ "cfopcode", "start_block", "constlike", "dump_noblock" ]
437 block = "get_irg_start_block(irg)"
440 """Last node of a graph. It references nodes in endless loops (so called
445 flags = [ "cfopcode" ]
447 block = "get_irg_end_block(irg)"
449 customSerializer = True
452 """returns the result of a bitwise exclusive or operation of its operands"""
453 flags = [ "commutative" ]
456 """Frees a block of memory previously allocated by an Alloc node"""
457 ins = [ "mem", "ptr", "size" ]
459 flags = [ "uses_memory" ]
468 type = "ir_where_alloc"
471 attr_struct = "free_attr"
474 """Returns its operand unchanged."""
480 """Jumps to the code in its argument. The code has to be in the same
481 function and the the destination must be one of the blocks reachable
482 by the tuple results"""
486 flags = [ "cfopcode", "forking", "keep" ]
489 """Tests wether an object is an instance of a class-type"""
490 ins = [ "store", "obj" ]
492 ("M", "memory result", "pn_Generic_M"),
493 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
494 ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
495 ("res", "checked object pointer", "pn_Generic_other"),
497 flags = [ "highlevel" ]
504 attr_struct = "io_attr"
506 pinned_init = "op_pin_state_floats"
509 """Jumps to the block connected through the out-value"""
513 flags = [ "cfopcode" ]
516 """Loads a value from memory (heap or stack)."""
517 ins = [ "mem", "ptr" ]
519 ("M", "memory result", "pn_Generic_M"),
520 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
521 ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
522 ("res", "result of load operation", "pn_Generic_other"),
524 flags = [ "fragile", "uses_memory" ]
526 pinned_init = "flags & cons_floats ? op_pin_state_floats : op_pin_state_pinned"
531 java_name = "load_mode"
534 attr_struct = "load_attr"
537 type = "ir_cons_flags",
543 """returns the difference between its operands"""
547 """returns the remainder of its operands from an implied division.
550 * mod(5,3) produces 2
551 * mod(5,-3) produces 2
552 * mod(-5,3) produces -2
553 * mod(-5,-3) produces -2
555 ins = [ "mem", "left", "right" ]
557 ("M", "memory result", "pn_Generic_M"),
558 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
559 ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
560 ("res", "result of computation", "pn_Generic_other"),
562 flags = [ "fragile", "uses_memory" ]
563 attrs_name = "divmod"
570 attr_struct = "divmod_attr"
573 arity_override = "oparity_binary"
576 """returns the product of its operands"""
577 flags = [ "commutative" ]
580 """returns the upper word of the product of its operands (the part which
581 would not fit into the result mode of a normal Mul anymore)"""
582 flags = [ "commutative" ]
585 """returns the false or true operand depending on the value of the sel
587 ins = [ "sel", "false", "true" ]
592 """Placeholder node for cases where you don't need any memory input"""
594 flags = [ "dump_noblock", "dump_noinput" ]
597 block = "get_irg_start_block(irg)"
601 """returns the logical complement of a value. Works for integer values too.
602 If the input is false/zero then true/one is returned, otherwise false/zero
607 """returns the result of a bitwise or operation of its operands"""
608 flags = [ "commutative" ]
611 """Choose a value based on control flow. A phi node has 1 input for each
612 predecessor of its block. If a block is entered from its nth predecessor
613 all phi nodes produce their nth input as result."""
617 attr_struct = "phi_attr"
619 /* Memory Phis in endless loops must be kept alive.
620 As we can't distinguish these easily we keep all of them alive. */
621 if (is_Phi(res) && mode == mode_M)
622 add_End_keepalive(get_irg_end(irg), res);
626 """Pin the value of the node node in the current block. No users of the Pin
627 node can float above the Block of the Pin. The node cannot float behind
628 this block. Often used to Pin the NoMem node."""
630 mode = "get_irn_mode(irn_op)"
631 flags = [ "highlevel" ]
635 """returns an entry of a tuple value"""
641 block = "get_nodes_block(irn_pred)"
642 graph = "get_irn_irg(irn_pred)"
643 customSerializer = True
655 """returns the quotient of its 2 operands, floatingpoint version"""
656 ins = [ "mem", "left", "right" ]
658 ("M", "memory result", "pn_Generic_M"),
659 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
660 ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
661 ("res", "result of computation", "pn_Generic_other"),
663 flags = [ "fragile", "uses_memory" ]
664 attrs_name = "divmod"
671 attr_struct = "divmod_attr"
674 arity_override = "oparity_binary"
677 """Raises an exception. Unconditional change of control flow. Writes an
678 explicit Except variable to memory to pass it to the exception handler.
679 Must be lowered to a Call to a runtime check function."""
680 ins = [ "mem", "exo_ptr" ]
682 ("M", "memory result", "pn_Generic_M"),
683 ("X", "control flow to exception handler", "pn_Generic_X_regular"),
685 flags = [ "highlevel", "cfopcode" ]
689 """Returns from the current function. Takes memory and return values as
694 flags = [ "cfopcode" ]
698 """Returns its first operand bits rotated left by the amount in the 2nd
703 """Computes the address of a entity of a compound type given the base
704 address of an instance of the compound type."""
705 ins = [ "mem", "ptr" ]
708 mode = "is_Method_type(get_entity_type(entity)) ? mode_P_code : mode_P_data"
716 attr_struct = "sel_attr"
719 """Returns its first operands bits shifted left by the amount of the 2nd
724 """Returns its first operands bits shifted right by the amount of the 2nd
725 operand. No special handling for the sign bit (zero extension)"""
729 """Returns its first operands bits shifted right by the amount of the 2nd
730 operand. The leftmost bit (usually the sign bit) stays the same
735 """The first node of a graph. Execution starts with this node."""
737 ("X_initial_exec", "control flow"),
738 ("M", "initial memory"),
739 ("P_frame_base", "frame base pointer"),
740 ("P_tls", "pointer to thread local storage segment"),
741 ("T_args", "function arguments")
745 flags = [ "cfopcode" ]
748 customSerializer = True
749 block = "get_irg_start_block(irg)"
752 """Stores a value into memory (heap or stack)."""
753 ins = [ "mem", "ptr", "value" ]
755 ("M", "memory result", "pn_Generic_M"),
756 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
757 ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
759 flags = [ "fragile", "uses_memory" ]
761 attr_struct = "store_attr"
762 pinned_init = "flags & cons_floats ? op_pin_state_floats : op_pin_state_pinned"
765 type = "ir_cons_flags",
771 """returns the difference of its operands"""
775 """A symbolic constant.
777 - symconst_type_tag The symbolic constant represents a type tag. The
778 type the tag stands for is given explicitly.
779 - symconst_type_size The symbolic constant represents the size of a type.
780 The type of which the constant represents the size
782 - symconst_type_align The symbolic constant represents the alignment of a
783 type. The type of which the constant represents the
784 size is given explicitly.
785 - symconst_addr_ent The symbolic constant represents the address of an
786 entity (variable or method). The variable is given
787 explicitly by a firm entity.
788 - symconst_ofs_ent The symbolic constant represents the offset of an
789 entity in its owner type.
790 - symconst_enum_const The symbolic constant is a enumeration constant of
791 an enumeration type."""
793 flags = [ "constlike", "start_block" ]
803 attr_struct = "symconst_attr"
804 customSerializer = True
807 """The Sync operation unifies several partial memory blocks. These blocks
808 have to be pairwise disjunct or the values in common locations have to
809 be identical. This operation allows to specify all operations that
810 eventually need several partial memory blocks as input with a single
811 entrance by unifying the memories with a preceding Sync operation."""
818 """Builds a Tuple from single values.
820 This is needed to implement optimizations that remove a node that produced
821 a tuple. The node can be replaced by the Tuple operation so that the
822 following Proj nodes have not to be changed. (They are hard to find due to
823 the implementation with pointers in only one direction.) The Tuple node is
824 smaller than any other node, so that a node can be changed into a Tuple by
825 just changing it's opcode and giving it a new in array."""
829 flags = [ "labeled" ]
832 """Returns an unknown (at compile- and runtime) value. It is a valid
833 optimisation to replace an Unknown by any other constant value."""
836 block = "get_irg_start_block(irg)"
837 flags = [ "cfopcode", "start_block", "constlike", "dump_noblock" ]
841 def getOpList(namespace):
843 for t in namespace.values():
847 if issubclass(t, Op):
852 nodes = getOpList(globals())
853 nodes = sorted(nodes, lambda x,y: cmp(x.name, y.name))