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 name = "input_constraints",
86 type = "ir_asm_constraint*",
89 name = "n_output_constraints",
94 name = "output_constraints",
95 type = "ir_asm_constraint*",
111 # constructor is written manually at the moment, because of the clobbers+
112 # constraints arrays needing special handling (2 arguments for 1 attribute)
116 """Bad nodes indicate invalid input, which is values which should never be
119 The typical use case for the Bad node is removing unreachable code.
120 Frontends should set the current_block to Bad when it is clear that
121 following code must be unreachable (ie. after a goto or return statement).
122 Optimisations also set block predecessors to Bad when it becomes clear,
123 that a control flow edge can never be executed.
125 The gigo optimisations ensures that nodes with Bad as their block, get
126 replaced by Bad themselfes. Nodes with at least 1 Bad input get exchanged
127 with Bad too. Exception to this rule are Block, Phi, Tuple and End node;
128 This is because removing inputs from a Block is hairy operation (requiring,
129 Phis to be shortened too for example). So instead of removing block inputs
130 they are set to Bad, and the actual removal is left to the control flow
131 optimisation phase. Block, Phi, Tuple with only Bad inputs however are
132 replaced by Bad right away."""
134 flags = [ "cfopcode", "start_block", "dump_noblock" ]
137 block = "get_irg_start_block(irg)"
139 attr_struct = "bad_attr"
141 res->attr.bad.irg.irg = irg;
145 """Internal node which is temporary set to nodes which are already removed
151 customSerializer = True
160 flags = [ "labeled" ]
161 attr_struct = "block_attr"
162 customSerializer = True
165 res->attr.block.irg.irg = irg;
166 res->attr.block.backedge = new_backedge_arr(irg->obst, arity);
167 set_Block_matured(res, 1);
169 /* Create and initialize array for Phi-node construction. */
170 if (get_irg_phase_state(irg) == phase_building) {
171 res->attr.block.graph_arr = NEW_ARR_D(ir_node *, irg->obst, irg->n_loc);
172 memset(res->attr.block.graph_arr, 0, irg->n_loc * sizeof(ir_node*));
177 """Returns the borrow bit from and implied subtractions of its 2 operands"""
181 """Performs a bounds-check: if lower <= index < upper then return index,
182 otherwise throw an exception."""
183 ins = [ "mem", "index", "lower", "upper" ]
185 ("M", "memory result", "pn_Generic_M"),
186 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
187 ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
188 ("res", "the checked index", "pn_Generic_other"),
190 flags = [ "fragile", "highlevel" ]
192 pinned_init = "op_pin_state_pinned"
193 attr_struct = "bound_attr"
197 """performs a backend-specific builtin."""
201 ("M", "memory result", "pn_Generic_M"),
202 ("1_result", "first result", "pn_Generic_other"),
204 flags = [ "uses_memory" ]
207 type = "ir_builtin_kind",
216 pinned_init = "op_pin_state_pinned"
217 attr_struct = "builtin_attr"
219 assert((get_unknown_type() == type) || is_Method_type(type));
223 """Calls other code. Control flow is transfered to ptr, additional
224 operands are passed to the called code. Called code usually performs a
225 return operation. The operands of this return operation are the result
227 ins = [ "mem", "ptr" ]
230 ("M", "memory result", "pn_Generic_M"),
231 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
232 ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
233 ("T_result", "tuple containing all results", "pn_Generic_other"),
234 ("P_value_res_base", "pointer to memory register containing copied results passed by value"),
236 flags = [ "fragile", "uses_memory" ]
245 # the tail call attribute can only be set by analysis
249 attr_struct = "call_attr"
251 pinned_init = "op_pin_state_pinned"
253 assert((get_unknown_type() == type) || is_Method_type(type));
257 """Computes the value of the carry-bit that would result when adding the 2
259 flags = [ "commutative" ]
262 """perform a high-level type cast"""
263 mode = "get_irn_mode(irn_op)"
264 flags = [ "highlevel" ]
271 attr_struct = "cast_attr"
272 init = "assert(is_atomic_type(type));"
275 """Returns the relation of 2 operands"""
277 ("False", "always false", "0"),
278 ("Eq", "equal", "1"),
280 ("Le", "less or equal", "pn_Cmp_Eq|pn_Cmp_Lt"),
281 ("Gt", "greater", "4"),
282 ("Ge", "greater or equal", "pn_Cmp_Eq|pn_Cmp_Gt"),
283 ("Lg", "less or greater ('not equal' for integer numbers)", "pn_Cmp_Lt|pn_Cmp_Gt"),
284 ("Leg", "less, equal or greater ('not unordered')", "pn_Cmp_Lt|pn_Cmp_Eq|pn_Cmp_Gt"),
285 ("Uo", "unordered", "8"),
286 ("Ue", "unordered or equal", "pn_Cmp_Uo|pn_Cmp_Eq"),
287 ("Ul", "unordered or less", "pn_Cmp_Uo|pn_Cmp_Lt"),
288 ("Ule", "unordered, less or equal", "pn_Cmp_Uo|pn_Cmp_Lt|pn_Cmp_Eq"),
289 ("Ug", "unordered or greater", "pn_Cmp_Uo|pn_Cmp_Gt"),
290 ("Uge", "onordered, greater or equal", "pn_Cmp_Uo|pn_Cmp_Gt|pn_Cmp_Eq"),
291 ("Ne", "unordered, less or greater ('not equal' for floatingpoint numbers)", "pn_Cmp_Uo|pn_Cmp_Lt|pn_Cmp_Gt"),
292 ("True", "always true", "15"),
297 """Conditionally change control flow. There are two versions of this node:
300 Input: A value of mode_b
301 Output: A tuple of two control flows. The first is taken if the input is
302 false, the second if it is true.
305 Input: A value of mode_Iu
306 Output: A tuple of n control flows. If the Cond's input is i, control flow
307 will proceed along output i. If the input is >= n control flow proceeds
308 along output def_proj.
312 ("false", "control flow if operand is \"false\""),
313 ("true", "control flow if operand is \"true\""),
315 flags = [ "cfopcode", "forking" ]
319 name = "default_proj",
325 type = "cond_jmp_predicate",
326 init = "COND_JMP_PRED_NONE"
329 attr_struct = "cond_attr"
332 """Specifies constraints for a value. This allows explicit representation
333 of path-sensitive properties. (Example: This value is always >= 0 on 1
334 if-branch then all users within that branch are rerouted to a confirm-node
335 specifying this property).
337 A constraint is specified for the relation between value and bound.
338 value is always returned.
339 Note that this node does NOT check or assert the constraint, it merely
341 ins = [ "value", "bound" ]
342 mode = "get_irn_mode(irn_value)"
343 flags = [ "highlevel" ]
351 attr_struct = "confirm_attr"
352 attrs_name = "confirm"
355 """Returns a constant value."""
356 flags = [ "constlike", "start_block" ]
357 block = "get_irg_start_block(irg)"
358 mode = "get_tarval_mode(tarval)"
367 attr_struct = "const_attr"
371 """Converts values between modes"""
380 attr_struct = "conv_attr"
384 """Copies a block of memory"""
385 ins = [ "mem", "dst", "src" ]
387 ("M", "memory result", "pn_Generic_M"),
388 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
389 ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
391 flags = [ "fragile", "uses_memory" ]
398 attr_struct = "copyb_attr"
401 pinned_init = "op_pin_state_pinned"
404 """returns the quotient of its 2 operands, integer version"""
405 ins = [ "mem", "left", "right" ]
407 ("M", "memory result", "pn_Generic_M"),
408 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
409 ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
410 ("res", "result of computation", "pn_Generic_other"),
412 flags = [ "fragile", "uses_memory" ]
413 attrs_name = "divmod"
420 name = "no_remainder",
425 attr_struct = "divmod_attr"
428 arity_override = "oparity_binary"
431 """divides its 2 operands and computes the remainder of the division"""
432 ins = [ "mem", "left", "right" ]
434 ("M", "memory result", "pn_Generic_M"),
435 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
436 ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
437 ("res_div", "result of computation a/b", "pn_Generic_other"),
438 ("res_mod", "result of computation a%b"),
440 flags = [ "fragile", "uses_memory" ]
441 attrs_name = "divmod"
448 attr_struct = "divmod_attr"
451 arity_override = "oparity_binary"
454 """A placeholder value. This is used when constructing cyclic graphs where
455 you have cases where not all predecessors of a phi-node are known. Dummy
456 nodes are used for the unknown predecessors and replaced later."""
458 flags = [ "cfopcode", "start_block", "constlike", "dump_noblock" ]
461 block = "get_irg_start_block(irg)"
464 """Last node of a graph. It references nodes in endless loops (so called
469 flags = [ "cfopcode" ]
471 block = "get_irg_end_block(irg)"
473 customSerializer = True
476 """returns the result of a bitwise exclusive or operation of its operands"""
477 flags = [ "commutative" ]
480 """Frees a block of memory previously allocated by an Alloc node"""
481 ins = [ "mem", "ptr", "size" ]
483 flags = [ "uses_memory" ]
492 type = "ir_where_alloc"
495 attr_struct = "free_attr"
498 """Returns its operand unchanged."""
504 """Jumps to the code in its argument. The code has to be in the same
505 function and the the destination must be one of the blocks reachable
506 by the tuple results"""
510 flags = [ "cfopcode", "forking", "keep" ]
513 """Tests wether an object is an instance of a class-type"""
514 ins = [ "store", "obj" ]
516 ("M", "memory result", "pn_Generic_M"),
517 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
518 ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
519 ("res", "checked object pointer", "pn_Generic_other"),
521 flags = [ "highlevel" ]
528 attr_struct = "io_attr"
530 pinned_init = "op_pin_state_floats"
533 """Jumps to the block connected through the out-value"""
537 flags = [ "cfopcode" ]
540 """Loads a value from memory (heap or stack)."""
541 ins = [ "mem", "ptr" ]
543 ("M", "memory result", "pn_Generic_M"),
544 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
545 ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
546 ("res", "result of load operation", "pn_Generic_other"),
548 flags = [ "fragile", "uses_memory" ]
550 pinned_init = "flags & cons_floats ? op_pin_state_floats : op_pin_state_pinned"
555 java_name = "load_mode"
558 attr_struct = "load_attr"
561 type = "ir_cons_flags",
566 res->attr.load.volatility = flags & cons_volatile ? volatility_is_volatile : volatility_non_volatile;
567 res->attr.load.aligned = flags & cons_unaligned ? align_non_aligned : align_is_aligned;
571 """returns the difference between its operands"""
575 """returns the remainder of its operands from an implied division.
578 * mod(5,3) produces 2
579 * mod(5,-3) produces 2
580 * mod(-5,3) produces -2
581 * mod(-5,-3) produces -2
583 ins = [ "mem", "left", "right" ]
585 ("M", "memory result", "pn_Generic_M"),
586 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
587 ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
588 ("res", "result of computation", "pn_Generic_other"),
590 flags = [ "fragile", "uses_memory" ]
591 attrs_name = "divmod"
598 attr_struct = "divmod_attr"
601 arity_override = "oparity_binary"
604 """returns the product of its operands"""
605 flags = [ "commutative" ]
608 """returns the upper word of the product of its operands (the part which
609 would not fit into the result mode of a normal Mul anymore)"""
610 flags = [ "commutative" ]
613 """returns the false or true operand depending on the value of the sel
615 ins = [ "sel", "false", "true" ]
620 """Placeholder node for cases where you don't need any memory input"""
622 flags = [ "dump_noblock", "dump_noinput" ]
625 block = "get_irg_start_block(irg)"
629 """returns the logical complement of a value. Works for integer values too.
630 If the input is false/zero then true/one is returned, otherwise false/zero
635 """returns the result of a bitwise or operation of its operands"""
636 flags = [ "commutative" ]
639 """Choose a value based on control flow. A phi node has 1 input for each
640 predecessor of its block. If a block is entered from its nth predecessor
641 all phi nodes produce their nth input as result."""
645 attr_struct = "phi_attr"
647 res->attr.phi.u.backedge = new_backedge_arr(irg->obst, arity);'''
649 /* Memory Phis in endless loops must be kept alive.
650 As we can't distinguish these easily we keep all of them alive. */
651 if (is_Phi(res) && mode == mode_M)
652 add_End_keepalive(get_irg_end(irg), res);'''
655 """Pin the value of the node node in the current block. No users of the Pin
656 node can float above the Block of the Pin. The node cannot float behind
657 this block. Often used to Pin the NoMem node."""
659 mode = "get_irn_mode(irn_op)"
660 flags = [ "highlevel" ]
664 """returns an entry of a tuple value"""
670 block = "get_nodes_block(irn_pred)"
671 graph = "get_irn_irg(irn_pred)"
672 customSerializer = True
679 attr_struct = "proj_attr"
682 """returns the quotient of its 2 operands, floatingpoint version"""
683 ins = [ "mem", "left", "right" ]
685 ("M", "memory result", "pn_Generic_M"),
686 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
687 ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
688 ("res", "result of computation", "pn_Generic_other"),
690 flags = [ "fragile", "uses_memory" ]
691 attrs_name = "divmod"
698 attr_struct = "divmod_attr"
701 arity_override = "oparity_binary"
704 """Raises an exception. Unconditional change of control flow. Writes an
705 explicit Except variable to memory to pass it to the exception handler.
706 Must be lowered to a Call to a runtime check function."""
707 ins = [ "mem", "exo_ptr" ]
709 ("M", "memory result", "pn_Generic_M"),
710 ("X", "control flow to exception handler", "pn_Generic_X_regular"),
712 flags = [ "highlevel", "cfopcode" ]
716 """Returns from the current function. Takes memory and return values as
721 flags = [ "cfopcode" ]
725 """Returns its first operand bits rotated left by the amount in the 2nd
730 """Computes the address of a entity of a compound type given the base
731 address of an instance of the compound type."""
732 ins = [ "mem", "ptr" ]
735 mode = "is_Method_type(get_entity_type(entity)) ? mode_P_code : mode_P_data"
743 attr_struct = "sel_attr"
746 """Returns its first operands bits shifted left by the amount of the 2nd
751 """Returns its first operands bits shifted right by the amount of the 2nd
752 operand. No special handling for the sign bit (zero extension)"""
756 """Returns its first operands bits shifted right by the amount of the 2nd
757 operand. The leftmost bit (usually the sign bit) stays the same
762 """The first node of a graph. Execution starts with this node."""
764 ("X_initial_exec", "control flow"),
765 ("M", "initial memory"),
766 ("P_frame_base", "frame base pointer"),
767 ("P_tls", "pointer to thread local storage segment"),
768 ("T_args", "function arguments")
772 flags = [ "cfopcode" ]
775 customSerializer = True
776 block = "get_irg_start_block(irg)"
779 """Stores a value into memory (heap or stack)."""
780 ins = [ "mem", "ptr", "value" ]
782 ("M", "memory result", "pn_Generic_M"),
783 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
784 ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
786 flags = [ "fragile", "uses_memory" ]
788 attr_struct = "store_attr"
789 pinned_init = "flags & cons_floats ? op_pin_state_floats : op_pin_state_pinned"
792 type = "ir_cons_flags",
797 res->attr.store.volatility = flags & cons_volatile ? volatility_is_volatile : volatility_non_volatile;
798 res->attr.store.aligned = flags & cons_unaligned ? align_non_aligned : align_is_aligned;
802 """returns the difference of its operands"""
806 """A symbolic constant.
808 - symconst_type_tag The symbolic constant represents a type tag. The
809 type the tag stands for is given explicitly.
810 - symconst_type_size The symbolic constant represents the size of a type.
811 The type of which the constant represents the size
813 - symconst_type_align The symbolic constant represents the alignment of a
814 type. The type of which the constant represents the
815 size is given explicitly.
816 - symconst_addr_ent The symbolic constant represents the address of an
817 entity (variable or method). The variable is given
818 explicitly by a firm entity.
819 - symconst_ofs_ent The symbolic constant represents the offset of an
820 entity in its owner type.
821 - symconst_enum_const The symbolic constant is a enumeration constant of
822 an enumeration type."""
824 flags = [ "constlike", "start_block" ]
834 attr_struct = "symconst_attr"
835 customSerializer = True
836 # constructor is written manually at the moment, because of the strange
841 """The Sync operation unifies several partial memory blocks. These blocks
842 have to be pairwise disjunct or the values in common locations have to
843 be identical. This operation allows to specify all operations that
844 eventually need several partial memory blocks as input with a single
845 entrance by unifying the memories with a preceding Sync operation."""
852 """Builds a Tuple from single values.
854 This is needed to implement optimizations that remove a node that produced
855 a tuple. The node can be replaced by the Tuple operation so that the
856 following Proj nodes have not to be changed. (They are hard to find due to
857 the implementation with pointers in only one direction.) The Tuple node is
858 smaller than any other node, so that a node can be changed into a Tuple by
859 just changing it's opcode and giving it a new in array."""
863 flags = [ "labeled" ]
866 """Returns an unknown (at compile- and runtime) value. It is a valid
867 optimisation to replace an Unknown by any other constant value."""
870 block = "get_irg_start_block(irg)"
871 flags = [ "cfopcode", "start_block", "constlike", "dump_noblock" ]
875 def getOpList(namespace):
877 for t in namespace.values():
881 if issubclass(t, Op):
886 nodes = getOpList(globals())
887 nodes = sorted(nodes, lambda x,y: cmp(x.name, y.name))