output documentation to file on request
[libfirm] / scripts / ir_spec.py
index 5e47b09..489cd40 100755 (executable)
@@ -38,10 +38,10 @@ class Alloc(Op):
                ("count", "number of objects to allocate" ),
        ]
        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"),
-               ("res",       "pointer to newly allocated memory",     "pn_Generic_other"),
+               ("M",         "memory result"),
+               ("res",       "pointer to newly allocated memory"),
+               ("X_regular", "control flow when no exception occurs"),
+               ("X_except",  "control flow when exception occured"),
        ]
        attrs = [
                dict(
@@ -56,7 +56,9 @@ class Alloc(Op):
                )
        ]
        flags       = [ "fragile", "uses_memory" ]
-       pinned      = "yes"
+       pinned      = "exception"
+       throws_init = "false"
+       pinned_init = "op_pin_state_pinned"
        attr_struct = "alloc_attr"
 
 class Anchor(Op):
@@ -98,7 +100,7 @@ class ASM(Op):
                ),
                dict(
                        name    = "n_output_constraints",
-                       type    = "int",
+                       type    = "size_t",
                        noprop  = True,
                        comment = "number of output constraints",
                ),
@@ -109,7 +111,7 @@ class ASM(Op):
                ),
                dict(
                        name    = "n_clobbers",
-                       type    = "int",
+                       type    = "size_t",
                        noprop  = True,
                        comment = "number of clobbered registers/memory",
                ),
@@ -162,7 +164,7 @@ class Deleted(Op):
        flags            = [ ]
        pinned           = "yes"
        noconstructor    = True
-       customSerializer = True
+       customSerializer = True # this has no serializer
 
 class Block(Op):
        """A basic block"""
@@ -173,6 +175,14 @@ class Block(Op):
        arity            = "variable"
        flags            = [ "labeled" ]
        attr_struct      = "block_attr"
