put node descriptions into the spec file
authorMatthias Braun <matze@braunis.de>
Sat, 8 Jan 2011 12:32:04 +0000 (12:32 +0000)
committerMatthias Braun <matze@braunis.de>
Sat, 8 Jan 2011 12:32:04 +0000 (12:32 +0000)
[r28232]

scripts/ir_spec.py

index 038871c..6f6b144 100755 (executable)
@@ -1,11 +1,11 @@
 from spec_util import abstract, setnodedefaults
 
 class Op(object):
-       "Base class for firm nodes"
+       """Base class for firm nodes"""
 abstract(Op)
 
 class Unop(Op):
-       "Unary nodes have exactly 1 input"
+       """Unary nodes have exactly 1 input"""
        name     = "unop"
        ins      = [ "op" ]
        op_index = 0
@@ -13,7 +13,7 @@ class Unop(Op):
 abstract(Unop)
 
 class Binop(Op):
-       "Binary nodes have exactly 2 inputs"
+       """Binary nodes have exactly 2 inputs"""
        name     = "binop"
        ins      = [ "left", "right" ]
        op_index = 0
@@ -21,9 +21,13 @@ class Binop(Op):
 abstract(Binop)
 
 class Add(Binop):
+       """returns the sum of its operands"""
        flags = ["commutative"]
 
 class Alloc(Op):
