Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Zwinkau
libfirm
Commits
ce4907ea
Commit
ce4907ea
authored
Jan 13, 2015
by
Matthias Braun
Browse files
gen_ir: move ir opcode related things to irops.py
parent
f5bbd0f7
Changes
5
Hide whitespace changes
Inline
Side-by-side
Makefile
View file @
ce4907ea
...
...
@@ -114,7 +114,7 @@ IR_SPEC_GENERATED_INCLUDES := \
$(gendir)
/ir/ir/gen_irdump.c.inl
\
$(gendir)
/ir/ir/gen_irnode.h
IR_SPEC_GENERATOR
:=
$(srcdir)
/scripts/gen_ir.py
IR_SPEC_GENERATOR_DEPS
:=
$(IR_SPEC_GENERATOR)
$(srcdir)
/scripts/jinjautil.py
$(srcdir)
/scripts/
spec_util
.py
$(srcdir)
/scripts/filters.py
IR_SPEC_GENERATOR_DEPS
:=
$(IR_SPEC_GENERATOR)
$(srcdir)
/scripts/jinjautil.py
$(srcdir)
/scripts/
irops
.py
$(srcdir)
/scripts/filters.py
IR_SPEC
:=
$(srcdir)
/scripts/ir_spec.py
libfirm_BUILDDIRS
+=
$(gendir)
/include/libfirm
...
...
configure
View file @
ce4907ea
...
...
@@ -136,7 +136,7 @@ def specgen(out, template=None):
generator
=
"$srcdir/scripts/gen_ir.py"
specfile
=
"$srcdir/scripts/ir_spec.py"
deps
=
[
template
,
specfile
,
generator
,
"$srcdir/scripts/jinjautil.py"
,
"$srcdir/scripts/
spec_util
.py"
,
"$srcdir/scripts/filters.py"
]
"$srcdir/scripts/
irops
.py"
,
"$srcdir/scripts/filters.py"
]
return
build
(
"GEN_IR"
,
out
,
deps
,
specfile
=
specfile
,
template
=
template
,
generatortool
=
generator
)
...
...
scripts/gen_ir.py
View file @
ce4907ea
...
...
@@ -4,310 +4,11 @@
# Copyright (C) 2012 Karlsruhe Institute of Technology.
import
sys
import
argparse
from
datetime
import
datetime
from
jinja2
import
Environment
,
Template
from
jinjautil
import
export
,
export_filter
from
irops
import
prepare_nodes
,
load_spec
import
filters
import
irops
import
jinjautil
from
spec_util
import
is_dynamic_pinned
,
isAbstract
,
setdefault
,
load_spec
,
Attribute
from
filters
import
arguments
,
filtjoin
,
has
,
hasnot
def
parameterlist
(
parameterlist
):
return
"
\n
"
.
join
(
parameterlist
)
def
nodearguments
(
node
):
arguments
=
[
arg
.
name
for
arg
in
node
.
arguments
]
return
parameterlist
(
arguments
)
def
nodeparameters
(
node
):
parameters
=
[
"%s %s"
%
(
arg
.
type
,
arg
.
name
)
for
arg
in
node
.
arguments
]
return
parameterlist
(
parameters
)
def
nodeparametershelp
(
node
):
res
=
""
for
param
in
node
.
arguments
:
res
+=
" * @param %-9s %s
\n
"
%
(
param
.
name
,
param
.
comment
)
return
res
def
a_an
(
text
):
if
text
[
0
]
in
"aAeEuUoOiI"
:
return
"an "
+
text
return
"a "
+
text
def
blockparameter
(
node
):
if
not
node
.
block
:
return
"ir_node *block"
elif
node
.
usesGraph
:
return
"ir_graph *irg"
else
:
return
""
def
blockparameterhelp
(
node
):
if
not
node
.
block
:
return
" * @param block The IR block the node belongs to.
\n
"
elif
node
.
usesGraph
:
return
" * @param irg The IR graph the node belongs to.
\n
"
else
:
return
""
def
blockargument
(
node
):
if
not
node
.
block
:
return
"block"
elif
node
.
usesGraph
:
return
"irg"
else
:
return
""
def
blockassign
(
node
):
if
node
.
block
:
return
"ir_node *block = %s;"
%
node
.
block
else
:
return
""
def
irgassign
(
node
):
if
node
.
usesGraph
:
return
""
else
:
return
"ir_graph *irg = get_irn_irg(block);
\n
"
def
curblock
(
node
):
if
not
node
.
block
:
return
"get_cur_block()"
elif
node
.
usesGraph
:
return
"current_ir_graph"
else
:
return
""
def
insdecl
(
node
):
arity
=
node
.
arity
if
arity
==
"dynamic"
or
arity
==
"variable"
:
if
len
(
node
.
ins
)
==
0
:
return
""
insarity
=
len
(
node
.
ins
)
res
=
"int r_arity = arity + "
+
repr
(
insarity
)
+
";"
res
+=
"
\n\t
ir_node **r_in= ALLOCAN(ir_node*, r_arity);"
i
=
0
for
input
in
node
.
ins
:
res
+=
"
\n\t
r_in["
+
repr
(
i
)
+
"] = irn_"
+
input
.
name
+
";"
i
+=
1
res
+=
"
\n\t
memcpy(&r_in["
+
repr
(
insarity
)
+
"], in, sizeof(ir_node *) * arity);
\n\t
"
elif
arity
==
0
:
return
""
else
:
res
=
"ir_node *in["
+
repr
(
arity
)
+
"];"
i
=
0
for
input
in
node
.
ins
:
res
+=
"
\n\t
in["
+
repr
(
i
)
+
"] = irn_"
+
input
.
name
+
";"
i
+=
1
return
res
def
arity_and_ins
(
node
):
arity
=
node
.
arity
if
arity
==
"dynamic"
or
arity
==
"variable"
:
if
len
(
node
.
ins
)
==
0
:
return
"arity, in"
else
:
return
"r_arity, r_in"
elif
arity
==
0
:
return
"0, NULL"
else
:
return
repr
(
arity
)
+
", in"
def
arity
(
node
):
if
hasattr
(
node
,
"arity_override"
):
return
node
.
arity_override
arity
=
node
.
arity
if
arity
==
"dynamic"
:
return
"oparity_dynamic"
if
arity
==
"variable"
:
return
"oparity_variable"
return
"oparity_any"
def
pinned
(
node
):
pinned
=
node
.
pinned
if
pinned
==
"yes"
:
return
"op_pin_state_pinned"
if
pinned
==
"no"
:
return
"op_pin_state_floats"
if
pinned
==
"exception"
:
return
"op_pin_state_exc_pinned"
print
(
"WARNING: Unknown pinned state %s in format pined"
%
pinned
)
return
""
def
flags
(
node
):
flags
=
list
(
map
(
lambda
x
:
"irop_flag_"
+
x
,
node
.
flags
))
if
not
flags
:
flags
=
[
"irop_flag_none"
]
return
" | "
.
join
(
flags
)
def
stringformat
(
string
,
*
args
):
return
string
%
args
def
attr_size
(
node
):
if
not
hasattr
(
node
,
"attr_struct"
):
return
"0"
return
"sizeof(%s)"
%
node
.
attr_struct
def
opindex
(
node
):
if
hasattr
(
node
,
"op_index"
):
return
node
.
op_index
return
"-1"
keywords
=
frozenset
([
"true"
,
"false"
])
def
escape_keywords
(
word
):
if
word
in
keywords
:
return
word
+
"_"
return
word
def
parameters
(
string
):
return
arguments
(
string
,
voidwhenempty
=
True
)
def
args
(
arglist
):
argument_names
=
[
arg
.
name
for
arg
in
arglist
]
return
"
\n
"
.
join
(
argument_names
)
def
block
(
node
):
if
not
node
.
block
:
return
"block"
elif
node
.
usesGraph
:
return
"env->irg"
else
:
return
""
def
simplify_type
(
string
):
"""Returns a simplified version of a C type for use in a function name.
Stars are replaced with _ref, spaces removed and the ir_ firm namespace
prefix stripped."""
res
=
string
.
replace
(
"*"
,
"_ref"
).
replace
(
" "
,
""
)
if
res
.
startswith
(
"ir_"
):
res
=
res
[
3
:]
return
res
def
doxygrouplink
(
string
,
link
=
None
):
global
tags
if
link
==
None
:
link
=
string
if
tags
==
None
:
return
string
e
=
tags
.
xpath
(
"//compound[name/text()='%s']"
%
link
)
if
len
(
e
)
==
0
:
return
string
e
=
e
[
0
]
anchorfile
=
e
.
xpath
(
"filename/text()"
)
if
len
(
anchorfile
)
==
0
:
return
string
global
linkbase
return
"<a href=
\"
%s%s
\"
>%s</a>"
%
(
linkbase
,
anchorfile
[
0
],
string
)
tags
=
None
linkbase
=
None
def
doxylink
(
string
,
link
=
None
):
global
tags
if
link
==
None
:
link
=
string
if
tags
==
None
:
return
string
e
=
tags
.
xpath
(
"//tagfile/compound[name/text()='%s']"
%
link
)
if
len
(
e
)
==
0
:
return
string
e
=
e
[
0
]
anchorfile
=
e
.
xpath
(
"anchorfile/text()"
)
anchor
=
e
.
xpath
(
"anchor/text()"
)
if
len
(
anchorfile
)
==
0
or
len
(
anchor
)
==
0
:
return
string
global
linkbase
return
"<a href=
\"
%s%s#%s
\"
>%s</a>"
%
(
linkbase
,
anchorfile
[
0
],
anchor
[
0
],
string
)
def
docutils
(
string
):
import
docutils.writers.html4css1
import
docutils.core
writer
=
docutils
.
writers
.
html4css1
.
Writer
()
document
=
docutils
.
core
.
publish_parts
(
string
,
writer
=
writer
)[
'body'
]
return
document
def
parse_tagfile
(
filename
):
global
tags
tagfile
=
open
(
filename
)
try
:
from
lxml
import
etree
tags
=
etree
.
parse
(
tagfile
)
except
:
tags
=
None
for
f
in
[
a_an
,
args
,
arity_and_ins
,
arity
,
attr_size
,
blockargument
,
block
,
blockparameter
,
blockparameterhelp
,
curblock
,
escape_keywords
,
flags
,
insdecl
,
blockassign
,
irgassign
,
nodearguments
,
nodeparameters
,
nodeparametershelp
,
opindex
,
parameterlist
,
parameters
,
pinned
,
simplify_type
,
stringformat
,
docutils
,
doxylink
,
doxygrouplink
]:
export_filter
(
f
)
export
(
is_dynamic_pinned
)
def
preprocess_node
(
node
):
setdefault
(
node
,
"attrs_name"
,
node
.
name
.
lower
())
# construct node arguments
arguments
=
[
]
initattrs
=
[
]
for
input
in
node
.
ins
:
arguments
.
append
(
Attribute
(
"irn_"
+
input
.
name
,
type
=
"ir_node *"
,
comment
=
input
.
name
))
if
node
.
arity
==
"variable"
or
node
.
arity
==
"dynamic"
:
arguments
.
append
(
Attribute
(
"arity"
,
type
=
"int"
,
comment
=
"size of additional inputs array"
))
arguments
.
append
(
Attribute
(
"in"
,
type
=
"ir_node *const *"
,
comment
=
"additional inputs"
))
if
not
hasattr
(
node
,
"mode"
):
arguments
.
append
(
Attribute
(
"mode"
,
type
=
"ir_mode *"
,
comment
=
"mode of the operations result"
))
for
attr
in
node
.
attrs
:
if
attr
.
init
is
not
None
:
continue
arguments
.
append
(
attr
)
# dynamic pin state means more constructor arguments
if
is_dynamic_pinned
(
node
):
if
hasattr
(
node
,
"pinned_init"
):
initattrs
.
append
(
Attribute
(
"pin_state"
,
fqname
=
"exc.pin_state"
,
type
=
"op_pin_state"
,
init
=
node
.
pinned_init
))
else
:
node
.
constructor_args
.
append
(
Attribute
(
"pin_state"
,
type
=
"op_pin_state"
,
comment
=
"pinned state"
))
initattrs
.
append
(
Attribute
(
"pin_state"
,
fqname
=
"exc.pin_state"
,
type
=
"op_pin_state"
,
init
=
"pin_state"
))
if
hasattr
(
node
,
"throws_init"
):
initattrs
.
append
(
Attribute
(
"throws_exception"
,
fqname
=
"exc.throws_exception"
,
type
=
"unsigned"
,
init
=
node
.
throws_init
))
for
arg
in
node
.
constructor_args
:
arguments
.
append
(
arg
)
node
.
arguments
=
arguments
node
.
initattrs
=
initattrs
def
prepare_nodes
(
nodes
):
real_nodes
=
[]
abstract_nodes
=
[]
for
node
in
nodes
:
if
isAbstract
(
node
):
abstract_nodes
.
append
(
node
)
else
:
real_nodes
.
append
(
node
)
for
node
in
real_nodes
:
preprocess_node
(
node
)
return
(
real_nodes
,
abstract_nodes
)
def
main
(
argv
):
parser
=
argparse
.
ArgumentParser
(
description
=
'Generate code/docu from node specification'
,
add_help
=
True
)
...
...
scripts/ir_spec.py
View file @
ce4907ea
...
...
@@ -4,7 +4,7 @@
# Firm node specifications
# The comments are in (standard python) restructured text format and are used
# to generate documentation.
from
spec_util
import
abstract
,
op
,
Attribute
from
irops
import
abstract
,
op
,
Attribute
name
=
"ir"
...
...
scripts/
spec_util
.py
→
scripts/
irops
.py
View file @
ce4907ea
# This file is part of libFirm.
# Copyright (C) 2012 Karlsruhe Institute of Technology.
import
sys
import
imp
from
jinjautil
import
export_filter
,
export
from
jinja2._compat
import
string_types
from
filters
import
arguments
import
imp
import
sys
# Datastructures for specifying ir operation types.
abstracts
=
set
()
def
abstract
(
cls
):
abstracts
.
add
(
cls
)
return
cls
def
is
A
bstract
(
nodetype
):
def
is
_a
bstract
(
nodetype
):
return
nodetype
in
abstracts
def
op
(
cls
):
cls
.
__is_firm_op
=
True
# Without new-style classes it is hard to detect the inheritance hierarchy
# later.
assert
hasattr
(
cls
,
"__class__"
),
"must use new-style classes"
return
cls
def
is
O
p
(
nodetype
):
def
is
_o
p
(
nodetype
):
return
hasattr
(
nodetype
,
"__is_firm_op"
)
class
Attribute
(
object
):
...
...
@@ -29,34 +34,31 @@ class Attribute(object):
fqname
=
name
self
.
fqname
=
fqname
def
is_dynamic_pinned
(
node
):
return
node
.
pinned
==
"exception"
class
Operand
(
object
):
pass
def
is_fragile
(
node
):
return
hasattr
(
node
,
"flags"
)
and
"fragile"
in
node
.
flags
def
Input
(
name
,
comment
=
None
):
op
=
Operand
()
op
.
name
=
name
op
.
comment
=
comment
return
op
def
inout_contains
(
l
,
nam
e
):
for
entry
in
l
:
if
entry
.
name
=
=
name
:
return
True
return
False
def
Output
(
name
,
comment
=
Non
e
):
op
=
Operand
()
op
.
name
=
name
op
.
comment
=
comment
return
op
def
verify_node
(
node
):
if
node
.
pinned
not
in
[
"yes"
,
"no"
,
"exception"
]:
print
(
"%s: UNKNOWN PINNED MODE: %s"
%
(
node
.
name
,
node
.
pinned
))
if
not
hasattr
(
node
,
"flags"
):
if
not
isAbstract
(
node
):
print
(
"WARNING: no flags specified for %s
\n
"
%
node
.
name
)
elif
type
(
node
.
flags
)
!=
list
:
print
(
"ERROR: flags of %s not a list"
%
node
.
name
)
if
hasattr
(
node
,
"pinned_init"
)
and
not
is_dynamic_pinned
(
node
):
print
(
"ERROR: node %s has pinned_init attribute but is not marked as dynamically pinned"
%
node
.
name
)
if
hasattr
(
node
,
"flags"
)
and
"uses_memory"
in
node
.
flags
:
if
"uses_memory"
in
node
.
flags
:
if
not
inout_contains
(
node
.
ins
,
"mem"
):
print
(
"ERROR: memory op %s needs an input named 'mem'"
%
node
.
name
)
if
is_
fragile
(
node
)
:
if
"
fragile
"
in
node
.
flags
:
if
not
is_dynamic_pinned
(
node
):
print
(
"ERROR: fragile node %s must be dynamically pinned"
%
node
.
name
)
if
not
hasattr
(
node
,
"throws_init"
):
...
...
@@ -80,43 +82,12 @@ def setdefault(node, attr, val):
if
not
hasattr
(
node
,
attr
):
setattr
(
node
,
attr
,
val
)
class
Operand
(
object
):
pass
def
Input
(
name
,
comment
=
None
):
op
=
Operand
()
op
.
name
=
name
op
.
comment
=
comment
return
op
def
Output
(
name
,
comment
=
None
):
op
=
Operand
()
op
.
name
=
name
op
.
comment
=
comment
return
op
def
setnodedefaults
(
node
):
setldefault
(
node
,
"name"
,
node
.
__name__
)
setdefault
(
node
,
"pinned"
,
"no"
)
if
isAbstract
(
node
):
return
setdefault
(
node
,
"flags"
,
[])
setdefault
(
node
,
"ins"
,
[])
setdefault
(
node
,
"arity"
,
len
(
node
.
ins
))
setdefault
(
node
,
"attrs"
,
[])
setdefault
(
node
,
"constructor"
,
True
)
setdefault
(
node
,
"constructor_args"
,
[])
setdefault
(
node
,
"serializer"
,
node
.
constructor
)
setdefault
(
node
,
"block"
,
None
)
if
hasattr
(
node
,
"__doc__"
):
node
.
doc
=
trim_docstring
(
node
.
__doc__
)
else
:
node
.
doc
=
""
if
hasattr
(
node
,
"outs"
)
and
len
(
node
.
outs
)
>
1
:
node
.
mode
=
"mode_T"
if
"start_block"
in
node
.
flags
:
node
.
block
=
"get_irg_start_block(irg)"
setdefault
(
node
,
"usesGraph"
,
node
.
block
!=
None
)
# As a shortcut you can specify inputs either as a list of strings or
# as a list of (name, comment) tuples. Normalize it to Input objects
...
...
@@ -138,36 +109,21 @@ def setnodedefaults(node):
new_outs
.
append
(
o
)
node
.
outs
=
new_outs
def
collect_ops
(
moduledict
):
return
[
node
for
node
in
moduledict
.
values
()
if
isOp
(
node
)
]
def
setdefaults
(
nodes
):
for
node
in
nodes
:
setnodedefaults
(
node
)
return
nodes
def
verify_spec
(
spec
):
if
len
(
spec
.
nodes
)
==
0
:
sys
.
stderr
.
write
(
"Warning: No nodes found in spec
\n
"
)
if
not
hasattr
(
spec
,
"name"
):
sys
.
stderr
.
write
(
"Warning: No name specified in node spec
\n
"
)
def
load_spec
(
filename
):
module
=
imp
.
load_source
(
'spec'
,
filename
)
nodes
=
[]
for
x
in
module
.
__dict__
.
values
():
if
not
isOp
(
x
):
continue
setnodedefaults
(
x
)
verify_node
(
x
)
nodes
.
append
(
x
)
nodes
.
sort
(
key
=
lambda
x
:
x
.
name
)
module
.
nodes
=
nodes
if
len
(
nodes
)
==
0
:
print
(
"Warning: No nodes found in spec file '%s'"
%
filename
)
if
not
hasattr
(
module
,
"name"
):
print
(
"Warning: No name specified in file '%s'"
%
filename
)
return
module
setdefault
(
node
,
"attrs"
,
[])
setdefault
(
node
,
"constructor"
,
True
)
setdefault
(
node
,
"constructor_args"
,
[])
setdefault
(
node
,
"serializer"
,
node
.
constructor
)
setdefault
(
node
,
"block"
,
None
)
if
hasattr
(
node
,
"__doc__"
):
node
.
doc
=
trim_docstring
(
node
.
__doc__
)
else
:
node
.
doc
=
""
if
hasattr
(
node
,
"outs"
)
and
len
(
node
.
outs
)
>
1
:
node
.
mode
=
"mode_T"
if
"start_block"
in
node
.
flags
:
node
.
block
=
"get_irg_start_block(irg)"
if
not
is_abstract
(
node
):
setdefault
(
node
,
"usesGraph"
,
node
.
block
!=
None
)
def
trim_docstring
(
docstring
):
if
not
docstring
:
...
...
@@ -193,3 +149,341 @@ def trim_docstring(docstring):
trimmed
.
pop
(
0
)
# Return a single string:
return
'
\n
'
.
join
(
trimmed
)
def
parameterlist
(
parameterlist
):
return
"
\n
"
.
join
(
parameterlist
)
def
nodearguments
(
node
):
arguments
=
[
arg
.
name
for
arg
in
node
.
arguments
]
return
parameterlist
(
arguments
)
def
nodeparameters
(
node
):
parameters
=
[
"%s %s"
%
(
arg
.
type
,
arg
.
name
)
for
arg
in
node
.
arguments
]
return
parameterlist
(
parameters
)
def
nodeparametershelp
(
node
):
res
=
""
for
param
in
node
.
arguments
:
res
+=
" * @param %-9s %s
\n
"
%
(
param
.
name
,
param
.
comment
)
return
res
def
a_an
(
text
):
if
text
[
0
]
in
"aAeEuUoOiI"
:
return
"an "
+
text
return
"a "
+
text
def
blockparameter
(
node
):
if
not
node
.
block
:
return
"ir_node *block"
elif
node
.
usesGraph
:
return
"ir_graph *irg"
else
:
return
""
def
blockparameterhelp
(
node
):
if
not
node
.
block
:
return
" * @param block The IR block the node belongs to.
\n
"
elif
node
.
usesGraph
:
return
" * @param irg The IR graph the node belongs to.
\n
"
else
:
return
""
def
blockargument
(
node
):
if
not
node
.
block
:
return
"block"
elif
node
.
usesGraph
:
return
"irg"
else
:
return
""
def
blockassign
(
node
):
if
node
.
block
:
return
"ir_node *block = %s;"
%
node
.
block
else
:
return
""
def
irgassign
(
node
):
if
node
.
usesGraph
:
return
""
else
:
return
"ir_graph *irg = get_irn_irg(block);
\n
"
def
curblock
(
node
):
if
not
node
.
block
:
return
"get_cur_block()"
elif
node
.
usesGraph
:
return
"current_ir_graph"
else
:
return
""
def
insdecl
(
node
):
arity
=
node
.
arity
if
arity
==
"dynamic"
or
arity
==
"variable"
:
if
len
(
node
.
ins
)
==
0
:
return
""
insarity
=
len
(
node
.
ins
)
res
=
"int r_arity = arity + "
+
repr
(
insarity
)
+
";"
res
+=
"
\n\t
ir_node **r_in= ALLOCAN(ir_node*, r_arity);"
i
=
0
for
input
in
node
.
ins
:
res
+=
"
\n\t
r_in["
+
repr
(
i
)
+
"] = irn_"
+
input
.
name
+
";"
i
+=
1
res
+=
"
\n\t
memcpy(&r_in["
+
repr
(
insarity
)
+
"], in, sizeof(ir_node *) * arity);
\n\t
"
elif
arity
==
0
:
return
""
else
:
res
=
"ir_node *in["
+
repr
(
arity
)
+
"];"
i
=
0
for
input
in
node
.
ins
:
res
+=
"
\n\t
in["
+
repr
(
i
)
+
"] = irn_"
+
input
.
name
+
";"
i
+=
1
return
res
def
arity_and_ins
(
node
):
arity
=
node
.
arity