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