+       """allocates a block of memory.
+       It can be specified whether the variable should be allocated to the stack
+       or to the heap."""
        ins   = [ "mem", "count" ]
        outs  = [
                ("M",         "memory result",                         "pn_Generic_M"),
@@ -46,6 +50,12 @@ class Alloc(Op):
        attr_struct = "alloc_attr"
 
 class Anchor(Op):
+       """utiliy node used to "hold" nodes in a graph that might possibly not be
+       reachable by other means or which should be reachable immediately without
+       searching through the graph.
+       Each firm-graph contains exactly one anchor node whose address is always
+       known. All other well-known graph-nodes like Start, End, NoMem, Bad, ...
+       are found by looking at the respective Anchor operand."""
        mode             = "mode_ANY"
        arity            = "variable"
        flags            = [ "dump_noblock" ]
@@ -57,9 +67,11 @@ class Anchor(Op):
        customSerializer = True
 
 class And(Binop):
+       """returns the result of a bitwise and operation of its operands"""
        flags    = [ "commutative" ]
 
 class ASM(Op):
+       """executes assembler fragments of the target machine"""
        mode             = "mode_T"
        arity            = "variable"
        flags            = [ "keep", "uses_memory" ]
@@ -68,36 +80,25 @@ class ASM(Op):
        attr_struct      = "asm_attr"
        attrs_name       = "assem"
        customSerializer = True
-       attrs = [
-               dict(
-                       name = "input_constraints",
-                       type = "ir_asm_constraint*",
-               ),
-               dict(
-                       name = "n_output_constraints",
-                       type = "int",
-                       noprop = True,
-               ),
-               dict(
-                       name = "output_constraints",
-                       type = "ir_asm_constraint*",
-               ),
-               dict(
-                       name = "n_clobbers",
-                       type = "int",
-                       noprop = True,
-               ),
-               dict(
-                       name = "clobbers",
-                       type = "ident**",
-               ),
-               dict(
-                       name = "text",
-                       type = "ident*",
-               ),
-       ]
 
 class Bad(Op):
+       """Bad nodes indicate invalid input, which is values which should never be
+       computed.
+
+       The typical use case for the Bad node is removing unreachable code.
+       Frontends should set the current_block to Bad when it is clear that
+       following code must be unreachable (ie. after a goto or return statement).
+       Optimisations also set block predecessors to Bad when it becomes clear,
+       that a control flow edge can never be executed.
+
+       The gigo optimisations ensures that nodes with Bad as their block, get
+       replaced by Bad themselfes. Nodes with at least 1 Bad input get exchanged
+       with Bad too. Exception to this rule are Block, Phi, Tuple and End node;
+       This is because removing inputs from a Block is hairy operation (requiring,
+       Phis to be shortened too for example). So instead of removing block inputs
+       they are set to Bad, and the actual removal is left to the control flow
+       optimisation phase. Block, Phi, Tuple with only Bad inputs however are
+       replaced by Bad right away."""
        mode          = "mode_T"
        flags         = [ "cfopcode", "start_block", "dump_noblock" ]
        pinned        = "yes"
@@ -110,6 +111,8 @@ class Bad(Op):
        '''
 
 class Deleted(Op):
+       """Internal node which is temporary set to nodes which are already removed
+       from the graph."""
        mode             = "mode_Bad"
        flags            = [ ]
        pinned           = "yes"
@@ -117,6 +120,7 @@ class Deleted(Op):
        customSerializer = True
 
 class Block(Op):
+       """A basic block"""
        mode             = "mode_BB"
        knownBlock       = True
        block            = "NULL"
@@ -139,9 +143,12 @@ class Block(Op):
        '''
 
 class Borrow(Binop):
+       """Returns the borrow bit from and implied subtractions of its 2 operands"""
        flags = []
 
 class Bound(Op):
+       """Performs a bounds-check: if lower <= index < upper then return index,
+       otherwise throw an exception."""
        ins    = [ "mem", "index", "lower", "upper" ]
        outs  = [
                ("M",         "memory result",                         "pn_Generic_M"),
@@ -156,6 +163,7 @@ class Bound(Op):
        attrs_name  = "bound"
 
 class Builtin(Op):
+       """performs a backend-specific builtin."""
        ins      = [ "mem" ]
        arity    = "variable"
        outs     = [
@@ -181,6 +189,10 @@ class Builtin(Op):
        '''
 
 class Call(Op):
+       """Calls other code. Control flow is transfered to ptr, additional
+       operands are passed to the called code. Called code usually performs a
+       return operation. The operands of this return operation are the result
+       of the Call node."""
        ins      = [ "mem", "ptr" ]
        arity    = "variable"
        outs     = [
@@ -211,9 +223,12 @@ class Call(Op):
        '''
 
 class Carry(Binop):
+       """Computes the value of the carry-bit that would result when adding the 2
+       operands"""
        flags = [ "commutative" ]
 
 class Cast(Unop):
+       """perform a high-level type cast"""
        mode     = "get_irn_mode(irn_op)"
        flags    = [ "highlevel" ]
        attrs    = [
@@ -226,6 +241,7 @@ class Cast(Unop):
        init     = "assert(is_atomic_type(type));"
 
 class Cmp(Binop):
+       """Returns the relation of 2 operands"""
        outs  = [
                ("False", "always false",                            "0"),
                ("Eq",    "equal",                                   "1"),
@@ -247,6 +263,19 @@ class Cmp(Binop):
        flags = []
 
 class Cond(Op):
+       """Conditionally change control flow. There are two versions of this node:
+
+       Boolean Cond:
+       Input:  A value of mode_b
+       Output: A tuple of two control flows. The first is taken if the input is
+               false, the second if it is true.
+
+       Switch Cond:
+       Input:  A value of mode_Iu
+       Output: A tuple of n control flows. If the Cond's input is i, control flow
+       will proceed along output i. If the input is >= n control flow proceeds
+       along output def_proj.
+       """
        ins      = [ "selector" ]
        outs     = [
                ("false", "control flow if operand is \"false\""),
@@ -269,6 +298,15 @@ class Cond(Op):
        attr_struct = "cond_attr"
 
 class Confirm(Op):
+       """Specifies constraints for a value. This allows explicit representation
+       of path-sensitive properties. (Example: This value is always >= 0 on 1
+       if-branch then all users within that branch are rerouted to a confirm-node
+       specifying this property).
+
+       A constraint is specified for the relation between value and bound.
+       value is always returned.
+       Note that this node does NOT check or assert the constraint, it merely
+       specifies it."""
        ins      = [ "value", "bound" ]
        mode     = "get_irn_mode(irn_value)"
        flags    = [ "highlevel" ]
@@ -283,6 +321,7 @@ class Confirm(Op):
        attrs_name  = "confirm"
 
 class Const(Op):
+       """Returns a constant value."""
        mode       = ""
        flags      = [ "constlike", "start_block" ]
        knownBlock = True
@@ -297,6 +336,7 @@ class Const(Op):
        attr_struct = "const_attr"
 
 class Conv(Unop):
+       """Converts values between modes"""
        flags = []
        attrs = [
                dict(
@@ -313,13 +353,14 @@ class Conv(Unop):
        attrs_name  = "conv"
 
 class CopyB(Op):
+       """Copies a block of memory"""
        ins   = [ "mem", "dst", "src" ]
        outs  = [
                ("M",         "memory result",                         "pn_Generic_M"),
                ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
                ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
        ]
-       flags = [ "fragile", "highlevel", "uses_memory" ]
+       flags = [ "fragile", "uses_memory" ]
        attrs = [
                dict(
                        name = "type",
@@ -332,6 +373,7 @@ class CopyB(Op):
        pinned_init = "op_pin_state_pinned"
 
 class Div(Op):
+       """returns the quotient of its 2 operands, integer version"""
        ins   = [ "mem", "left", "right" ]
        outs  = [
                ("M",         "memory result",                         "pn_Generic_M"),
@@ -362,6 +404,7 @@ class Div(Op):
        arity_override = "oparity_binary"
 
 class DivMod(Op):
+       """divides its 2 operands and computes the remainder of the division"""
        ins   = [ "mem", "left", "right" ]
        outs  = [
                ("M",         "memory result",                         "pn_Generic_M"),
@@ -384,6 +427,9 @@ class DivMod(Op):
        arity_override = "oparity_binary"
 
 class Dummy(Op):
+       """A placeholder value. This is used when constructing cyclic graphs where
+       you have cases where not all predecessors of a phi-node are known. Dummy
+       nodes are used for the unknown predecessors and replaced later."""
        ins        = []
        flags      = [ "cfopcode", "start_block", "constlike", "dump_noblock" ]
        knownBlock = True
@@ -391,6 +437,8 @@ class Dummy(Op):
        block      = "get_irg_start_block(irg)"
 
 class End(Op):
+       """Last node of a graph. It references nodes in endless loops (so called
+       keepalive edges)"""
        mode             = "mode_X"
        pinned           = "yes"
        arity            = "dynamic"
@@ -401,9 +449,11 @@ class End(Op):
        customSerializer = True
 
 class Eor(Binop):
+       """returns the result of a bitwise exclusive or operation of its operands"""
        flags    = [ "commutative" ]
 
 class Free(Op):
+       """Frees a block of memory previously allocated by an Alloc node"""
        ins    = [ "mem", "ptr", "size" ]
        mode   = "mode_M"
        flags  = [ "uses_memory" ]
@@ -421,17 +471,22 @@ class Free(Op):
        attr_struct = "free_attr"
 
 class Id(Op):
+       """Returns its operand unchanged."""
        ins    = [ "pred" ]
        pinned = "no"
        flags  = []
 
 class IJmp(Op):
+       """Jumps to the code in its argument. The code has to be in the same
+       function and the the destination must be one of the blocks reachable
+       by the tuple results"""
        mode     = "mode_X"
        pinned   = "yes"
        ins      = [ "target" ]
        flags    = [ "cfopcode", "forking", "keep" ]
 
 class InstOf(Op):
+       """Tests wether an object is an instance of a class-type"""
        ins   = [ "store", "obj" ]
        outs  = [
                ("M",         "memory result",                         "pn_Generic_M"),
@@ -451,12 +506,14 @@ class InstOf(Op):
        pinned_init = "op_pin_state_floats"
 
 class Jmp(Op):
+       """Jumps to the block connected through the out-value"""
        mode     = "mode_X"
        pinned   = "yes"
        ins      = []
        flags    = [ "cfopcode" ]
 
 class Load(Op):
+       """Loads a value from memory (heap or stack)."""
        ins      = [ "mem", "ptr" ]
        outs  = [
                ("M",         "memory result",                         "pn_Generic_M"),
@@ -483,9 +540,18 @@ class Load(Op):
        ]
 
 class Minus(Unop):
+       """returns the difference between its operands"""
        flags = []
 
 class Mod(Op):
+       """returns the remainder of its operands from an implied division.
+
+       Examples:
+       * mod(5,3)   produces 2
+       * mod(5,-3)  produces 2
+       * mod(-5,3)  produces -2
+       * mod(-5,-3) produces -2
+       """
        ins   = [ "mem", "left", "right" ]
        outs  = [
                ("M",         "memory result",                         "pn_Generic_M"),
@@ -507,17 +573,23 @@ class Mod(Op):
        arity_override = "oparity_binary"
 
 class Mul(Binop):
+       """returns the product of its operands"""
        flags = [ "commutative" ]
 
 class Mulh(Binop):
+       """returns the upper word of the product of its operands (the part which
+       would not fit into the result mode of a normal Mul anymore)"""
        flags = [ "commutative" ]
 
 class Mux(Op):
+       """returns the false or true operand depending on the value of the sel
+       operand"""
        ins    = [ "sel", "false", "true" ]
        flags  = []
        pinned = "no"
 
 class NoMem(Op):
+       """Placeholder node for cases where you don't need any memory input"""
        mode          = "mode_M"
        flags         = [ "dump_noblock", "dump_noinput" ]
        pinned        = "yes"
@@ -526,12 +598,19 @@ class NoMem(Op):
        singleton     = True
 
 class Not(Unop):
+       """returns the logical complement of a value. Works for integer values too.
+       If the input is false/zero then true/one is returned, otherwise false/zero
+       is returned."""
        flags = []
 
 class Or(Binop):
+       """returns the result of a bitwise or operation of its operands"""
        flags = [ "commutative" ]
 
 class Phi(Op):
+       """Choose a value based on control flow. A phi node has 1 input for each
+       predecessor of its block. If a block is entered from its nth predecessor
+       all phi nodes produce their nth input as result."""
        pinned        = "yes"
        arity         = "variable"
        flags         = []
@@ -544,12 +623,16 @@ class Phi(Op):
        '''
 
 class Pin(Op):
+       """Pin the value of the node node in the current block. No users of the Pin
+       node can float above the Block of the Pin. The node cannot float behind
+       this block. Often used to Pin the NoMem node."""
        ins      = [ "op" ]
        mode     = "get_irn_mode(irn_op)"
        flags    = [ "highlevel" ]
        pinned   = "yes"
 
 class Proj(Op):
+       """returns an entry of a tuple value"""
        ins              = [ "pred" ]
        flags            = []
        pinned           = "no"
@@ -569,6 +652,7 @@ class Proj(Op):
        attr_struct = "long"
 
 class Quot(Op):
+       """returns the quotient of its 2 operands, floatingpoint version"""
        ins   = [ "mem", "left", "right" ]
        outs  = [
                ("M",         "memory result",                         "pn_Generic_M"),
@@ -590,6 +674,9 @@ class Quot(Op):
        arity_override = "oparity_binary"
 
 class Raise(Op):
+       """Raises an exception. Unconditional change of control flow. Writes an
+       explicit Except variable to memory to pass it to the exception handler.
+       Must be lowered to a Call to a runtime check function."""
        ins    = [ "mem", "exo_ptr" ]
        outs  = [
                ("M", "memory result",                     "pn_Generic_M"),
@@ -599,6 +686,8 @@ class Raise(Op):
        pinned = "yes"
 
 class Return(Op):
+       """Returns from the current function. Takes memory and return values as
+       operands."""
        ins      = [ "mem" ]
        arity    = "variable"
        mode     = "mode_X"
@@ -606,9 +695,13 @@ class Return(Op):
        pinned   = "yes"
 
 class Rotl(Binop):
+       """Returns its first operand bits rotated left by the amount in the 2nd
+       operand"""
        flags    = []
 
 class Sel(Op):
+       """Computes the address of a entity of a compound type given the base
+       address of an instance of the compound type."""
        ins    = [ "mem", "ptr" ]
        arity  = "variable"
        flags  = []
@@ -623,15 +716,23 @@ class Sel(Op):
        attr_struct = "sel_attr"
 
 class Shl(Binop):
+       """Returns its first operands bits shifted left by the amount of the 2nd
+       operand"""
        flags = []
 
 class Shr(Binop):
+       """Returns its first operands bits shifted right by the amount of the 2nd
+       operand. No special handling for the sign bit (zero extension)"""
        flags = []
 
 class Shrs(Binop):
+       """Returns its first operands bits shifted right by the amount of the 2nd
+       operand. The leftmost bit (usually the sign bit) stays the same
+       (sign extension)"""
        flags = []
 
 class Start(Op):
+       """The first node of a graph. Execution starts with this node."""
        outs       = [
                ("X_initial_exec", "control flow"),
                ("M",              "initial memory"),
@@ -648,6 +749,7 @@ class Start(Op):
        block            = "get_irg_start_block(irg)"
 
 class Store(Op):
+       """Stores a value into memory (heap or stack)."""
        ins      = [ "mem", "ptr", "value" ]
        outs  = [
                ("M",         "memory result",                         "pn_Generic_M"),
@@ -666,9 +768,27 @@ class Store(Op):
        ]
 
 class Sub(Binop):
+       """returns the difference of its operands"""
        flags = []
 
 class SymConst(Op):
+       """A symbolic constant.
+
+        - symconst_type_tag   The symbolic constant represents a type tag.  The
+                              type the tag stands for is given explicitly.
+        - symconst_type_size  The symbolic constant represents the size of a type.
+                              The type of which the constant represents the size
+                              is given explicitly.
+        - symconst_type_align The symbolic constant represents the alignment of a
+                              type.  The type of which the constant represents the
+                              size is given explicitly.
+        - symconst_addr_ent   The symbolic constant represents the address of an
+                              entity (variable or method).  The variable is given
+                              explicitly by a firm entity.
+        - symconst_ofs_ent    The symbolic constant represents the offset of an
+                              entity in its owner type.
+        - symconst_enum_const The symbolic constant is a enumeration constant of
+                              an enumeration type."""
        mode       = "mode_P"
        flags      = [ "constlike", "start_block" ]
        knownBlock = True
@@ -684,18 +804,33 @@ class SymConst(Op):
        customSerializer = True
 
 class Sync(Op):
+       """The Sync operation unifies several partial memory blocks. These blocks
+       have to be pairwise disjunct or the values in common locations have to
+       be identical.  This operation allows to specify all operations that
+       eventually need several partial memory blocks as input with a single
+       entrance by unifying the memories with a preceding Sync operation."""
        mode     = "mode_M"
        flags    = []
        pinned   = "no"
        arity    = "dynamic"
 
 class Tuple(Op):
+       """Builds a Tuple from single values.
+
+       This is needed to implement optimizations that remove a node that produced
+       a tuple.  The node can be replaced by the Tuple operation so that the
+       following Proj nodes have not to be changed. (They are hard to find due to
+       the implementation with pointers in only one direction.) The Tuple node is
+       smaller than any other node, so that a node can be changed into a Tuple by
+       just changing it's opcode and giving it a new in array."""
        arity  = "variable"
        mode   = "mode_T"
        pinned = "no"
        flags  = [ "labeled" ]
 
 class Unknown(Op):
+       """Returns an unknown (at compile- and runtime) value. It is a valid
+       optimisation to replace an Unknown by any other constant value."""
        knownBlock = True
        pinned     = "yes"
        block      = "get_irg_start_block(irg)"