- updated exchange_types() to use the new type flags
[libfirm] / scripts / gen_ir_io.py
1 #!/usr/bin/env python
2 import sys
3 from jinja2 import Environment, Template
4 from jinja2.filters import do_dictsort
5 import ir_spec
6
7 def format_args(arglist):
8         #argstrings = map(lambda arg : arg["name"], arglist)
9         #return ", ".join(argstrings)
10         s = ", ".join(arglist)
11         if len(s) == 0:
12           return "";
13         return ", " + s;
14
15 def format_ifnset(string, node, key):
16         if key in node:
17                 return ""
18         return string
19
20 def format_block(node):
21         if node.get("knownBlock"):
22                 return ""
23         else:
24                 return ", get_node(env, preds[0])"
25
26 env = Environment()
27 env.filters['args']   = format_args
28 env.filters['ifnset'] = format_ifnset
29 env.filters['block']  = format_block
30
31 def get_io_type(type, attrname, nodename):
32         if type == "tarval*":
33                 importcmd = "tarval *%s = read_tv(env);" % attrname
34                 exportcmd = "write_tarval(env, %(val)s);";
35         elif type == "ir_mode*":
36                 importcmd = "ir_mode *%s = read_mode(env);" % attrname
37                 exportcmd = "write_mode(env, %(val)s);"
38         elif type == "ir_entity*":
39                 importcmd = "ir_entity *%s = read_entity(env);" % attrname
40                 exportcmd = """fprintf(env->file, "%%ld ", get_entity_nr(%(val)s));"""
41         elif type == "ir_type*":
42                 importcmd = "ir_type *%s = read_type(env);" % attrname
43                 exportcmd = """fprintf(env->file, "%%ld ", get_type_nr(%(val)s));"""
44         elif type == "long" and nodename == "Proj":
45                 importcmd = "long %s = read_long(env);" % attrname
46                 exportcmd = """fprintf(env->file, "%%ld ", %(val)s);"""
47         elif type == "pn_Cmp" or type == "ir_where_alloc":
48                 importcmd = "%s %s = (%s) read_long(env);" % (type, attrname, type)
49                 exportcmd = """fprintf(env->file, "%%ld ", (long) %(val)s);"""
50         elif type == "ir_cons_flags" and nodename == "Store":
51                 importcmd = "ir_cons_flags %s = get_cons_flags(env);" % attrname
52                 exportcmd = """write_pin_state(env, irn);
53                         write_volatility(env, irn);
54                         write_align(env, irn);"""
55         elif type == "ir_cons_flags" and nodename == "Load":
56                 importcmd = "ir_cons_flags %s = get_cons_flags(env);" % attrname
57                 exportcmd = """write_pin_state(env, irn);
58                         write_volatility(env, irn);
59                         write_align(env, irn);"""
60         elif type == "op_pin_state":
61                 importcmd = "op_pin_state %s = read_pin_state(env);" % attrname
62                 exportcmd = "write_pin_state(env, irn);"
63         elif type == "ir_builtin_kind":
64                 importcmd = "ir_builtin_kind %s = read_builtin_kind(env);" % attrname
65                 exportcmd = "write_builtin_kind(env, irn);"
66         elif type == "cond_kind":
67                 importcmd = "cond_kind %s = read_cond_kind(env);" % attrname
68                 exportcmd = "write_cond_kind(env, irn);"
69         elif type == "cond_jmp_predicate":
70                 importcmd = "cond_jmp_predicate %s = read_cond_jmp_predicate(env);" % attrname
71                 exportcmd = "write_cond_jmp_predicate(env, irn);"
72         elif type == "int":
73                 importcmd = "int %s = (int) read_long(env);" % attrname
74                 exportcmd = """fprintf(env->file, "%%d ", %(val)s);"""
75         elif type == "long":
76                 importcmd = "long %s = read_long(env);" % attrname
77                 exportcmd = """fprintf(env->file, "%%ld ", %(val)s);"""
78         else:
79                 print "UNKNOWN TYPE: %s" % type
80                 importcmd = """// BAD: %s %s
81                         %s %s = (%s) 0;""" % (type, attrname, type, attrname, type)
82                 exportcmd = "// BAD: %s" % type
83         return (importcmd, exportcmd)
84
85 """     if type == "ir_type*":
86                 java_type    = "firm.Type"
87                 wrap_type    = "Pointer"
88                 to_wrapper   = "%s.ptr"
89                 from_wrapper = "firm.Type.createWrapper(%s)"
90         elif type == "ir_mode*":
91                 java_type    = "firm.Mode"
92                 wrap_type    = "Pointer"
93                 to_wrapper   = "%s.ptr"
94                 from_wrapper = "new firm.Mode(%s)"
95         elif type == "tarval*":
96                 java_type    = "firm.TargetValue"
97                 wrap_type    = "Pointer"
98                 to_wrapper   = "%s.ptr"
99                 from_wrapper = "new firm.TargetValue(%s)"
100         elif type == "pn_Cmp":
101                 java_type    = "int"
102                 wrap_type    = "int"
103                 to_wrapper   = "%s"
104                 from_wrapper = "%s"
105         elif type == "long":
106                 java_type    = "int"
107                 wrap_type    = "com.sun.jna.NativeLong"
108                 to_wrapper   = "new com.sun.jna.NativeLong(%s)"
109                 from_wrapper = "%s.intValue()"
110         elif type == "cons_flags":
111                 java_type    = "firm.bindings.binding_ircons.ir_cons_flags"
112                 wrap_type    = "int"
113                 to_wrapper   = "%s.val"
114                 from_wrapper = "firm.bindings.binding_ircons.ir_cons_flags.getEnum(%s)"
115         elif type == "ir_where_alloc":
116                 java_type    = "firm.bindings.binding_ircons.ir_where_alloc"
117                 wrap_type    = "int"
118                 to_wrapper   = "%s.val"
119                 from_wrapper = "firm.bindings.binding_ircons.ir_where_alloc.getEnum(%s)"
120         elif type == "ir_entity*":
121                 java_type    = "firm.Entity"
122                 wrap_type    = "Pointer"
123                 to_wrapper   = "%s.ptr"
124                 from_wrapper = "new firm.Entity(%s)"
125         else:
126                 print "UNKNOWN TYPE"
127                 java_type    = "BAD"
128                 wrap_type    = "BAD"
129                 to_wrapper   = "BAD"
130                 from_wrapper = "BAD"
131         return (java_type,wrap_type,to_wrapper,from_wrapper)"""
132
133 def prepare_attr(nodename, attr):
134         (importcmd,exportcmd) = get_io_type(attr["type"], attr["name"], nodename)
135         attr["importcmd"] = importcmd
136         attr["exportcmd"] = exportcmd % {"val": "get_%s_%s(irn)" % (nodename, attr["name"])}
137
138 def preprocess_node(nodename, node):
139         if "is_a" in node:
140                 parent = ir_spec.nodes[node["is_a"]]
141                 node["ins"] = parent["ins"]
142                 if "outs" in parent:
143                         node["outs"] = parent["outs"]
144         if "ins" not in node:
145                 node["ins"] = []
146         if "outs" in node:
147                 node["mode"] = "mode_T"
148         if "arity" not in node:
149                 node["arity"] = len(node["ins"])
150         if "attrs" not in node:
151                 node["attrs"] = []
152         if "constructor_args" not in node:
153                 node["constructor_args"] = []
154
155         # construct node arguments
156         arguments = [ ]
157         initargs = [ ]
158         specialconstrs = [ ]
159         i = 0
160         for input in node["ins"]:
161                 arguments.append("prednodes[%i]" % i)
162                 i += 1
163
164         # Special case for Builtin...
165         if nodename == "Builtin":
166                 for attr in node["attrs"]:
167                         if attr["name"] == "kind":
168                                 prepare_attr(nodename, attr)
169                                 arguments.append(attr["name"])
170
171         if node["arity"] == "variable" or node["arity"] == "dynamic":
172                 arguments.append("numpreds - %i" % (i + 1))
173                 arguments.append("prednodes + %i" % i)
174
175         if "mode" not in node:
176                 arguments.append("mode")
177
178         attrs_with_special = 0
179         for attr in node["attrs"]:
180                 if nodename == "Builtin" and attr["name"] == "kind":
181                         continue
182                 prepare_attr(nodename, attr)
183                 if "special" in attr:
184                         if not "init" in attr:
185                                 print "Node type %s has an attribute with a \"special\" entry but without \"init\"" % nodename
186                                 sys.exit(1)
187
188                         if attrs_with_special != 0:
189                                 print "Node type %s has more than one attribute with a \"special\" entry" % nodename
190                                 sys.exit(1)
191
192                         attrs_with_special += 1
193
194                         if "prefix" in attr["special"]:
195                                 specialname = attr["special"]["prefix"] + nodename
196                         elif "suffix" in attr["special"]:
197                                 specialname = nodename + attr["special"]["suffix"]
198                         else:
199                                 print "Unknown special constructor type for node type %s" %nodename
200                                 sys.exit(1)
201
202                         specialconstrs.append(
203                                 dict(
204                                         constrname = specialname,
205                                         attrname = attr["name"],
206                                         value = attr["special"]["init"]
207                                 )
208                         )
209                 elif "init" in attr:
210                         if attr["type"] == "op_pin_state":
211                                 initfunc = "set_irn_pinned"
212                         else:
213                                 initfunc = "set_" + nodename + "_" + attr["name"]
214                         initargs.append((attr["name"], initfunc))
215                 else:
216                         arguments.append(attr["name"])
217
218         for arg in node["constructor_args"]:
219                 prepare_attr(nodename, arg)
220                 arguments.append(arg["name"])
221
222         node["arguments"] = arguments
223         node["initargs"] = initargs
224         node["special_constructors"] = specialconstrs
225
226 export_attrs_template = env.from_string('''
227         case iro_{{nodename}}:
228                 {{"write_mode(env, get_irn_mode(irn));"|ifnset(node,"mode")}}
229                 {% for attr in node.attrs %}{{attr.exportcmd}}
230                 {% endfor %}
231                 {% for attr in node.constructor_args %}{{attr.exportcmd}}
232                 {% endfor %}break;''')
233
234 import_attrs_template = env.from_string('''
235         case iro_{{nodename}}:
236         {
237                 {{"ir_mode *mode = read_mode(env);"|ifnset(node,"mode")}}
238                 {% for attr in node.attrs %}{{attr.importcmd}}
239                 {% endfor %}
240                 {% for attr in node.constructor_args %}{{attr.importcmd}}
241                 {% endfor %}
242                 {% for special in node.special_constructors %}if({{special.attrname}} == {{special.value}})
243                         newnode = new_r_{{special.constrname}}(current_ir_graph{{node|block}}{{node["arguments"]|args}});
244                 else{% endfor %}
245                 newnode = new_r_{{nodename}}(current_ir_graph{{node|block}}{{node["arguments"]|args}});
246                 {% for (initarg, initfunc) in node.initargs %}{{initfunc}}(newnode, {{initarg}});
247                 {% endfor %}
248                 break;
249         }
250 ''')
251
252 def main(argv):
253         """the main function"""
254
255         if len(argv) < 3:
256                 print "usage: %s specname(ignored) destdirectory" % argv[0]
257                 sys.exit(1)
258
259         gendir = argv[2]
260
261         sortednodes = do_dictsort(ir_spec.nodes)
262
263         file = open(gendir + "/gen_irio_export.inl", "w");
264         for nodename, node in sortednodes:
265                 preprocess_node(nodename, node)
266                 if not "abstract" in node:
267                         file.write(export_attrs_template.render(vars()))
268         file.write("\n")
269         file.close()
270
271         file = open(gendir + "/gen_irio_import.inl", "w");
272         for nodename, node in sortednodes:
273                 if not "abstract" in node and nodename != "Start" and nodename != "End" and nodename != "Anchor" and nodename != "SymConst" and nodename != "Block":
274                         file.write(import_attrs_template.render(vars()))
275         # TODO: SymConst
276         file.write("\n")
277         file.close()
278
279         file = open(gendir + "/gen_irio_lex.inl", "w");
280         for nodename, node in sortednodes:
281                 if not "abstract" in node:
282                         file.write("\tINSERT(\"" + nodename + "\", tt_iro, iro_" + nodename + ");\n");
283         file.close()
284
285 if __name__ == "__main__":
286         main(sys.argv)