- fixed Win32 build after r26081
[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 from spec_util import is_dynamic_pinned, verify_node
6 import ir_spec
7
8 def error(msg):
9         """writes an error message to stderr"""
10         sys.stderr.write("Error: " + msg + "\n");
11
12 def warning(msg):
13         """writes a warning message to stderr"""
14         sys.stderr.write("Warning: " + msg + "\n");
15
16 def format_args(arglist):
17         #argstrings = map(lambda arg : arg["name"], arglist)
18         #return ", ".join(argstrings)
19         s = ", ".join(arglist)
20         if len(s) == 0:
21           return ""
22         return ", " + s
23
24 def format_ifnset(string, node, key):
25         if key in node:
26                 return ""
27         return string
28
29 def format_block(node):
30         if node.get("knownBlock"):
31                 return ""
32         else:
33                 return ", get_node(env, preds[0])"
34
35 env = Environment()
36 env.filters['args']   = format_args
37 env.filters['ifnset'] = format_ifnset
38 env.filters['block']  = format_block
39
40 def get_io_type(type, attrname, nodename):
41         if type == "tarval*":
42                 importcmd = "tarval *%s = read_tv(env);" % attrname
43                 exportcmd = "write_tarval(env, %(val)s);";
44         elif type == "ir_mode*":
45                 importcmd = "ir_mode *%s = read_mode(env);" % attrname
46                 exportcmd = "write_mode(env, %(val)s);"
47         elif type == "ir_entity*":
48                 importcmd = "ir_entity *%s = read_entity(env);" % attrname
49                 exportcmd = """fprintf(env->file, "%%ld ", get_entity_nr(%(val)s));"""
50         elif type == "ir_type*":
51                 importcmd = "ir_type *%s = read_type(env);" % attrname
52                 exportcmd = """fprintf(env->file, "%%ld ", get_type_nr(%(val)s));"""
53         elif type == "long" and nodename == "Proj":
54                 importcmd = "long %s = read_long(env);" % attrname
55                 exportcmd = """fprintf(env->file, "%%ld ", %(val)s);"""
56         elif type == "pn_Cmp" or type == "ir_where_alloc":
57                 importcmd = "%s %s = (%s) read_long(env);" % (type, attrname, type)
58                 exportcmd = """fprintf(env->file, "%%ld ", (long) %(val)s);"""
59         elif type == "ir_cons_flags" and nodename == "Store":
60                 importcmd = "ir_cons_flags %s = get_cons_flags(env);" % attrname
61                 exportcmd = """write_pin_state(env, irn);
62                         write_volatility(env, irn);
63                         write_align(env, irn);"""
64         elif type == "ir_cons_flags" and nodename == "Load":
65                 importcmd = "ir_cons_flags %s = get_cons_flags(env);" % attrname
66                 exportcmd = """write_pin_state(env, irn);
67                         write_volatility(env, irn);
68                         write_align(env, irn);"""
69         elif type == "op_pin_state":
70                 importcmd = "op_pin_state %s = read_pin_state(env);" % attrname
71                 exportcmd = "write_pin_state(env, irn);"
72         elif type == "ir_builtin_kind":
73                 importcmd = "ir_builtin_kind %s = read_builtin_kind(env);" % attrname
74                 exportcmd = "write_builtin_kind(env, irn);"
75         elif type == "cond_kind":
76                 importcmd = "cond_kind %s = read_cond_kind(env);" % attrname
77                 exportcmd = "write_cond_kind(env, irn);"
78         elif type == "cond_jmp_predicate":
79                 importcmd = "cond_jmp_predicate %s = read_cond_jmp_predicate(env);" % attrname
80                 exportcmd = "write_cond_jmp_predicate(env, irn);"
81         elif type == "int":
82                 importcmd = "int %s = (int) read_long(env);" % attrname
83                 exportcmd = """fprintf(env->file, "%%d ", %(val)s);"""
84         elif type == "long":
85                 importcmd = "long %s = read_long(env);" % attrname
86                 exportcmd = """fprintf(env->file, "%%ld ", %(val)s);"""
87         else:
88                 error("cannot generate import/export for node %s: unsupported attribute type: %s" % (nodename, type))
89                 importcmd = """// BAD: %s %s
90                         %s %s = (%s) 0;""" % (type, attrname, type, attrname, type)
91                 exportcmd = "// BAD: %s" % type
92         return (importcmd, exportcmd)
93
94 def prepare_attr(nodename, attr):
95         (importcmd,exportcmd) = get_io_type(attr["type"], attr["name"], nodename)
96         attr["importcmd"] = importcmd
97         attr["exportcmd"] = exportcmd % {"val": "get_%s_%s(irn)" % (nodename, attr["name"])}
98
99 def preprocess_node(nodename, node):
100         if "is_a" in node:
101                 parent = ir_spec.nodes[node["is_a"]]
102                 node["ins"] = parent["ins"]
103                 if "outs" in parent:
104                         node["outs"] = parent["outs"]
105         if "ins" not in node:
106                 node["ins"] = []
107         if "outs" in node:
108                 node["mode"] = "mode_T"
109         if "arity" not in node:
110                 node["arity"] = len(node["ins"])
111         if "attrs" not in node:
112                 node["attrs"] = []
113         if "constructor_args" not in node:
114                 node["constructor_args"] = []
115         if "pinned" not in node:
116                 node["pinned"] = "no"
117         # dynamic pin state means, we have to im/export that
118         if is_dynamic_pinned(node):
119                 newattr = dict(
120                         name = "state",
121                         type = "op_pin_state"
122                 )
123                 if "pinned_init" in node:
124                         newattr["init"] = node["pinned_init"]
125                 node["attrs"].append(newattr)
126
127         verify_node(nodename, node)
128
129         # construct node arguments
130         arguments = [ ]
131         initargs = [ ]
132         specialconstrs = [ ]
133         i = 0
134         for input in node["ins"]:
135                 arguments.append("prednodes[%i]" % i)
136                 i += 1
137
138         if node["arity"] == "variable" or node["arity"] == "dynamic":
139                 arguments.append("numpreds - %i" % (i + 1))
140                 arguments.append("prednodes + %i" % i)
141
142         if "mode" not in node:
143                 arguments.append("mode")
144
145         attrs_with_special = 0
146         for attr in node["attrs"]:
147                 prepare_attr(nodename, attr)
148                 if "special" in attr:
149                         if not "init" in attr:
150                                 warning("Node type %s has an attribute with a \"special\" entry but without \"init\"" % nodename)
151                                 sys.exit(1)
152
153                         if attrs_with_special != 0:
154                                 warning("Node type %s has more than one attribute with a \"special\" entry" % nodename)
155                                 sys.exit(1)
156
157                         attrs_with_special += 1
158
159                         if "prefix" in attr["special"]:
160                                 specialname = attr["special"]["prefix"] + nodename
161                         elif "suffix" in attr["special"]:
162                                 specialname = nodename + attr["special"]["suffix"]
163                         else:
164                                 error("Unknown special constructor type for node type %s" % nodename)
165                                 sys.exit(1)
166
167                         specialconstrs.append(
168                                 dict(
169                                         constrname = specialname,
170                                         attrname = attr["name"],
171                                         value = attr["special"]["init"]
172                                 )
173                         )
174                 elif "init" in attr:
175                         if attr["type"] == "op_pin_state":
176                                 initfunc = "set_irn_pinned"
177                         else:
178                                 initfunc = "set_" + nodename + "_" + attr["name"]
179                         initargs.append((attr["name"], initfunc))
180                 else:
181                         arguments.append(attr["name"])
182
183         for arg in node["constructor_args"]:
184                 prepare_attr(nodename, arg)
185                 arguments.append(arg["name"])
186
187         node["arguments"] = arguments
188         node["initargs"] = initargs
189         node["special_constructors"] = specialconstrs
190
191 export_attrs_template = env.from_string('''
192         case iro_{{nodename}}:
193                 {{"write_mode(env, get_irn_mode(irn));"|ifnset(node,"mode")}}
194                 {% for attr in node.attrs %}{{attr.exportcmd}}
195                 {% endfor %}
196                 {% for attr in node.constructor_args %}{{attr.exportcmd}}
197                 {% endfor %}break;''')
198
199 import_attrs_template = env.from_string('''
200         case iro_{{nodename}}:
201         {
202                 {{"ir_mode *mode = read_mode(env);"|ifnset(node,"mode")}}
203                 {% for attr in node.attrs %}{{attr.importcmd}}
204                 {% endfor %}
205                 {% for attr in node.constructor_args %}{{attr.importcmd}}
206                 {% endfor %}
207                 {% for special in node.special_constructors %}if({{special.attrname}} == {{special.value}})
208                         newnode = new_r_{{special.constrname}}(current_ir_graph{{node|block}}{{node["arguments"]|args}});
209                 else{% endfor %}
210                 newnode = new_r_{{nodename}}(current_ir_graph{{node|block}}{{node["arguments"]|args}});
211                 {% for (initarg, initfunc) in node.initargs %}{{initfunc}}(newnode, {{initarg}});
212                 {% endfor %}
213                 break;
214         }
215 ''')
216
217 def main(argv):
218         """the main function"""
219
220         if len(argv) < 3:
221                 print "usage: %s specname(ignored) destdirectory" % argv[0]
222                 sys.exit(1)
223
224         gendir = argv[2]
225         sortednodes = do_dictsort(ir_spec.nodes)
226         # these nodes don't work correctly yet for some reasons...
227         niynodes = [ "EndExcept", "EndReg", "ASM" ]
228         # these have custom im-/export code
229         customcode = [ "Start", "End", "Anchor", "SymConst", "Block" ]
230
231         file = open(gendir + "/gen_irio_export.inl", "w");
232         for nodename, node in sortednodes:
233                 if nodename in niynodes:
234                         continue
235
236                 preprocess_node(nodename, node)
237                 if "abstract" not in node:
238                         file.write(export_attrs_template.render(vars()))
239         file.write("\n")
240         file.close()
241
242         file = open(gendir + "/gen_irio_import.inl", "w");
243         for nodename, node in sortednodes:
244                 if "abstract" in node or nodename in customcode or nodename in niynodes:
245                         continue
246                 file.write(import_attrs_template.render(vars()))
247         file.write("\n")
248         file.close()
249
250         file = open(gendir + "/gen_irio_lex.inl", "w");
251         for nodename, node in sortednodes:
252                 if "abstract" not in node and nodename not in niynodes:
253                         file.write("\tINSERT(\"" + nodename + "\", tt_iro, iro_" + nodename + ");\n");
254         file.close()
255
256 if __name__ == "__main__":
257         main(sys.argv)