+       attrs            = [
+               dict(
+                       name    = "entity",
+                       type    = "ir_entity*",
+                       comment = "entity representing this block",
+                       init    = "NULL",
+               ),
+       ]
        customSerializer = True
 
        init = '''
@@ -201,16 +211,16 @@ class Bound(Op):
                ("upper",  "upper bound (exclusive)"),
        ]
        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"),
-               ("res",       "the checked index",                     "pn_Generic_other"),
+               ("M",         "memory result"),
+               ("res",       "the checked index"),
+               ("X_regular", "control flow when no exception occurs"),
+               ("X_except",  "control flow when exception occured"),
        ]
        flags  = [ "fragile", "highlevel" ]
        pinned = "exception"
        pinned_init = "op_pin_state_pinned"
+       throws_init = "false"
        attr_struct = "bound_attr"
-       attrs_name  = "bound"
 
 class Builtin(Op):
        """performs a backend-specific builtin."""
@@ -219,8 +229,8 @@ class Builtin(Op):
        ]
        arity    = "variable"
        outs     = [
-               ("M",        "memory result", "pn_Generic_M"),
-               ("1_result", "first result",  "pn_Generic_other"),
+               ("M", "memory result"),
+               # results follow here
        ]
        flags    = [ "uses_memory" ]
        attrs    = [
@@ -253,10 +263,10 @@ class Call(Op):
        ]
        arity    = "variable"
        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"),
-               ("T_result",         "tuple containing all results",          "pn_Generic_other"),
+               ("M",                "memory result"),
+               ("T_result",         "tuple containing all results"),
+               ("X_regular",        "control flow when no exception occurs"),
+               ("X_except",         "control flow when exception occured"),
        ]
        flags    = [ "fragile", "uses_memory" ]
        attrs    = [
@@ -265,16 +275,11 @@ class Call(Op):
                        name    = "type",
                        comment = "type of the call (usually type of the called procedure)",
                ),
-               dict(
-                       type = "unsigned",
-                       name = "tail_call",
-                       # the tail call attribute can only be set by analysis
-                       init = "0",
-               )
        ]
        attr_struct = "call_attr"
        pinned      = "memory"
        pinned_init = "op_pin_state_pinned"
+       throws_init = "false"
        init = '''
        assert((get_unknown_type() == type) || is_Method_type(type));
        '''
@@ -313,19 +318,7 @@ class Cmp(Binop):
        attr_struct = "cmp_attr"
 
 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.
-       """
+       """Conditionally change control flow."""
        ins      = [
                ("selector",  "condition parameter"),
        ]
@@ -336,21 +329,42 @@ class Cond(Op):
        flags    = [ "cfopcode", "forking" ]
        pinned   = "yes"
        attrs    = [
-               dict(
-                       name    = "default_proj",
-                       type    = "long",
-                       init    = "0",
-                       comment = "Proj-number of default case for switch-Cond",
-               ),
                dict(
                        name    = "jmp_pred",
                        type    = "cond_jmp_predicate",
                        init    = "COND_JMP_PRED_NONE",
                        comment = "can indicate the most likely jump",
-               )
+               ),
        ]
        attr_struct = "cond_attr"
 
+class Switch(Op):
+       """Change control flow. The destination is choosen based on an integer input value which is looked up in a table.
+
+       Backends can implement this efficiently using a jump table."""
+       ins    = [
+               ("selector", "input selector"),
+       ]
+       outs   = [
+               ("default", "control flow if no other case matches"),
+       ]
+       flags  = [ "cfopcode", "forking" ]
+       pinned = "yes"
+       attrs  = [
+               dict(
+                       name    = "n_outs",
+                       type    = "unsigned",
+                       comment = "number of outputs (including pn_Switch_default)",
+               ),
+               dict(
+                       name    = "table",
+                       type    = "ir_switch_table*",
+                       comment = "table describing mapping from input values to Proj numbers",
+               ),
+       ]
+       attr_struct = "switch_attr"
+       attrs_name  = "switcha"
+
 class Confirm(Op):
        """Specifies constraints for a value. This allows explicit representation
        of path-sensitive properties. (Example: This value is always >= 0 on 1
@@ -376,7 +390,6 @@ class Confirm(Op):
                ),
        ]
        attr_struct = "confirm_attr"
-       attrs_name  = "confirm"
 
 class Const(Op):
        """Returns a constant value."""
@@ -407,7 +420,6 @@ class Conv(Unop):
                )
        ]
        attr_struct = "conv_attr"
-       attrs_name  = "conv"
 
 class CopyB(Op):
        """Copies a block of memory"""
@@ -417,9 +429,9 @@ class CopyB(Op):
                ("src",  "source address"),
        ]
        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"),
+               ("M",         "memory result"),
+               ("X_regular", "control flow when no exception occurs"),
+               ("X_except",  "control flow when exception occured"),
        ]
        flags = [ "fragile", "uses_memory" ]
        attrs = [
@@ -430,9 +442,9 @@ class CopyB(Op):
                )
        ]
        attr_struct = "copyb_attr"
-       attrs_name  = "copyb"
        pinned      = "memory"
        pinned_init = "op_pin_state_pinned"
+       throws_init = "false"
 
 class Div(Op):
        """returns the quotient of its 2 operands"""
@@ -442,13 +454,12 @@ class Div(Op):
                ("right", "second operand"),
        ]
        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"),
-               ("res",       "result of computation",                 "pn_Generic_other"),
+               ("M",         "memory result"),
+               ("res",       "result of computation"),
+               ("X_regular", "control flow when no exception occurs"),
+               ("X_except",  "control flow when exception occured"),
        ]
        flags = [ "fragile", "uses_memory" ]
-       attrs_name = "div"
        attrs = [
                dict(
                        type    = "ir_mode*",
@@ -463,6 +474,7 @@ class Div(Op):
        ]
        attr_struct = "div_attr"
        pinned      = "exception"
+       throws_init = "false"
        op_index    = 1
        arity_override = "oparity_binary"
 
@@ -486,7 +498,6 @@ class End(Op):
        knownBlock       = True
        block            = "get_irg_end_block(irg)"
        singleton        = True
-       customSerializer = True
 
 class Eor(Binop):
        """returns the result of a bitwise exclusive or operation of its operands"""
@@ -497,7 +508,7 @@ class Free(Op):
        ins    = [
                ("mem",   "memory dependency" ),
                ("ptr",   "pointer to the object to free"),
-               ("size",  "number of objects to allocate" ),
+               ("count", "number of objects to allocate" ),
        ]
        mode   = "mode_M"
        flags  = [ "uses_memory" ]
@@ -542,10 +553,10 @@ class InstOf(Op):
           ("obj",   "pointer to object being queried")
        ]
        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"),
-               ("res",       "checked object pointer",                "pn_Generic_other"),
+               ("M",         "memory result"),
+               ("res",       "checked object pointer"),
+               ("X_regular", "control flow when no exception occurs"),
+               ("X_except",  "control flow when exception occured"),
        ]
        flags = [ "highlevel" ]
        attrs = [
@@ -573,10 +584,10 @@ class Load(Op):
                ("ptr",  "address to load from"),
        ]
        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"),
-               ("res",       "result of load operation",              "pn_Generic_other"),
+               ("M",         "memory result"),
+               ("res",       "result of load operation"),
+               ("X_regular", "control flow when no exception occurs"),
+               ("X_except",  "control flow when exception occured"),
        ]
        flags    = [ "fragile", "uses_memory" ]
        pinned   = "exception"
@@ -591,12 +602,14 @@ class Load(Op):
                        name      = "volatility",
                        comment   = "volatile loads are a visible side-effect and may not be optimized",
                        init      = "flags & cons_volatile ? volatility_is_volatile : volatility_non_volatile",
+                       to_flags  = "%s == volatility_is_volatile ? cons_volatile : 0"
                ),
                dict(
                        type      = "ir_align",
                        name      = "unaligned",
                        comment   = "pointers to unaligned loads don't need to respect the load-mode/type alignments",
                        init      = "flags & cons_unaligned ? align_non_aligned : align_is_aligned",
+                       to_flags  = "%s == align_non_aligned ? cons_unaligned : 0"
                ),
        ]
        attr_struct = "load_attr"
@@ -608,6 +621,7 @@ class Load(Op):
                ),
        ]
        pinned_init = "flags & cons_floats ? op_pin_state_floats : op_pin_state_pinned"
+       throws_init = "(flags & cons_throws_exception) != 0"
 
 class Minus(Unop):
        """returns the difference between its operands"""
@@ -617,6 +631,7 @@ 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
@@ -628,13 +643,12 @@ class Mod(Op):
                ("right", "second operand"),
        ]
        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"),
-               ("res",       "result of computation",                 "pn_Generic_other"),
+               ("M",         "memory result"),
+               ("res",       "result of computation"),
+               ("X_regular", "control flow when no exception occurs"),
+               ("X_except",  "control flow when exception occured"),
        ]
        flags = [ "fragile", "uses_memory" ]
-       attrs_name = "mod"
        attrs = [
                dict(
                        type    = "ir_mode*",
@@ -644,6 +658,7 @@ class Mod(Op):
        ]
        attr_struct = "mod_attr"
        pinned      = "exception"
+       throws_init = "false"
        op_index    = 1
        arity_override = "oparity_binary"
 
@@ -701,6 +716,7 @@ class Phi(Op):
           As we can't distinguish these easily we keep all of them alive. */
        if (is_Phi(res) && mode == mode_M)
                add_End_keepalive(get_irg_end(irg), res);'''
