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