- Fix some more stuff in ir_spec.py
[libfirm] / scripts / gen_ir.py
1 #!/usr/bin/env python
2 import sys
3 from jinja2 import Environment, Template
4 from jinja2.filters import do_dictsort
5 from spec_util import is_dynamic_pinned, verify_node
6 import ir_spec
7
8 def format_argdecls(node, first = False, voidwhenempty = False):
9         if not node.has_key("args") or len(node["args"]) == 0:
10                 if voidwhenempty:
11                         return "void"
12                 else:
13                         return ""
14
15         res = ""
16         if not first:
17                 comma = ", "
18         else:
19                 comma = ""
20         for arg in node["args"]:
21                 res = res + (comma + arg["type"] + " " + arg["name"])
22                 comma = ", "
23         return res
24
25 def format_args(node, first = False):
26         if not node.has_key("args"):
27                 return ""
28
29         res = ""
30         if not first:
31                 comma = ", "
32         else:
33                 comma = ""
34         for arg in node["args"]:
35                 res = res + (comma + arg["name"])
36                 comma = ", "
37         return res
38
39 def format_blockdecl(node):
40         if node.get("knownBlock"):
41                 return ""
42         else:
43                 return ", ir_node *block"
44
45 def format_block(node):
46         if node.get("knownBlock"):
47                 return ""
48         else:
49                 return ", block"
50
51 def format_curblock(node):
52         if node.get("knownBlock"):
53                 return ""
54         else:
55                 return ", current_ir_graph->current_block"
56
57 def format_insdecl(node):
58         arity = node["arity"]
59         if arity == "variable" and len(node["ins"]) == 0 or arity == "dynamic" or arity == 0:
60                 return ""
61
62         if arity == "variable":
63                 insarity = len(node["ins"])
64                 res = "int r_arity = arity + " + `insarity` + ";\n\tir_node **r_in;\n\t" \
65                         + "NEW_ARR_A(ir_node *, r_in, r_arity);\n\t"
66                 i = 0
67                 for input in node["ins"]:
68                         res += "r_in[" + `i` + "] = irn_" + input + ";\n\t"
69                         i += 1
70                 res += "memcpy(&r_in[" + `insarity` + "], in, sizeof(ir_node *) * arity);\n\t"
71         else:
72                 res = "ir_node *in[" + `arity` + "];\n\t"
73                 i = 0
74                 for input in node["ins"]:
75                         res += "in[" + `i` + "] = irn_" + input + ";\n\t"
76                         i += 1
77         return res
78
79 def format_arity_and_ins(node):
80         arity = node["arity"]
81         if arity == "dynamic":
82                 return "-1, NULL"
83         elif arity == "variable":
84                 if len(node["ins"]) == 0:
85                         return "arity, in"
86                 else:
87                         return "r_arity, r_in"
88         elif arity == 0:
89                 return "0, NULL"
90         else:
91                 return `arity` + ", in"
92
93 env = Environment()
94 env.filters['argdecls']  = format_argdecls
95 env.filters['args']      = format_args
96 env.filters['blockdecl'] = format_blockdecl
97 env.filters['block']     = format_block
98 env.filters['curblock']  = format_curblock
99 env.filters['insdecl']       = format_insdecl
100 env.filters['arity_and_ins'] = format_arity_and_ins
101
102 def add_attr(list, type, name, init = None, initname = None):
103         if initname == None:
104                 initname = "." + name
105         if init != None:
106                 list.append(dict(type = type, name = name, init = init, initname = initname))
107         else:
108                 list.append(dict(type = type, name = name, initname = initname))
109
110 def prepare_attr(attr):
111         if "init" in attr:
112                 return dict(type = attr["type"], name = attr["name"], init = attr["init"])
113         else:
114                 return dict(type = attr["type"], name = attr["name"])
115
116 def preprocess_node(nodename, node):
117         # set default attributes
118         if "is_a" in node:
119                 parent = ir_spec.nodes[node["is_a"]]
120                 node["ins"] = parent["ins"]
121                 if "outs" in parent:
122                         node["outs"] = parent["outs"]
123
124         if "outs" in node:
125                 node["mode"] = "mode_T"
126         if "nodbginfo" in node:
127                 node["db"] = "NULL"
128                 node["dbdecl"] = ""
129                 node["dbdeclnocomma"] = ""
130         else:
131                 node["db"] = "db"
132                 node["dbdecl"] = "dbg_info *db, "
133                 node["dbdeclnocomma"] = "dbg_info *db"
134
135         node.setdefault("ins", [])
136         node.setdefault("arity", len(node["ins"]))
137         node.setdefault("attrs", [])
138         node.setdefault("constrname", nodename);
139         node.setdefault("constructor_args", [])
140         node.setdefault("attrs_name", nodename.lower())
141         node.setdefault("block", "block")
142         node.setdefault("pinned", "no")
143
144         verify_node(node)
145
146
147         # construct node arguments
148         arguments = [ ]
149         initattrs = [ ]
150         specialconstrs = [ ]
151         for input in node["ins"]:
152                 arguments.append(dict(type = "ir_node *", name = "irn_" + input))
153
154         if node["arity"] == "variable":
155                 arguments.append(dict(type = "int", name = "arity"))
156                 arguments.append(dict(type = "ir_node **", name = "in"))
157
158         if "mode" not in node:
159                 arguments.append(dict(type = "ir_mode *", name = "mode"))
160                 node["mode"] = "mode"
161
162         attrs_with_special = 0
163         for attr in node["attrs"]:
164                 attr.setdefault("initname", "." + attr["name"])
165
166                 if "special" in attr:
167                         if not "init" in attr:
168                                 print "Node type %s has an attribute with a \"special\" entry but without \"init\"" % nodename
169                                 sys.exit(1)
170
171                         if attrs_with_special != 0:
172                                 print "Node type %s has more than one attribute with a \"special\" entry" % nodename
173                                 sys.exit(1)
174
175                         attrs_with_special += 1
176
177                         if "prefix" in attr["special"]:
178                                 specialname = attr["special"]["prefix"] + nodename
179                         elif "suffix" in attr["special"]:
180                                 specialname = nodename + attr["special"]["suffix"]
181                         else:
182                                 print "Unknown special constructor type for node type %s" % nodename
183                                 sys.exit(1)
184
185                         specialconstrs.append(
186                                 dict(
187                                         constrname = specialname,
188                                         attr = attr
189                                 )
190                         )
191                 elif not "init" in attr:
192                         arguments.append(prepare_attr(attr))
193
194         # dynamic pin state means more constructor arguments
195         if is_dynamic_pinned(node):
196                 if "pinned_init" in node:
197                         initattrs.append(dict(
198                                 initname = ".exc.pin_state",
199                                 init     = "op_pin_state_" + node["pinned_init"]
200                         ))
201                 else:
202                         node["constructor_args"].append(
203                                 dict(
204                                         name = "pin_state",
205                                         type = "op_pin_state"
206                                 )
207                         )
208                         initattrs.append(dict(
209                                 initname = ".exc.pin_state",
210                                 init     = "pin_state"
211                         ))
212
213         for arg in node["constructor_args"]:
214                 arguments.append(prepare_attr(arg))
215                 if arg["type"] == "ir_cons_flags":
216                         name = arg["name"]
217                         initattrs.append(dict(initname = ".exc.pin_state",
218                                 init = name + " & cons_floats ? op_pin_state_floats : op_pin_state_pinned"))
219                         initattrs.append(dict(initname = ".volatility",
220                                 init = name + " & cons_volatile ? volatility_is_volatile : volatility_non_volatile"))
221                         initattrs.append(dict(initname = ".aligned",
222                                 init = name + " & cons_unaligned ? align_non_aligned : align_is_aligned"))
223
224         node["args"] = arguments
225         node["initattrs"] = initattrs
226         node["special_constructors"] = specialconstrs
227
228 #############################
229
230 node_template = env.from_string('''
231 ir_node *new_rd_{{node["constrname"]}}({{node["dbdecl"]}}ir_graph *irg{{node|blockdecl}}{{node|argdecls}})
232 {
233         ir_node *res;
234         ir_graph *rem = current_ir_graph;
235         {{node|insdecl}}
236         current_ir_graph = irg;
237         res = new_ir_node({{node["db"]}}, irg, {{node["block"]}}, op_{{nodename}}, {{node["mode"]}}, {{node|arity_and_ins}});
238         {% for attr in node["attrs"] -%}
239                 res->attr.{{node["attrs_name"]}}{{attr["initname"]}} =
240                 {%- if "init" in attr %} {{ attr["init"] -}};
241                 {%- else              %} {{ attr["name"] -}};
242                 {% endif %}
243         {% endfor %}
244         {%- for attr in node["initattrs"] -%}
245                 res->attr.{{node["attrs_name"]}}{{attr["initname"]}} = {{ attr["init"] -}};
246         {% endfor %}
247         {{- node["init"] }}
248         {% if node["optimize"] != False -%}
249                 res = optimize_node(res);
250         {% endif -%}
251         IRN_VRFY_IRG(res, irg);
252         current_ir_graph = rem;
253         return res;
254 }
255
256 ir_node *new_r_{{node["constrname"]}}(ir_graph *irg{{node|blockdecl}}{{node|argdecls}})
257 {
258         {% if node["nodbginfo"] -%}
259                 return new_rd_{{node["constrname"]}}(irg{{node|block}}{{node|args}});
260         {%- else -%}
261                 return new_rd_{{node["constrname"]}}(NULL, irg{{node|block}}{{node|args}});
262         {%- endif %}
263 }
264
265 ir_node *new_d_{{node["constrname"]}}({{node["dbdeclnocomma"]}}{{node|argdecls(node["nodbginfo"])}})
266 {
267         ir_node *res;
268         {{ node["d_pre"] }}
269         {% if node["nodbginfo"] -%}
270                 res = new_rd_{{node["constrname"]}}(current_ir_graph{{node|curblock}}{{node|args}});
271         {%- else -%}
272                 res = new_rd_{{node["constrname"]}}(db, current_ir_graph{{node|curblock}}{{node|args}});
273         {%- endif %}
274         {{ node["d_post"] }}
275         return res;
276 }
277
278 ir_node *new_{{node["constrname"]}}({{node|argdecls(True, True)}})
279 {
280         {% if node["nodbginfo"] -%}
281                 return new_d_{{node["constrname"]}}({{node|args(True)}});
282         {%- else -%}
283                 return new_d_{{node["constrname"]}}(NULL{{node|args}});
284         {%- endif %}
285 }
286
287 ''')
288
289 #############################
290
291 def main(argv):
292         """the main function"""
293
294         if len(argv) < 3:
295                 print "usage: %s specname(ignored) destdirectory" % argv[0]
296                 sys.exit(1)
297
298         gendir = argv[2]
299
300         # List of TODOs
301         niymap = ["Anchor", "ASM", "Bad",
302                 "CallBegin", "Const", "Const_type", "Const_long",
303                 "defaultProj", "Dummy", "EndReg", "EndExcept",
304                 "NoMem", "Phi",
305                 "simpleSel", "SymConst", "SymConst_type", "Sync"]
306
307         file = open(gendir + "/gen_ir_cons.c.inl", "w")
308         for nodename, node in do_dictsort(ir_spec.nodes):
309                 if nodename in niymap:
310                         continue
311                 preprocess_node(nodename, node)
312                 if not "abstract" in node:
313                         file.write(node_template.render(vars()))
314
315                         if "special_constructors" in node:
316                                 for special in node["special_constructors"]:
317                                         node["constrname"] = special["constrname"]
318                                         special["attr"]["init"] = special["attr"]["special"]["init"]
319                                         file.write(node_template.render(vars()))
320         file.write("\n")
321         file.close()
322
323 if __name__ == "__main__":
324         main(sys.argv)