redo pinned mode handling in spec generator
[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         # Special case for Builtin...
155         if nodename == "Builtin":
156                 for attr in node["attrs"]:
157                         if attr["name"] == "kind":
158                                 attr.setdefault("initname", "." + attr["name"])
159                                 arguments.append(prepare_attr(attr))
160
161         if node["arity"] == "variable":
162                 arguments.append(dict(type = "int", name = "arity"))
163                 arguments.append(dict(type = "ir_node **", name = "in"))
164
165         if "mode" not in node:
166                 arguments.append(dict(type = "ir_mode *", name = "mode"))
167                 node["mode"] = "mode"
168
169         attrs_with_special = 0
170         for attr in node["attrs"]:
171                 if nodename == "Builtin" and attr["name"] == "kind":
172                         continue
173
174                 attr.setdefault("initname", "." + attr["name"])
175
176                 if "special" in attr:
177                         if not "init" in attr:
178                                 print "Node type %s has an attribute with a \"special\" entry but without \"init\"" % nodename
179                                 sys.exit(1)
180
181                         if attrs_with_special != 0:
182                                 print "Node type %s has more than one attribute with a \"special\" entry" % nodename
183                                 sys.exit(1)
184
185                         attrs_with_special += 1
186
187                         if "prefix" in attr["special"]:
188                                 specialname = attr["special"]["prefix"] + nodename
189                         elif "suffix" in attr["special"]:
190                                 specialname = nodename + attr["special"]["suffix"]
191                         else:
192                                 print "Unknown special constructor type for node type %s" % nodename
193                                 sys.exit(1)
194
195                         specialconstrs.append(
196                                 dict(
197                                         constrname = specialname,
198                                         attr = attr
199                                 )
200                         )
201                 elif not "init" in attr:
202                         arguments.append(prepare_attr(attr))
203
204         # dynamic pin state means more constructor arguments
205         if is_dynamic_pinned(node):
206                 if "pinned_init" in node:
207                         initattrs.append(dict(
208                                 initname = ".exc.pin_state",
209                                 init     = "op_pin_state_" + node["pinned_init"]
210                         ))
211                 else:
212                         node["constructor_args"].append(
213                                 dict(
214                                         name = "pin_state",
215                                         type = "op_pin_state"
216                                 )
217                         )
218                         initattrs.append(dict(
219                                 initname = ".exc.pin_state",
220                                 init     = "pin_state"
221                         ))
222
223         for arg in node["constructor_args"]:
224                 arguments.append(prepare_attr(arg))
225                 if arg["type"] == "ir_cons_flags":
226                         name = arg["name"]
227                         initattrs.append(dict(initname = ".exc.pin_state",
228                                 init = name + " & cons_floats ? op_pin_state_floats : op_pin_state_pinned"))
229                         initattrs.append(dict(initname = ".volatility",
230                                 init = name + " & cons_volatile ? volatility_is_volatile : volatility_non_volatile"))
231                         initattrs.append(dict(initname = ".aligned",
232                                 init = name + " & cons_unaligned ? align_non_aligned : align_is_aligned"))
233
234         node["args"] = arguments
235         node["initattrs"] = initattrs
236         node["special_constructors"] = specialconstrs
237
238 #############################
239
240 node_template = env.from_string('''
241 ir_node *new_rd_{{node["constrname"]}}({{node["dbdecl"]}}ir_graph *irg{{node|blockdecl}}{{node|argdecls}})
242 {
243         ir_node *res;
244         ir_graph *rem = current_ir_graph;
245         {{node|insdecl}}
246         current_ir_graph = irg;
247         res = new_ir_node({{node["db"]}}, irg, {{node["block"]}}, op_{{nodename}}, {{node["mode"]}}, {{node|arity_and_ins}});
248         {% for attr in node["attrs"] -%}
249                 res->attr.{{node["attrs_name"]}}{{attr["initname"]}} =
250                 {%- if "init" in attr %} {{ attr["init"] -}};
251                 {%- else              %} {{ attr["name"] -}};
252                 {% endif %}
253         {% endfor %}
254         {%- for attr in node["initattrs"] -%}
255                 res->attr.{{node["attrs_name"]}}{{attr["initname"]}} = {{ attr["init"] -}};
256         {% endfor %}
257         {{- node["init"] }}
258         {% if node["optimize"] != False -%}
259                 res = optimize_node(res);
260         {% endif -%}
261         IRN_VRFY_IRG(res, irg);
262         current_ir_graph = rem;
263         return res;
264 }
265
266 ir_node *new_r_{{node["constrname"]}}(ir_graph *irg{{node|blockdecl}}{{node|argdecls}})
267 {
268         {% if node["nodbginfo"] -%}
269                 return new_rd_{{node["constrname"]}}(irg{{node|block}}{{node|args}});
270         {%- else -%}
271                 return new_rd_{{node["constrname"]}}(NULL, irg{{node|block}}{{node|args}});
272         {%- endif %}
273 }
274
275 ir_node *new_d_{{node["constrname"]}}({{node["dbdeclnocomma"]}}{{node|argdecls(node["nodbginfo"])}})
276 {
277         ir_node *res;
278         {{ node["d_pre"] }}
279         {% if node["nodbginfo"] -%}
280                 res = new_rd_{{node["constrname"]}}(current_ir_graph{{node|curblock}}{{node|args}});
281         {%- else -%}
282                 res = new_rd_{{node["constrname"]}}(db, current_ir_graph{{node|curblock}}{{node|args}});
283         {%- endif %}
284         {{ node["d_post"] }}
285         return res;
286 }
287
288 ir_node *new_{{node["constrname"]}}({{node|argdecls(True, True)}})
289 {
290         {% if node["nodbginfo"] -%}
291                 return new_d_{{node["constrname"]}}({{node|args(True)}});
292         {%- else -%}
293                 return new_d_{{node["constrname"]}}(NULL{{node|args}});
294         {%- endif %}
295 }
296
297 ''')
298
299 #############################
300
301 def main(argv):
302         """the main function"""
303
304         if len(argv) < 3:
305                 print "usage: %s specname(ignored) destdirectory" % argv[0]
306                 sys.exit(1)
307
308         gendir = argv[2]
309
310         # List of TODOs
311         niymap = ["Anchor", "ASM", "Bad",
312                 "CallBegin", "Const", "Const_type", "Const_long",
313                 "defaultProj", "Dummy", "EndReg", "EndExcept",
314                 "NoMem", "Phi",
315                 "simpleSel", "SymConst", "SymConst_type", "Sync"]
316
317         file = open(gendir + "/gen_ir_cons.c.inl", "w")
318         for nodename, node in do_dictsort(ir_spec.nodes):
319                 if nodename in niymap:
320                         continue
321                 preprocess_node(nodename, node)
322                 if not "abstract" in node:
323                         file.write(node_template.render(vars()))
324
325                         if "special_constructors" in node:
326                                 for special in node["special_constructors"]:
327                                         node["constrname"] = special["constrname"]
328                                         special["attr"]["init"] = special["attr"]["special"]["init"]
329                                         file.write(node_template.render(vars()))
330         file.write("\n")
331         file.close()
332
333 if __name__ == "__main__":
334         main(sys.argv)