gen_docu: fix missing attributes, show generation time at the end
[libfirm] / scripts / gen_ir_io.py
1 #!/usr/bin/env python
2 import sys
3 import re
4 from jinja2 import Environment, Template
5 from jinja2.filters import do_dictsort
6 from spec_util import is_dynamic_pinned, verify_node, isAbstract
7 import ir_spec
8
9 def error(msg):
10         """writes an error message to stderr"""
11         sys.stderr.write("Error: " + msg + "\n");
12
13 def warning(msg):
14         """writes a warning message to stderr"""
15         sys.stderr.write("Warning: " + msg + "\n");
16
17 def format_args(arglist):
18         return "\n".join(arglist)
19
20 def format_ifnset(string, node, key):
21         if hasattr(node, key):
22                 return ""
23         return string
24
25 def format_block(node):
26         if hasattr(node, "knownBlock"):
27                 if hasattr(node, "knownGraph"):
28                         return ""
29                 return "irg"
30         else:
31                 return "preds[0]"
32
33 def format_arguments(string):
34         args = re.split('\s*\n\s*', string)
35         if args[0] == '':
36                 args = args[1:]
37         if len(args) > 0 and args[-1] == '':
38                 args = args[:-1]
39         return ", ".join(args)
40
41 env = Environment()
42 env.filters['args']      = format_args
43 env.filters['ifnset']    = format_ifnset
44 env.filters['block']     = format_block
45 env.filters['arguments'] = format_arguments
46
47 def get_io_type(type, attrname, node):
48         if type == "ir_tarval*":
49                 importcmd = "ir_tarval *%s = read_tv(env);" % attrname
50                 exportcmd = "write_tarval(env, %(val)s);";
51         elif type == "ir_mode*":
52                 importcmd = "ir_mode *%s = read_mode(env);" % attrname
53                 exportcmd = "write_mode(env, %(val)s);"
54         elif type == "ir_entity*":
55                 importcmd = "ir_entity *%s = read_entity(env);" % attrname
56                 exportcmd = "write_entity_ref(env, %(val)s);"
57         elif type == "ir_type*":
58                 importcmd = "ir_type *%s = read_type(env);" % attrname
59                 exportcmd = "write_type_ref(env, %(val)s);"
60         elif type == "long" and node.name == "Proj":
61                 importcmd = "long %s = read_long(env);" % attrname
62                 exportcmd = "write_long(env, %(val)s);"
63         elif type == "ir_relation" or type == "ir_where_alloc":
64                 importcmd = "%s %s = (%s) read_long(env);" % (type, attrname, type)
65                 exportcmd = "write_long(env, (long) %(val)s);"
66         elif type == "ir_align":
67                 importcmd = "ir_align %s = read_align(env);" % attrname
68                 exportcmd = "write_align(env, %(val)s);"
69         elif type == "ir_volatility":
70                 importcmd = "ir_volatility %s = read_volatility(env);" % attrname
71                 exportcmd = "write_volatility(env, %(val)s);"
72         elif type == "ir_cons_flags":
73                 importcmd = "ir_cons_flags %s = cons_none;" % attrname
74                 exportcmd = "" # can't really export cons_flags
75         elif type == "op_pin_state":
76                 importcmd = "op_pin_state %s = read_pin_state(env);" % attrname
77                 exportcmd = "write_pin_state(env, irn);"
78         elif type == "ir_builtin_kind":
79                 importcmd = "ir_builtin_kind %s = read_builtin_kind(env);" % attrname
80                 exportcmd = "write_builtin_kind(env, irn);"
81         elif type == "cond_kind":
82                 importcmd = "cond_kind %s = read_cond_kind(env);" % attrname
83                 exportcmd = "write_cond_kind(env, irn);"
84         elif type == "cond_jmp_predicate":
85                 importcmd = "cond_jmp_predicate %s = read_cond_jmp_predicate(env);" % attrname
86                 exportcmd = "write_cond_jmp_predicate(env, irn);"
87         elif type == "int":
88                 importcmd = "int %s = read_int(env);" % attrname
89                 exportcmd = "write_int(env, %(val)s);"
90         elif type == "unsigned":
91                 importcmd = "unsigned %s = read_unsigned(env);" % attrname
92                 exportcmd = "write_unsigned(env, %(val)s);"
93         elif type == "long":
94                 importcmd = "long %s = read_long(env);" % attrname
95                 exportcmd = "write_long(env, %(val)s);"
96         else:
97                 warning("cannot generate import/export for node %s: unsupported attribute type: %s" % (node.name, type))
98                 importcmd = """// BAD: %s %s
99                         %s %s = (%s) 0;""" % (type, attrname, type, attrname, type)
100                 exportcmd = "// BAD: %s" % type
101         return (importcmd, exportcmd)
102
103 def prepare_attr(node, attr):
104         (importcmd,exportcmd) = get_io_type(attr["type"], attr["name"], node)
105         attr["importcmd"] = importcmd
106         attr["exportcmd"] = exportcmd % {"val": "get_%s_%s(irn)" % (node.name, attr["name"])}
107
108
109 def preprocess_node(node):
110         # dynamic pin state means, we have to im/export that
111         if is_dynamic_pinned(node):
112                 newattr = dict(
113                         name = "state",
114                         type = "op_pin_state"
115                 )
116                 if hasattr(node, "pinned_init"):
117                         newattr["init"] = node.pinned_init
118                 node.attrs.append(newattr)
119
120         verify_node(node)
121
122         # construct node arguments
123         arguments = [ ]
124         initargs = [ ]
125         i = 1
126         for input in node.ins:
127                 arguments.append("preds[%i]" % i)
128                 i += 1
129
130         if node.arity == "variable" or node.arity == "dynamic":
131                 arguments.append("numpreds - %i" % i)
132                 arguments.append("preds + %i" % i)
133
134         if not hasattr(node, "mode"):
135                 arguments.append("mode")
136
137         for attr in node.attrs:
138                 prepare_attr(node, attr)
139                 if "init" in attr:
140                         if attr["type"] == "op_pin_state":
141                                 initfunc = "set_irn_pinned"
142                         else:
143                                 initfunc = "set_" + node.name + "_" + attr["name"]
144                         initargs.append((attr["name"], initfunc))
145                 else:
146                         arguments.append(attr["name"])
147
148         for arg in node.constructor_args:
149                 prepare_attr(node, arg)
150                 arguments.append(arg["name"])
151
152         node.arguments = arguments
153         node.initargs = initargs
154
155 export_attrs_template = env.from_string('''
156         case iro_{{node.name}}:
157                 {{"write_mode(env, get_irn_mode(irn));"|ifnset(node,"mode")}}
158                 {% for attr in node.attrs %}{{attr.exportcmd}}
159                 {% endfor %}
160                 {% for attr in node.constructor_args %}{{attr.exportcmd}}
161                 {% endfor %}break;''')
162
163 import_attrs_template = env.from_string('''
164         case iro_{{node.name}}: {
165                 {{"ir_mode *mode = read_mode(env);"|ifnset(node,"mode")}}
166                 {% for attr in node.attrs %}
167                 {{attr.importcmd}}
168                 {% endfor -%}
169                 {% for attr in node.constructor_args %}
170                 {{attr.importcmd}}
171                 {% endfor -%}
172                 newnode = new_r_{{node.name}}(
173 {%- filter arguments %}
174 {{node|block}}
175 {{node.arguments|args}}
176 {% endfilter %});
177                 {% for (initarg, initfunc) in node.initargs %}
178                 {{initfunc}}(newnode, {{initarg}});
179                 {% endfor -%}
180                 break;
181         }
182 ''')
183
184 def main(argv):
185         """the main function"""
186
187         if len(argv) < 3:
188                 print "usage: %s specname(ignored) destdirectory" % argv[0]
189                 sys.exit(1)
190
191         gendir = argv[2]
192
193         real_nodes = []
194         for node in ir_spec.nodes:
195                 if isAbstract(node):
196                         continue
197                 real_nodes.append(node)
198
199         file = open(gendir + "/gen_irio_export.inl", "w");
200         file.write("/* Warning: automatically generated code */")
201         for node in real_nodes:
202                 if node.customSerializer:
203                         continue
204
205                 preprocess_node(node)
206                 file.write(export_attrs_template.render(vars()))
207         file.write("\n")
208         file.close()
209
210         file = open(gendir + "/gen_irio_import.inl", "w");
211         file.write("/* Warning: automatically generated code */")
212         for node in real_nodes:
213                 if node.customSerializer:
214                         continue
215                 file.write(import_attrs_template.render(vars()))
216         file.write("\n")
217         file.close()
218
219         file = open(gendir + "/gen_irio_lex.inl", "w");
220         file.write("/* Warning: automatically generated code */")
221         for node in real_nodes:
222                 file.write("\tINSERT(tt_iro, \"%s\", iro_%s);\n" % (node.name, node.name));
223         file.close()
224
225 main(sys.argv)