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",
535 """returns the difference between its operands"""
539 """returns the remainder of its operands from an implied division.
542 * mod(5,3) produces 2
543 * mod(5,-3) produces 2
544 * mod(-5,3) produces -2
545 * mod(-5,-3) produces -2
547 ins = [ "mem", "left", "right" ]
549 ("M", "memory result", "pn_Generic_M"),
550 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
551 ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
552 ("res", "result of computation", "pn_Generic_other"),
554 flags = [ "fragile", "uses_memory" ]
555 attrs_name = "divmod"
562 attr_struct = "divmod_attr"
565 arity_override = "oparity_binary"
568 """returns the product of its operands"""
569 flags = [ "commutative" ]
572 """returns the upper word of the product of its operands (the part which
573 would not fit into the result mode of a normal Mul anymore)"""
574 flags = [ "commutative" ]
577 """returns the false or true operand depending on the value of the sel
579 ins = [ "sel", "false", "true" ]
584 """Placeholder node for cases where you don't need any memory input"""
586 flags = [ "dump_noblock", "dump_noinput" ]
589 block = "get_irg_start_block(irg)"
593 """returns the logical complement of a value. Works for integer values too.
594 If the input is false/zero then true/one is returned, otherwise false/zero
599 """returns the result of a bitwise or operation of its operands"""
600 flags = [ "commutative" ]
603 """Choose a value based on control flow. A phi node has 1 input for each
604 predecessor of its block. If a block is entered from its nth predecessor
605 all phi nodes produce their nth input as result."""
609 attr_struct = "phi_attr"
611 /* Memory Phis in endless loops must be kept alive.
612 As we can't distinguish these easily we keep all of them alive. */
613 if (is_Phi(res) && mode == mode_M)
614 add_End_keepalive(get_irg_end(irg), res);
618 """Pin the value of the node node in the current block. No users of the Pin
619 node can float above the Block of the Pin. The node cannot float behind
620 this block. Often used to Pin the NoMem node."""
622 mode = "get_irn_mode(irn_op)"
623 flags = [ "highlevel" ]
627 """returns an entry of a tuple value"""
633 block = "get_nodes_block(irn_pred)"
634 graph = "get_irn_irg(irn_pred)"
635 customSerializer = True
642 attr_struct = "proj_attr"
645 """returns the quotient of its 2 operands, floatingpoint version"""
646 ins = [ "mem", "left", "right" ]
648 ("M", "memory result", "pn_Generic_M"),
649 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
650 ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
651 ("res", "result of computation", "pn_Generic_other"),
653 flags = [ "fragile", "uses_memory" ]
654 attrs_name = "divmod"
661 attr_struct = "divmod_attr"
664 arity_override = "oparity_binary"
667 """Raises an exception. Unconditional change of control flow. Writes an
668 explicit Except variable to memory to pass it to the exception handler.
669 Must be lowered to a Call to a runtime check function."""
670 ins = [ "mem", "exo_ptr" ]
672 ("M", "memory result", "pn_Generic_M"),
673 ("X", "control flow to exception handler", "pn_Generic_X_regular"),
675 flags = [ "highlevel", "cfopcode" ]
679 """Returns from the current function. Takes memory and return values as
684 flags = [ "cfopcode" ]
688 """Returns its first operand bits rotated left by the amount in the 2nd
693 """Computes the address of a entity of a compound type given the base
694 address of an instance of the compound type."""
695 ins = [ "mem", "ptr" ]
698 mode = "is_Method_type(get_entity_type(entity)) ? mode_P_code : mode_P_data"
706 attr_struct = "sel_attr"
709 """Returns its first operands bits shifted left by the amount of the 2nd
714 """Returns its first operands bits shifted right by the amount of the 2nd
715 operand. No special handling for the sign bit (zero extension)"""
719 """Returns its first operands bits shifted right by the amount of the 2nd
720 operand. The leftmost bit (usually the sign bit) stays the same
725 """The first node of a graph. Execution starts with this node."""
727 ("X_initial_exec", "control flow"),
728 ("M", "initial memory"),
729 ("P_frame_base", "frame base pointer"),
730 ("P_tls", "pointer to thread local storage segment"),
731 ("T_args", "function arguments")
735 flags = [ "cfopcode" ]
738 customSerializer = True
739 block = "get_irg_start_block(irg)"
742 """Stores a value into memory (heap or stack)."""
743 ins = [ "mem", "ptr", "value" ]
745 ("M", "memory result", "pn_Generic_M"),
746 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
747 ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
749 flags = [ "fragile", "uses_memory" ]
751 attr_struct = "store_attr"
752 pinned_init = "flags & cons_floats ? op_pin_state_floats : op_pin_state_pinned"
755 type = "ir_cons_flags",
761 """returns the difference of its operands"""
765 """A symbolic constant.
767 - symconst_type_tag The symbolic constant represents a type tag. The
768 type the tag stands for is given explicitly.
769 - symconst_type_size The symbolic constant represents the size of a type.
770 The type of which the constant represents the size
772 - symconst_type_align The symbolic constant represents the alignment of a
773 type. The type of which the constant represents the
774 size is given explicitly.
775 - symconst_addr_ent The symbolic constant represents the address of an
776 entity (variable or method). The variable is given
777 explicitly by a firm entity.
778 - symconst_ofs_ent The symbolic constant represents the offset of an
779 entity in its owner type.
780 - symconst_enum_const The symbolic constant is a enumeration constant of
781 an enumeration type."""
783 flags = [ "constlike", "start_block" ]
793 attr_struct = "symconst_attr"
794 customSerializer = True
797 """The Sync operation unifies several partial memory blocks. These blocks
798 have to be pairwise disjunct or the values in common locations have to
799 be identical. This operation allows to specify all operations that
800 eventually need several partial memory blocks as input with a single
801 entrance by unifying the memories with a preceding Sync operation."""
808 """Builds a Tuple from single values.
810 This is needed to implement optimizations that remove a node that produced
811 a tuple. The node can be replaced by the Tuple operation so that the
812 following Proj nodes have not to be changed. (They are hard to find due to
813 the implementation with pointers in only one direction.) The Tuple node is
814 smaller than any other node, so that a node can be changed into a Tuple by
815 just changing it's opcode and giving it a new in array."""
819 flags = [ "labeled" ]
822 """Returns an unknown (at compile- and runtime) value. It is a valid
823 optimisation to replace an Unknown by any other constant value."""
826 block = "get_irg_start_block(irg)"
827 flags = [ "cfopcode", "start_block", "constlike", "dump_noblock" ]
831 def getOpList(namespace):
833 for t in namespace.values():
837 if issubclass(t, Op):
842 nodes = getOpList(globals())
843 nodes = sorted(nodes, lambda x,y: cmp(x.name, y.name))