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
647 """returns the quotient of its 2 operands, floatingpoint version"""
648 ins = [ "mem", "left", "right" ]
650 ("M", "memory result", "pn_Generic_M"),
651 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
652 ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
653 ("res", "result of computation", "pn_Generic_other"),
655 flags = [ "fragile", "uses_memory" ]
656 attrs_name = "divmod"
663 attr_struct = "divmod_attr"
666 arity_override = "oparity_binary"
669 """Raises an exception. Unconditional change of control flow. Writes an
670 explicit Except variable to memory to pass it to the exception handler.
671 Must be lowered to a Call to a runtime check function."""
672 ins = [ "mem", "exo_ptr" ]
674 ("M", "memory result", "pn_Generic_M"),
675 ("X", "control flow to exception handler", "pn_Generic_X_regular"),
677 flags = [ "highlevel", "cfopcode" ]
681 """Returns from the current function. Takes memory and return values as
686 flags = [ "cfopcode" ]
690 """Returns its first operand bits rotated left by the amount in the 2nd
695 """Computes the address of a entity of a compound type given the base
696 address of an instance of the compound type."""
697 ins = [ "mem", "ptr" ]
700 mode = "is_Method_type(get_entity_type(entity)) ? mode_P_code : mode_P_data"
708 attr_struct = "sel_attr"
711 """Returns its first operands bits shifted left by the amount of the 2nd
716 """Returns its first operands bits shifted right by the amount of the 2nd
717 operand. No special handling for the sign bit (zero extension)"""
721 """Returns its first operands bits shifted right by the amount of the 2nd
722 operand. The leftmost bit (usually the sign bit) stays the same
727 """The first node of a graph. Execution starts with this node."""
729 ("X_initial_exec", "control flow"),
730 ("M", "initial memory"),
731 ("P_frame_base", "frame base pointer"),
732 ("P_tls", "pointer to thread local storage segment"),
733 ("T_args", "function arguments")
737 flags = [ "cfopcode" ]
740 customSerializer = True
741 block = "get_irg_start_block(irg)"
744 """Stores a value into memory (heap or stack)."""
745 ins = [ "mem", "ptr", "value" ]
747 ("M", "memory result", "pn_Generic_M"),
748 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
749 ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
751 flags = [ "fragile", "uses_memory" ]
753 attr_struct = "store_attr"
754 pinned_init = "flags & cons_floats ? op_pin_state_floats : op_pin_state_pinned"
757 type = "ir_cons_flags",
763 """returns the difference of its operands"""
767 """A symbolic constant.
769 - symconst_type_tag The symbolic constant represents a type tag. The
770 type the tag stands for is given explicitly.
771 - symconst_type_size The symbolic constant represents the size of a type.
772 The type of which the constant represents the size
774 - symconst_type_align The symbolic constant represents the alignment of a
775 type. The type of which the constant represents the
776 size is given explicitly.
777 - symconst_addr_ent The symbolic constant represents the address of an
778 entity (variable or method). The variable is given
779 explicitly by a firm entity.
780 - symconst_ofs_ent The symbolic constant represents the offset of an
781 entity in its owner type.
782 - symconst_enum_const The symbolic constant is a enumeration constant of
783 an enumeration type."""
785 flags = [ "constlike", "start_block" ]
795 attr_struct = "symconst_attr"
796 customSerializer = True
799 """The Sync operation unifies several partial memory blocks. These blocks
800 have to be pairwise disjunct or the values in common locations have to
801 be identical. This operation allows to specify all operations that
802 eventually need several partial memory blocks as input with a single
803 entrance by unifying the memories with a preceding Sync operation."""
810 """Builds a Tuple from single values.
812 This is needed to implement optimizations that remove a node that produced
813 a tuple. The node can be replaced by the Tuple operation so that the
814 following Proj nodes have not to be changed. (They are hard to find due to
815 the implementation with pointers in only one direction.) The Tuple node is
816 smaller than any other node, so that a node can be changed into a Tuple by
817 just changing it's opcode and giving it a new in array."""
821 flags = [ "labeled" ]
824 """Returns an unknown (at compile- and runtime) value. It is a valid
825 optimisation to replace an Unknown by any other constant value."""
828 block = "get_irg_start_block(irg)"
829 flags = [ "cfopcode", "start_block", "constlike", "dump_noblock" ]
833 def getOpList(namespace):
835 for t in namespace.values():
839 if issubclass(t, Op):
844 nodes = getOpList(globals())
845 nodes = sorted(nodes, lambda x,y: cmp(x.name, y.name))