Commit b50ba7aa authored by Matthias Braun's avatar Matthias Braun
Browse files

put node descriptions into the spec file

[r28232]
parent 1005c3d7
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)"
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment