fix code after TLS-type change
[libfirm] / scripts / gen_ir_io.py
1 #!/usr/bin/env python
2 import sys
3 import re
4 from jinja2 import Environment, Template
5 from jinja2.filters import do_dictsort
6 from spec_util import is_dynamic_pinned, verify_node, isAbstract
7 import ir_spec
8
9 def error(msg):
10         """writes an error message to stderr"""
11         sys.stderr.write("Error: " + msg + "\n");
12
13 def warning(msg):
14         """writes a warning message to stderr"""
15         sys.stderr.write("Warning: " + msg + "\n");
16
17 def format_args(arglist):
18         return "\n".join(arglist)
19
20 def format_ifnset(string, node, key):
21         if hasattr(node, key):
22                 return ""
23         return string
24
25 def format_block(node):
26         if hasattr(node, "knownBlock"):
27                 if hasattr(node, "knownGraph"):
28                         return ""
29                 return "irg"
30         else:
31                 return "preds[0]"
32
33 def format_arguments(string):
34         args = re.split('\s*\n\s*', string)
35         if args[0] == '':
36                 args = args[1:]
37         if len(args) > 0 and args[-1] == '':
38                 args = args[:-1]
39         return ", ".join(args)
40
41 env = Environment()
42 env.filters['args']      = format_args
43 env.filters['ifnset']    = format_ifnset
44 env.filters['block']     = format_block
45 env.filters['arguments'] = format_arguments
46
47 def get_io_type(type, attrname, node):
48         if type == "ir_tarval*":
49                 importcmd = "ir_tarval *%s = read_tv(env);" % attrname
50                 exportcmd = "write_tarval(env, %(val)s);";
51         elif type == "ir_mode*":
52                 importcmd = "ir_mode *%s = read_mode(env);" % attrname
53                 exportcmd = "write_mode(env, %(val)s);"
54         elif type == "ir_entity*":
55                 importcmd = "ir_entity *%s = read_entity(env);" % attrname
56                 exportcmd = """write_entity_ref(env, %(val)s);"""
57         elif type == "ir_type*":
58                 importcmd = "ir_type *%s = read_type(env);" % attrname
59                 exportcmd = """write_type_ref(env, %(val)s);"""
60         elif type == "long" and node.name == "Proj":
61                 importcmd = "long %s = read_long(env);" % attrname
62                 exportcmd = """write_long(env, %(val)s);"""
63         elif type == "ir_relation" or type == "ir_where_alloc":
64                 importcmd = "%s %s = (%s) read_long(env);" % (type, attrname, type)
65                 exportcmd = """write_long(env, (long) %(val)s);"""
66         elif type == "ir_cons_flags" and node.name == "Store":
67                 importcmd = "ir_cons_flags %s = get_cons_flags(env);" % attrname
68                 exportcmd = """write_pin_state(env, irn);
69                         write_volatility(env, irn);
70                         write_align(env, irn);"""
71         elif type == "ir_cons_flags" and node.name == "Load":
72                 importcmd = "ir_cons_flags %s = get_cons_flags(env);" % attrname
73                 exportcmd = """write_pin_state(env, irn);
74                         write_volatility(env, irn);
75                         write_align(env, irn);"""
76         elif type == "op_pin_state":
77                 importcmd = "op_pin_state %s = read_pin_state(env);" % attrname
78                 exportcmd = "write_pin_state(env, irn);"
79         elif type == "ir_builtin_kind":
80                 importcmd = "ir_builtin_kind %s = read_builtin_kind(env);" % attrname
81                 exportcmd = "write_builtin_kind(env, irn);"
82         elif type == "cond_kind":
83                 importcmd = "cond_kind %s = read_cond_kind(env);" % attrname
84                 exportcmd = "write_cond_kind(env, irn);"
85         elif type == "cond_jmp_predicate":
86                 importcmd = "cond_jmp_predicate %s = read_cond_jmp_predicate(env);" % attrname
87                 exportcmd = "write_cond_jmp_predicate(env, irn);"
88         elif type == "int":
89                 importcmd = "int %s = read_int(env);" % attrname
90                 exportcmd = """write_int(env, %(val)s);"""
91         elif type == "unsigned":
92                 importcmd = "unsigned %s = read_unsigned(env);" % attrname
93                 exportcmd = """write_unsigned(env, %(val)s);"""
94         elif type == "long":
95                 importcmd = "long %s = read_long(env);" % attrname
96                 exportcmd = """write_long(env, %(val)s);"""
97         else:
98                 warning("cannot generate import/export for node %s: unsupported attribute type: %s" % (node.name, type))
99                 importcmd = """// BAD: %s %s
100                         %s %s = (%s) 0;""" % (type, attrname, type, attrname, type)
101                 exportcmd = "// BAD: %s" % type
102         return (importcmd, exportcmd)
103
104 def prepare_attr(node, attr):
105         (importcmd,exportcmd) = get_io_type(attr["type"], attr["name"], node)
106         attr["importcmd"] = importcmd
107         attr["exportcmd"] = exportcmd % {"val": "get_%s_%s(irn)" % (node.name, attr["name"])}
108
109
110 def preprocess_node(node):
111         # dynamic pin state means, we have to im/export that
112         if is_dynamic_pinned(node):
113                 newattr = dict(
114                         name = "state",
115                         type = "op_pin_state"
116                 )
117                 if hasattr(node, "pinned_init"):
118                         newattr["init"] = node.pinned_init
119                 node.attrs.append(newattr)
120
121         verify_node(node)
122
123         # construct node arguments
124         arguments = [ ]
125         initargs = [ ]
126         i = 1
127         for input in node.ins:
128                 arguments.append("preds[%i]" % i)
129                 i += 1
130
131         if node.arity == "variable" or node.arity == "dynamic":
132                 arguments.append("numpreds - %i" % i)
133                 arguments.append("preds + %i" % i)
134
135         if not hasattr(node, "mode"):
136                 arguments.append("mode")
137
138         for attr in node.attrs:
139                 prepare_attr(node, attr)
140                 if "init" in attr:
141                         if attr["type"] == "op_pin_state":
142                                 initfunc = "set_irn_pinned"
143                         else:
144                                 initfunc = "set_" + node.name + "_" + attr["name"]
145                         initargs.append((attr["name"], initfunc))
146                 else:
147                         arguments.append(attr["name"])
148
149         for arg in node.constructor_args:
150                 prepare_attr(node, arg)
151                 arguments.append(arg["name"])
152
153         node.arguments = arguments
154         node.initargs = initargs
155
156 export_attrs_template = env.from_string('''
157         case iro_{{node.name}}:
158                 {{"write_mode(env, get_irn_mode(irn));"|ifnset(node,"mode")}}
159                 {% for attr in node.attrs %}{{attr.exportcmd}}
160                 {% endfor %}
161                 {% for attr in node.constructor_args %}{{attr.exportcmd}}
162                 {% endfor %}break;''')
163
164 import_attrs_template = env.from_string('''
165         case iro_{{node.name}}: {
166                 {{"ir_mode *mode = read_mode(env);"|ifnset(node,"mode")}}
167                 {% for attr in node.attrs %}
168                 {{attr.importcmd}}
169                 {% endfor -%}
170                 {% for attr in node.constructor_args %}
171                 {{attr.importcmd}}
172                 {% endfor -%}
173                 newnode = new_r_{{node.name}}(
174 {%- filter arguments %}
175 {{node|block}}
176 {{node.arguments|args}}
177 {% endfilter %});
178                 {% for (initarg, initfunc) in node.initargs %}
179                 {{initfunc}}(newnode, {{initarg}});
180                 {% endfor -%}
181                 break;
182         }
183 ''')
184
185 def main(argv):
186         """the main function"""
187
188         if len(argv) < 3:
189                 print "usage: %s specname(ignored) destdirectory" % argv[0]
190                 sys.exit(1)
191
192         gendir = argv[2]
193
194         real_nodes = []
195         for node in ir_spec.nodes:
196                 if isAbstract(node):
197                         continue
198                 real_nodes.append(node)
199
200         file = open(gendir + "/gen_irio_export.inl", "w");
201         file.write("/* Warning: automatically generated code */")
202         for node in real_nodes:
203                 if node.customSerializer:
204                         continue
205
206                 preprocess_node(node)
207                 file.write(export_attrs_template.render(vars()))
208         file.write("\n")
209         file.close()
210
211         file = open(gendir + "/gen_irio_import.inl", "w");
212         file.write("/* Warning: automatically generated code */")
213         for node in real_nodes:
214                 if node.customSerializer:
215                         continue
216                 file.write(import_attrs_template.render(vars()))
217         file.write("\n")
218         file.close()
219
220         file = open(gendir + "/gen_irio_lex.inl", "w");
221         file.write("/* Warning: automatically generated code */")
222         for node in real_nodes:
223                 file.write("\tINSERT(tt_iro, \"%s\", iro_%s);\n" % (node.name, node.name));
224         file.close()
225
226 main(sys.argv)