+       customSerializer = True
 
 class Pin(Op):
        """Pin the value of the node node in the current block. No users of the Pin
@@ -724,7 +740,6 @@ class Proj(Op):
        knownGraph       = True
        block            = "get_nodes_block(irn_pred)"
        graph            = "get_irn_irg(irn_pred)"
-       customSerializer = True
        attrs      = [
                dict(
                        type    = "long",
@@ -743,8 +758,8 @@ class Raise(Op):
                ("exo_ptr", "pointer to exception object to be thrown"),
        ]
        outs  = [
-               ("M", "memory result",                     "pn_Generic_M"),
-               ("X", "control flow to exception handler", "pn_Generic_X_regular"),
+               ("M", "memory result"),
+               ("X", "control flow to exception handler"),
        ]
        flags  = [ "highlevel", "cfopcode" ]
        pinned = "yes"
@@ -767,7 +782,10 @@ class Rotl(Binop):
 
 class Sel(Op):
        """Computes the address of a entity of a compound type given the base
-       address of an instance of the compound type."""
+       address of an instance of the compound type.
+
+       Optimisations assume that a Sel node can only produce a NULL pointer if the
+       ptr input was NULL."""
        ins    = [
                ("mem", "memory dependency"),
                ("ptr", "pointer to object to select from"),
@@ -814,7 +832,6 @@ class Start(Op):
        flags            = [ "cfopcode" ]
        singleton        = True
        knownBlock       = True
-       customSerializer = True
        block            = "get_irg_start_block(irg)"
 
 class Store(Op):
@@ -825,26 +842,29 @@ class Store(Op):
           ("value", "value to store"),
        ]
        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"),
+               ("M",         "memory result"),
+               ("X_regular", "control flow when no exception occurs"),
+               ("X_except",  "control flow when exception occured"),
        ]
        flags    = [ "fragile", "uses_memory" ]
        pinned   = "exception"
        attr_struct = "store_attr"
        pinned_init = "flags & cons_floats ? op_pin_state_floats : op_pin_state_pinned"
+       throws_init = "(flags & cons_throws_exception) != 0"
        attrs = [
                dict(
                        type      = "ir_volatility",
                        name      = "volatility",
                        comment   = "volatile stores are a visible side-effect and may not be optimized",
                        init      = "flags & cons_volatile ? volatility_is_volatile : volatility_non_volatile",
+                       to_flags  = "%s == volatility_is_volatile ? cons_volatile : 0"
                ),
                dict(
                        type      = "ir_align",
                        name      = "unaligned",
                        comment   = "pointers to unaligned stores don't need to respect the load-mode/type alignments",
                        init      = "flags & cons_unaligned ? align_non_aligned : align_is_aligned",
+                       to_flags  = "%s == align_non_aligned ? cons_unaligned : 0"
                ),
        ]
        constructor_args = [
@@ -862,21 +882,19 @@ class Sub(Binop):
 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."""
+        - *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