Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Zwinkau
libfirm
Commits
b50ba7aa
Commit
b50ba7aa
authored
Jan 08, 2011
by
Matthias Braun
Browse files
put node descriptions into the spec file
[r28232]
parent
1005c3d7
Changes
1
Hide whitespace changes
Inline
Side-by-side
scripts/ir_spec.py
View file @
b50ba7aa
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)"
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment