beifg: Simplify the implementation of be_ifg_foreach_node().
[libfirm] / scripts / gen_ir_io.py
1 #!/usr/bin/env python
2 #
3 # This file is part of libFirm.
4 # Copyright (C) 2012 Karlsruhe Institute of Technology.
5 import sys
6 from jinja2 import Environment, Template
7 from spec_util import is_dynamic_pinned, isAbstract, load_spec
8 from filters import format_arguments, filter_isnot, filter_hasnot, filter_notset
9
10 def error(msg):
11         """writes an error message to stderr"""
12         sys.stderr.write("Error: " + msg + "\n");
13
14 def warning(msg):
15         """writes a warning message to stderr"""
16         sys.stderr.write("Warning: " + msg + "\n");
17
18 def format_args(arglist):
19         return "\n".join(arglist)
20
21 def format_block(node):
22         if hasattr(node, "knownBlock"):
23                 if hasattr(node, "knownGraph"):
24                         return ""
25                 return "env->irg"
26         else:
27                 return "block"
28
29 env = Environment()
30 env.filters['args']      = format_args
31 env.filters['block']     = format_block
32 env.filters['arguments'] = format_arguments
33 env.filters['isnot']     = filter_isnot
34 env.filters['notset']    = filter_notset
35 env.filters['hasnot']    = filter_hasnot
36
37 def get_io_type(type, attrname, node):
38         if type == "ir_tarval*":
39                 importcmd = "read_tarval(env)"
40                 exportcmd = "write_tarval(env, %(val)s);"
41         elif type == "ir_mode*":
42                 importcmd = "read_mode_ref(env)"
43                 exportcmd = "write_mode_ref(env, %(val)s);"
44         elif type == "ir_entity*":
45                 importcmd = "read_entity_ref(env)"
46                 exportcmd = "write_entity_ref(env, %(val)s);"
47         elif type == "ir_type*":
48                 importcmd = "read_type_ref(env)"
49                 exportcmd = "write_type_ref(env, %(val)s);"
50         elif type == "long":
51                 importcmd = "read_long(env)"
52                 exportcmd = "write_long(env, %(val)s);"
53         elif type == "ir_relation":
54                 importcmd = "read_relation(env)"
55                 exportcmd = "write_relation(env, %(val)s);"
56         elif type == "ir_where_alloc":
57                 importcmd = "read_where_alloc(env)"
58                 exportcmd = "write_where_alloc(env, %(val)s);"
59         elif type == "ir_align":
60                 importcmd = "read_align(env)"
61                 exportcmd = "write_align(env, %(val)s);"
62         elif type == "ir_volatility":
63                 importcmd = "read_volatility(env)"
64                 exportcmd = "write_volatility(env, %(val)s);"
65         elif type == "ir_cons_flags":
66                 importcmd = "cons_none"
67                 exportcmd = "" # can't really export cons_flags
68         elif type == "op_pin_state":
69                 importcmd = "read_pin_state(env)"
70                 exportcmd = "write_pin_state(env, node);"
71         elif type == "ir_builtin_kind":
72                 importcmd = "read_builtin_kind(env)"
73                 exportcmd = "write_builtin_kind(env, node);"
74         elif type == "cond_kind":
75                 importcmd = "read_cond_kind(env)"
76                 exportcmd = "write_cond_kind(env, node);"
77         elif type == "cond_jmp_predicate":
78                 importcmd = "read_cond_jmp_predicate(env)"
79                 exportcmd = "write_cond_jmp_predicate(env, node);"
80         elif type == "int":
81                 importcmd = "read_int(env)"
82                 exportcmd = "write_int(env, %(val)s);"
83         elif type == "unsigned":
84                 importcmd = "read_unsigned(env)"
85                 exportcmd = "write_unsigned(env, %(val)s);"
86         elif type == "long":
87                 importcmd = "read_long(env)"
88                 exportcmd = "write_long(env, %(val)s);"
89         elif type == "ir_switch_table*":
90                 importcmd = "read_switch_table(env)"
91                 exportcmd = "write_switch_table(env, %(val)s);"
92         else:
93                 warning("cannot generate import/export for node %s: unsupported attribute type: %s" % (node.name, type))
94                 importcmd = "/* BAD: %s %s */ (%s)0" % (type, attrname, type)
95                 exportcmd = "// BAD: %s" % type
96         return (importcmd, exportcmd)
97
98 def prepare_attr(node, attr):
99         (importcmd,exportcmd) = get_io_type(attr["type"], attr["name"], node)
100         attr["importcmd"] = importcmd
101         attr["exportcmd"] = exportcmd % {"val": "get_%s_%s(node)" % (node.name, attr["name"])}
102
103
104 def preprocess_node(node):
105         if node.customSerializer:
106                 return
107
108         # construct node arguments
109         arguments = [ ]
110         extraattrs = [ ]
111         for input in node.ins:
112                 arguments.append("in_%s" % input[0])
113
114         if node.arity == "variable" or node.arity == "dynamic":
115                 arguments.append("n_preds")
116                 arguments.append("preds")
117
118         if not hasattr(node, "mode"):
119                 arguments.append("mode")
120
121         for attr in node.attrs:
122                 prepare_attr(node, attr)
123                 if "to_flags" in attr:
124                         node.constructorFlags = True
125                         attr['to_flags'] = attr['to_flags'] % (attr["name"])
126                 elif "init" in attr:
127                         extraattrs.append(attr)
128                 else:
129                         arguments.append(attr["name"])
130
131         for arg in node.constructor_args:
132                 if arg['type'] != "ir_cons_flags" and arg['name'] != "flags":
133                         error("only ir_cons_flags constructor arg supported in irio")
134                         continue
135                 node.constructorFlags = True
136                 arguments.append("flags")
137
138         node.arguments  = arguments
139         node.extraattrs = extraattrs
140         node.dynamic_pinned = is_dynamic_pinned(node)
141
142 io_template = env.from_string('''/* Warning: automatically generated code */
143 {%- for node in nodes|notset('customSerializer') %}
144 static ir_node *read_{{node.name}}(read_env_t *env)
145 {
146         {%- if not node.knownBlock %}
147         ir_node *block = read_node_ref(env);
148         {%- endif %}
149         {%- for input in node.ins %}
150         ir_node *in_{{input[0]}} = read_node_ref(env);
151         {%- endfor %}
152         {%- if not hasattr(node, "mode") %}
153         ir_mode *mode = read_mode_ref(env);
154         {%- endif %}
155         {%- for attr in node.attrs %}
156         {{attr.type}} {{attr.name}} = {{attr.importcmd}};
157         {%- endfor %}
158         {%- if node.dynamic_pinned %}
159         op_pin_state pin_state = read_pin_state(env);
160         {%- endif %}
161         {%- if "fragile" in node.flags %}
162         bool throws = read_throws(env);
163         {%- endif %}
164         {%- if node.arity == "dynamic" or node.arity == "variable" %}
165         int       n_preds = read_preds(env);
166         ir_node **preds   = (ir_node**)obstack_finish(&env->preds_obst);
167         {%- endif %}
168         {%- if node.constructorFlags %}
169         ir_cons_flags flags = cons_none;
170         {%- endif %}
171         ir_node *res;
172         {%- if node.constructorFlags %}
173                 {%- for attr in node.attrs %}
174                         {%- if "to_flags" in attr %}
175         flags |= {{attr.to_flags}};
176                         {%- endif %}
177                 {%- endfor %}
178                 {%- if node.dynamic_pinned %}
179         flags |= pin_state == op_pin_state_floats ? cons_floats : cons_none;
180                 {%- endif %}
181                 {%- if "fragile" in node.flags %}
182         flags |= throws ? cons_throws_exception : cons_none;
183                 {%- endif %}
184         {%- endif %}
185         res = new_r_{{node.name}}(
186                 {%- filter arguments %}
187 {{node|block}}
188 {{node.arguments|args}}
189                 {%- if node.dynamic_pinned and not hasattr(node, "pinned_init") %}
190 pin_state
191                 {%- endif %}
192 {% endfilter %});
193
194         {%- if node.arity == "dynamic" or node.arity == "variable" %}
195         obstack_free(&env->preds_obst, preds);
196         {%- endif %}
197         {%- for attr in node.extraattrs %}
198         set_{{node.name}}_{{attr.name}}(res, {{attr.name}});
199         {%- endfor %}
200         {%- if not node.constructorFlags %}
201                 {%- if node.dynamic_pinned and hasattr(node, "pinned_init") %}
202         set_irn_pinned(res, pin_state);
203                 {%- endif %}
204                 {%- if "fragile" in node.flags and hasattr(node, "throws_init") %}
205         ir_set_throws_exception(res, throws);
206                 {%- endif %}
207         {%- endif %}
208         return res;
209 }
210 {% endfor %}
211
212 {%- for node in nodes|notset('customSerializer') %}
213 static void write_{{node.name}}(write_env_t *env, const ir_node *node)
214 {
215         write_symbol(env, "{{node.name}}");
216         write_node_nr(env, node);
217         {%- if not node.knownBlock %}
218         write_node_ref(env, get_nodes_block(node));
219         {%- endif %}
220         {%- for input in node.ins %}
221         write_node_ref(env, get_{{node.name}}_{{input[0]}}(node));
222         {%- endfor %}
223         {%- if not hasattr(node, "mode") %}
224         write_mode_ref(env, get_irn_mode(node));
225         {%- endif %}
226         {%- for attr in node.attrs %}
227         {{attr.exportcmd}}
228         {%- endfor %}
229         {%- if node.dynamic_pinned %}
230         write_pin_state(env, get_irn_pinned(node));
231         {%- endif %}
232         {%- if "fragile" in node.flags %}
233         write_throws(env, ir_throws_exception(node));
234         {%- endif %}
235         {%- if node.arity == "dynamic" or node.arity == "variable" %}
236         write_pred_refs(env, node, {% if node.ins %}n_{{node.name}}_max+1{% else %}0{%endif%});
237         {%- endif %}
238 }
239 {% endfor %}
240
241 static void register_generated_node_readers(void)
242 {
243         {%- for node in nodes|notset('customSerializer') %}
244         register_node_reader(new_id_from_str("{{node.name}}"), read_{{node.name}});
245         {%- endfor %}
246 }
247
248 static void register_generated_node_writers(void)
249 {
250         {%- for node in nodes|notset('customSerializer') %}
251         register_node_writer(op_{{node.name}}, write_{{node.name}});
252         {%- endfor %}
253 }
254
255 ''')
256
257 def main(argv):
258         if len(argv) < 3:
259                 print "usage: %s specname(ignored) destdirectory" % argv[0]
260                 sys.exit(1)
261
262         specfile = argv[1]
263         gendir = argv[2]
264
265         spec = load_spec(specfile)
266         nodes = spec.nodes
267         real_nodes = []
268         for node in nodes:
269                 if isAbstract(node):
270                         continue
271                 preprocess_node(node)
272                 real_nodes.append(node)
273
274         file = open(gendir + "/gen_irio.inl", "w");
275         file.write(io_template.render(nodes = real_nodes, hasattr=hasattr))
276         file.close()
277
278 main(sys.argv)