- remove block parameter from new_r_Proj and new_rd_Proj
[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 "current_ir_graph"
30         else:
31                 return "get_node(env, 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 == "tarval*":
49                 importcmd = "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 = """fprintf(env->file, "%%ld ", get_entity_nr(%(val)s));"""
57         elif type == "ir_type*":
58                 importcmd = "ir_type *%s = read_type(env);" % attrname
59                 exportcmd = """fprintf(env->file, "%%ld ", get_type_nr(%(val)s));"""
60         elif type == "long" and node.name == "Proj":
61                 importcmd = "long %s = read_long(env);" % attrname
62                 exportcmd = """fprintf(env->file, "%%ld ", %(val)s);"""
63         elif type == "pn_Cmp" or type == "ir_where_alloc":
64                 importcmd = "%s %s = (%s) read_long(env);" % (type, attrname, type)
65                 exportcmd = """fprintf(env->file, "%%ld ", (long) %(val)s);"""
66         elif type == "ir_cons_flags" and node.name == "Store":
67                 importcmd = "ir_cons_flags %s = get_cons_flags(env);" % attrname
68                 exportcmd = """write_pin_state(env, irn);
69                         write_volatility(env, irn);
70                         write_align(env, irn);"""
71         elif type == "ir_cons_flags" and node.name == "Load":
72                 importcmd = "ir_cons_flags %s = get_cons_flags(env);" % attrname
73                 exportcmd = """write_pin_state(env, irn);
74                         write_volatility(env, irn);
75                         write_align(env, irn);"""
76         elif type == "op_pin_state":
77                 importcmd = "op_pin_state %s = read_pin_state(env);" % attrname
78                 exportcmd = "write_pin_state(env, irn);"
79         elif type == "ir_builtin_kind":
80                 importcmd = "ir_builtin_kind %s = read_builtin_kind(env);" % attrname
81                 exportcmd = "write_builtin_kind(env, irn);"
82         elif type == "cond_kind":
83                 importcmd = "cond_kind %s = read_cond_kind(env);" % attrname
84                 exportcmd = "write_cond_kind(env, irn);"
85         elif type == "cond_jmp_predicate":
86                 importcmd = "cond_jmp_predicate %s = read_cond_jmp_predicate(env);" % attrname
87                 exportcmd = "write_cond_jmp_predicate(env, irn);"
88         elif type == "int":
89                 importcmd = "int %s = (int) read_long(env);" % attrname
90                 exportcmd = """fprintf(env->file, "%%d ", %(val)s);"""
91         elif type == "unsigned":
92                 importcmd = "unsigned %s = (unsigned) read_long(env);" % attrname
93                 exportcmd = """fprintf(env->file, "%%u ", %(val)s);"""
94         elif type == "long":
95                 importcmd = "long %s = read_long(env);" % attrname
96                 exportcmd = """fprintf(env->file, "%%ld ", %(val)s);"""
97         else:
98                 error("cannot generate import/export for node %s: unsupported attribute type: %s" % (node.name, type))
99                 importcmd = """// BAD: %s %s
100                         %s %s = (%s) 0;""" % (type, attrname, type, attrname, type)
101                 exportcmd = "// BAD: %s" % type
102         return (importcmd, exportcmd)
103
104 def prepare_attr(node, attr):
105         (importcmd,exportcmd) = get_io_type(attr["type"], attr["name"], node)
106         attr["importcmd"] = importcmd
107         attr["exportcmd"] = exportcmd % {"val": "get_%s_%s(irn)" % (node.name, attr["name"])}
108
109
110 def preprocess_node(node):
111         # dynamic pin state means, we have to im/export that
112         if is_dynamic_pinned(node):
113                 newattr = dict(
114                         name = "state",
115                         type = "op_pin_state"
116                 )
117                 if hasattr(node, "pinned_init"):
118                         newattr["init"] = node.pinned_init
119                 node.attrs.append(newattr)
120
121         verify_node(node)
122
123         # construct node arguments
124         arguments = [ ]
125         initargs = [ ]
126         specialconstrs = [ ]
127         i = 0
128         for input in node.ins:
129                 arguments.append("prednodes[%i]" % i)
130                 i += 1
131
132         if node.arity == "variable" or node.arity == "dynamic":
133                 arguments.append("numpreds - %i" % (i + 1))
134                 arguments.append("prednodes + %i" % i)
135
136         if not hasattr(node, "mode"):
137                 arguments.append("mode")
138
139         attrs_with_special = 0
140         for attr in node.attrs:
141                 prepare_attr(node, attr)
142                 if "special" in attr:
143                         if not "init" in attr:
144                                 warning("Node type %s has an attribute with a \"special\" entry but without \"init\"" % node.name)
145                                 sys.exit(1)
146
147                         if attrs_with_special != 0:
148                                 warning("Node type %s has more than one attribute with a \"special\" entry" % node.name)
149                                 sys.exit(1)
150
151                         attrs_with_special += 1
152
153                         if "prefix" in attr["special"]:
154                                 specialname = attr["special"]["prefix"] + node.name
155                         elif "suffix" in attr["special"]:
156                                 specialname = node.name + attr["special"]["suffix"]
157                         else:
158                                 error("Unknown special constructor type for node type %s" % node.name)
159                                 sys.exit(1)
160
161                         specialconstrs.append(
162                                 dict(
163                                         constrname = specialname,
164                                         attrname = attr["name"],
165                                         value = attr["special"]["init"]
166                                 )
167                         )
168                 elif "init" in attr:
169                         if attr["type"] == "op_pin_state":
170                                 initfunc = "set_irn_pinned"
171                         else:
172                                 initfunc = "set_" + node.name + "_" + attr["name"]
173                         initargs.append((attr["name"], initfunc))
174                 else:
175                         arguments.append(attr["name"])
176
177         for arg in node.constructor_args:
178                 prepare_attr(node, arg)
179                 arguments.append(arg["name"])
180
181         node.arguments = arguments
182         node.initargs = initargs
183         node.special_constructors = specialconstrs
184
185 export_attrs_template = env.from_string('''
186         case iro_{{node.name}}:
187                 {{"write_mode(env, get_irn_mode(irn));"|ifnset(node,"mode")}}
188                 {% for attr in node.attrs %}{{attr.exportcmd}}
189                 {% endfor %}
190                 {% for attr in node.constructor_args %}{{attr.exportcmd}}
191                 {% endfor %}break;''')
192
193 import_attrs_template = env.from_string('''
194         case iro_{{node.name}}: {
195                 {{"ir_mode *mode = read_mode(env);"|ifnset(node,"mode")}}
196                 {% for attr in node.attrs %}
197                 {{attr.importcmd}}
198                 {% endfor -%}
199                 {% for attr in node.constructor_args %}
200                 {{attr.importcmd}}
201                 {% endfor -%}
202                 {% for special in node.special_constructors %}
203                 if ({{special.attrname}} == {{special.value}})
204                         newnode = new_r_{{special.constrname}}(
205 {%- filter arguments %}
206 {{node|block}}
207 {{node.arguments|args}}
208 {% endfilter %});
209                 else
210                 {% endfor -%}
211                 newnode = new_r_{{node.name}}(
212 {%- filter arguments %}
213 {{node|block}}
214 {{node.arguments|args}}
215 {% endfilter %});
216                 {% for (initarg, initfunc) in node.initargs %}
217                 {{initfunc}}(newnode, {{initarg}});
218                 {% endfor -%}
219                 break;
220         }
221 ''')
222
223 def main(argv):
224         """the main function"""
225
226         if len(argv) < 3:
227                 print "usage: %s specname(ignored) destdirectory" % argv[0]
228                 sys.exit(1)
229
230         gendir = argv[2]
231         # these nodes don't work correctly yet for some reasons...
232         niynodes = [ "EndExcept", "EndReg", "ASM" ]
233         # these have custom im-/export code
234         customcode = [ "Start", "End", "Anchor", "SymConst", "Block" ]
235
236         real_nodes = []
237         for node in ir_spec.nodes:
238                 if isAbstract(node):
239                         continue
240                 real_nodes.append(node)
241
242         file = open(gendir + "/gen_irio_export.inl", "w");
243         for node in real_nodes:
244                 if node.__name__ in niynodes:
245                         continue
246
247                 preprocess_node(node)
248                 file.write(export_attrs_template.render(vars()))
249         file.write("\n")
250         file.close()
251
252         file = open(gendir + "/gen_irio_import.inl", "w");
253         for node in real_nodes:
254                 if node.name in customcode or node.name in niynodes:
255                         continue
256                 file.write(import_attrs_template.render(vars()))
257         file.write("\n")
258         file.close()
259
260         file = open(gendir + "/gen_irio_lex.inl", "w");
261         for node in real_nodes:
262                 if node.name in niynodes:
263                         continue
264                 file.write("\tINSERT(tt_iro, \"%s\", iro_%s);\n" % (node.name, node.name));
265         file.close()
266
267 main(sys.argv)