remove ilp scheduler; simplify listsched interface
[libfirm] / scripts / gen_ir.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, setdefault
7 from ir_spec import nodes
8
9 def format_parameterlist(parameterlist):
10         return "\n".join(parameterlist)
11
12 def format_nodearguments(node):
13         arguments = map(lambda arg: arg["name"], node.arguments)
14         return format_parameterlist(arguments)
15
16 def format_nodeparameters(node):
17         parameters = map(lambda arg: arg["type"] + " " + arg["name"], node.arguments)
18         return format_parameterlist(parameters)
19
20 def format_blockparameter(node):
21         if hasattr(node, "knownBlock"):
22                 if hasattr(node, "knownGraph"):
23                         return ""
24                 return "ir_graph *irg"
25         else:
26                 return "ir_node *block"
27
28 def format_blockargument(node):
29         if hasattr(node, "knownBlock"):
30                 if hasattr(node, "knownGraph"):
31                         return ""
32                 return "irg"
33         else:
34                 return "block"
35
36 def format_irgassign(node):
37         if hasattr(node, "knownGraph"):
38                 return "ir_graph *irg = %s;\n" % node.graph
39
40         if hasattr(node, "knownBlock"):
41                 return ""
42         else:
43                 return "ir_graph *irg = get_Block_irg(block);\n"
44
45 def format_curblock(node):
46         if hasattr(node, "knownBlock"):
47                 if hasattr(node, "knownGraph"):
48                         return ""
49                 return "current_ir_graph"
50         else:
51                 return "current_ir_graph->current_block"
52
53 def format_insdecl(node):
54         arity = node.arity
55         if arity == "variable" and len(node.ins) == 0 or arity == "dynamic" or arity == 0:
56                 return ""
57
58         if arity == "variable":
59                 insarity = len(node.ins)
60                 res  = "int r_arity = arity + " + `insarity` + ";"
61                 res += "\n\tir_node **r_in;"
62                 res += "\n\tNEW_ARR_A(ir_node *, r_in, r_arity);"
63                 i = 0
64                 for input in node.ins:
65                         res += "\n\tr_in[" + `i` + "] = irn_" + input + ";"
66                         i += 1
67                 res += "\n\tmemcpy(&r_in[" + `insarity` + "], in, sizeof(ir_node *) * arity);\n\t"
68         else:
69                 res = "ir_node *in[" + `arity` + "];"
70                 i = 0
71                 for input in node.ins:
72                         res += "\n\tin[" + `i` + "] = irn_" + input + ";"
73                         i += 1
74         return res
75
76 def format_arity_and_ins(node):
77         arity = node.arity
78         if arity == "dynamic":
79                 return "-1, NULL"
80         elif arity == "variable":
81                 if len(node.ins) == 0:
82                         return "arity, in"
83                 else:
84                         return "r_arity, r_in"
85         elif arity == 0:
86                 return "0, NULL"
87         else:
88                 return `arity` + ", in"
89
90 def format_arity(node):
91         if hasattr(node, "arity_override"):
92                 return node.arity_override
93         arity = node.arity
94         if arity == "dynamic":
95                 return "oparity_dynamic"
96         if arity == "variable":
97                 return "oparity_variable"
98         if arity == 0:
99                 return "oparity_zero"
100         if arity == 1:
101                 return "oparity_unary"
102         if arity == 2:
103                 return "oparity_binary"
104         if arity == 3:
105                 return "oparity_trinary"
106         return "oparity_any"
107
108 def format_pinned(node):
109         pinned = node.pinned
110         if pinned == "yes":
111                 return "op_pin_state_pinned"
112         if pinned == "no":
113                 return "op_pin_state_floats"
114         if pinned == "exception":
115                 return "op_pin_state_exc_pinned"
116         if pinned == "memory":
117                 return "op_pin_state_mem_pinned"
118         print "WARNING: Unknown pinned state %s in format pined" % pinned
119         return ""
120
121 def format_flags(node):
122         flags = map(lambda x : "irop_flag_" + x, node.flags)
123         if flags == []:
124                 flags = [ "irop_flag_none" ]
125         return " | ".join(flags)
126
127 def format_attr_size(node):
128         if not hasattr(node, "attr_struct"):
129                 return "0"
130         return "sizeof(%s)" % node.attr_struct
131
132 def format_opindex(node):
133         if hasattr(node, "op_index"):
134                 return node.op_index
135         return "-1"
136
137 keywords = frozenset([ "true", "false" ])
138 def format_escape_keywords(word):
139         if word in keywords:
140                 return word + "_"
141         return word
142
143 def filter_isnot(list, flag):
144         return filter(lambda x: not hasattr(x, flag), list)
145
146 def filter_hasnot(list, flag):
147         return filter(lambda x: flag not in x, list)
148
149 def format_arguments(string, voidwhenempty = False):
150         args = re.split('\s*\n\s*', string)
151         if args[0] == '':
152                 args = args[1:]
153         if len(args) > 0 and args[-1] == '':
154                 args = args[:-1]
155         if len(args) == 0 and voidwhenempty:
156                 return "void"
157         return ", ".join(args)
158
159 def format_parameters(string):
160         return format_arguments(string, voidwhenempty = True)
161
162 env = Environment()
163 env.filters['parameterlist']   = format_parameterlist
164 env.filters['nodearguments']   = format_nodearguments
165 env.filters['nodeparameters']  = format_nodeparameters
166 env.filters['blockparameter']  = format_blockparameter
167 env.filters['blockargument']   = format_blockargument
168 env.filters['irgassign']       = format_irgassign
169 env.filters['curblock']        = format_curblock
170 env.filters['insdecl']         = format_insdecl
171 env.filters['arity_and_ins']   = format_arity_and_ins
172 env.filters['arity']           = format_arity
173 env.filters['pinned']          = format_pinned
174 env.filters['flags']           = format_flags
175 env.filters['attr_size']       = format_attr_size
176 env.filters['opindex']         = format_opindex
177 env.filters['isnot']           = filter_isnot
178 env.filters['hasnot']          = filter_hasnot
179 env.filters['arguments']       = format_arguments
180 env.filters['parameters']      = format_parameters
181 env.filters['escape_keywords'] = format_escape_keywords
182
183 def prepare_attr(attr):
184         if "init" in attr:
185                 return dict(type = attr["type"], name = attr["name"], init = attr["init"])
186         else:
187                 return dict(type = attr["type"], name = attr["name"])
188
189 def preprocess_node(node):
190         verify_node(node)
191
192         setdefault(node, "attrs_name", node.name.lower())
193         setdefault(node, "block", "block")
194
195         # construct node arguments
196         arguments = [ ]
197         initattrs = [ ]
198         specialconstrs = [ ]
199         for input in node.ins:
200                 arguments.append(dict(type = "ir_node *", name = "irn_" + input))
201
202         if node.arity == "variable" or node.arity == "dynamic":
203                 arguments.append(dict(type = "int", name = "arity"))
204                 arguments.append(dict(type = "ir_node **", name = "in"))
205
206         if not hasattr(node, "mode"):
207                 arguments.append(dict(type = "ir_mode *", name = "mode"))
208                 node.mode = "mode"
209
210         attrs_with_special = 0
211         for attr in node.attrs:
212                 attr.setdefault("initname", "." + attr["name"])
213
214                 if "special" in attr:
215                         if not "init" in attr:
216                                 print "Node type %s has an attribute with a \"special\" entry but without \"init\"" % node.name
217                                 sys.exit(1)
218
219                         if attrs_with_special != 0:
220                                 print "Node type %s has more than one attribute with a \"special\" entry" % node.name
221                                 sys.exit(1)
222
223                         attrs_with_special += 1
224
225                         if "prefix" in attr["special"]:
226                                 specialname = attr["special"]["prefix"] + node.name
227                         elif "suffix" in attr["special"]:
228                                 specialname = node.name + attr["special"]["suffix"]
229                         else:
230                                 print "Unknown special constructor type for node type %s" % node.name
231                                 sys.exit(1)
232
233                         specialconstrs.append(
234                                 dict(
235                                         constrname = specialname,
236                                         attr = attr
237                                 )
238                         )
239                 elif not "init" in attr:
240                         arguments.append(prepare_attr(attr))
241
242         # dynamic pin state means more constructor arguments
243         if is_dynamic_pinned(node):
244                 if hasattr(node, "pinned_init"):
245                         initattrs.append(dict(
246                                 initname = ".exc.pin_state",
247                                 init     = node.pinned_init
248                         ))
249                 else:
250                         node.constructor_args.append(
251                                 dict(
252                                         name = "pin_state",
253                                         type = "op_pin_state"
254                                 )
255                         )
256                         initattrs.append(dict(
257                                 initname = ".exc.pin_state",
258                                 init     = "pin_state"
259                         ))
260
261         for arg in node.constructor_args:
262                 arguments.append(prepare_attr(arg))
263                 if arg["type"] == "ir_cons_flags":
264                         name = arg["name"]
265                         initattrs.append(dict(initname = ".exc.pin_state",
266                                 init = name + " & cons_floats ? op_pin_state_floats : op_pin_state_pinned"))
267                         initattrs.append(dict(initname = ".volatility",
268                                 init = name + " & cons_volatile ? volatility_is_volatile : volatility_non_volatile"))
269                         initattrs.append(dict(initname = ".aligned",
270                                 init = name + " & cons_unaligned ? align_non_aligned : align_is_aligned"))
271
272         node.arguments = arguments
273         node.initattrs = initattrs
274         node.special_constructors = specialconstrs
275
276 #############################
277
278 constructor_template = env.from_string('''
279
280 ir_node *new_rd_{{node.constrname}}(
281         {%- filter parameters %}
282                 dbg_info *dbgi
283                 {{node|blockparameter}}
284                 {{node|nodeparameters}}
285         {% endfilter %})
286 {
287         ir_node *res;
288         ir_graph *rem = current_ir_graph;
289         {{node|irgassign}}
290         {{node|insdecl}}
291         current_ir_graph = irg;
292         res = new_ir_node(
293                 {%- filter arguments %}
294                         dbgi
295                         irg
296                         {{node.block}}
297                         op_{{node.name}}
298                         {{node.mode}}
299                         {{node|arity_and_ins}}
300                 {% endfilter %});
301         {%- for attr in node.attrs %}
302         res->attr.{{node.attrs_name}}{{attr["initname"]}} =
303                 {%- if "init" in attr %} {{ attr["init"] -}};
304                 {%- else              %} {{ attr["name"] -}};
305                 {%- endif %}
306         {%- endfor %}
307         {%- for attr in node.initattrs %}
308         res->attr.{{node.attrs_name}}{{attr["initname"]}} = {{ attr["init"] -}};
309         {%- endfor %}
310         {{- node.init }}
311         {%- if node.optimize != False %}
312         res = optimize_node(res);
313         {%- endif %}
314         IRN_VERIFY_IRG(res, irg);
315         current_ir_graph = rem;
316         return res;
317 }
318
319 ir_node *new_r_{{node.constrname}}(
320                 {%- filter parameters %}
321                         {{node|blockparameter}}
322                         {{node|nodeparameters}}
323                 {% endfilter %})
324 {
325         return new_rd_{{node.constrname}}(
326                 {%- filter arguments %}
327                         NULL
328                         {{node|blockargument}}
329                         {{node|nodearguments}}
330                 {% endfilter %});
331 }
332
333 ir_node *new_d_{{node.constrname}}(
334                 {%- filter parameters %}
335                         dbg_info *dbgi
336                         {{node|nodeparameters}}
337                 {% endfilter %})
338 {
339         ir_node *res;
340         res = new_rd_{{node.constrname}}(
341                 {%- filter parameters %}
342                         dbgi
343                         {{node|curblock}}
344                         {{node|nodearguments}}
345                 {% endfilter %});
346         {%- if "fragile" in node.flags %}
347         firm_alloc_frag_arr(res, op_{{node.name}}, &res->attr.except.frag_arr);
348         {%- endif %}
349         return res;
350 }
351
352 ir_node *new_{{node.constrname}}(
353                 {%- filter parameters %}
354                         {{node|nodeparameters}}
355                 {% endfilter %})
356 {
357         return new_d_{{node.constrname}}(
358                 {%- filter arguments %}
359                         NULL
360                         {{node|nodearguments}}
361                 {% endfilter %});
362 }
363 ''')
364
365 irnode_h_template = env.from_string('''
366 /* Warning: automatically generated code */
367
368 {%- for node in nodes|isnot('custom_is') %}
369 static inline int _is_{{node.name}}(const ir_node *node)
370 {
371         assert(node != NULL);
372         return _get_irn_op(node) == op_{{node.name}};
373 }
374 {%- endfor -%}
375
376 {% for node in nodes %}
377 #define is_{{node.name}}(node)    _is_{{node.name}}(node)
378 {%- endfor %}
379
380 ''')
381
382 irnode_template = env.from_string('''
383 /* Warning: automatically generated code */
384 {% for node in nodes %}
385 int (is_{{node.name}})(const ir_node *node)
386 {
387         return _is_{{node.name}}(node);
388 }
389 {% endfor %}
390
391 {%- for node in nodes %}
392 {%- for attr in node.attrs|hasnot("noprop") %}
393 {{attr.type}} (get_{{node.name}}_{{attr.name}})(const ir_node *node)
394 {
395         assert(is_{{node.name}}(node));
396         return node->attr.{{node.attrs_name}}.{{attr.name}};
397 }
398
399 void (set_{{node.name}}_{{attr.name}})(ir_node *node, {{attr.type}} {{attr.name}})
400 {
401         assert(is_{{node.name}}(node));
402         node->attr.{{node.attrs_name}}.{{attr.name}} = {{attr.name}};
403 }
404 {% endfor -%}
405 {% endfor -%}
406
407 {%- for node in nodes %}
408 {%- for in in node.ins %}
409 ir_node *(get_{{node.name}}_{{in}})(const ir_node *node)
410 {
411         assert(is_{{node.name}}(node));
412         return get_irn_n(node, {{node.ins.index(in)}});
413 }
414
415 void (set_{{node.name}}_{{in}})(ir_node *node, ir_node *{{in|escape_keywords}})
416 {
417         assert(is_{{node.name}}(node));
418         set_irn_n(node, {{node.ins.index(in)}}, {{in|escape_keywords}});
419 }
420 {% endfor %}
421 {% endfor %}
422 ''')
423
424 irop_template = env.from_string('''
425 /* Warning: automatically generated code */
426 {% for node in nodes %}
427 ir_op *op_{{node.name}}; ir_op *get_op_{{node.name}}(void) { return op_{{node.name}}; }
428 {%- endfor %}
429
430 void init_op(void)
431 {
432         {% for node in nodes %}
433         op_{{node.name}} = new_ir_op(
434                 {%- filter arguments %}
435                         iro_{{node.name}}
436                         "{{node.name}}"
437                         {{node|pinned}}
438                         {{node|flags}}
439                         {{node|arity}}
440                         {{node|opindex}}
441                         {{node|attr_size}}
442                         NULL
443                 {% endfilter %});
444         {%- endfor %}
445
446         be_init_op();
447 }
448
449 void finish_op(void)
450 {
451         {% for node in nodes %}
452         free_ir_op(op_{{node.name}}); op_{{node.name}} = NULL;
453         {%- endfor %}
454 }
455
456 ''')
457
458 nodeops_h_template = env.from_string('''
459 /* Warning: automatically generated code */
460 #ifndef FIRM_IR_NODEOPS_H
461 #define FIRM_IR_NODEOPS_H
462
463 #include "firm_types.h"
464
465 /**
466  * @addtogroup ir_node
467  * @{
468  */
469
470 {% for node in nodes -%}
471 {% if node.outs %}
472 /**
473  * Projection numbers for result of {{node.name}} node (use for Proj nodes)
474  */
475 typedef enum {
476         {% for out in node.outs -%}
477         pn_{{node.name}}_{{out[0]}}
478         {%- if out.__len__() > 2 %} = {{out[2]}}{% endif %}, /**< {{out[1]}} */
479         {% endfor -%}
480         pn_{{node.name}}_max
481 } pn_{{node.name}};
482 {% endif %}
483 {%- endfor %}
484
485 {% for node in nodes %}
486 /** Return true of the node is a {{node.name}} node. */
487 FIRM_API int is_{{node.name}}(const ir_node *node);
488 {%- endfor %}
489
490 {% for node in nodes %}
491 {% for in in node.ins -%}
492 FIRM_API ir_node *get_{{node.name}}_{{in}}(const ir_node *node);
493 void set_{{node.name}}_{{in}}(ir_node *node, ir_node *{{in|escape_keywords}});
494 {% endfor -%}
495 {% for attr in node.attrs|hasnot("noprop") -%}
496 FIRM_API {{attr.type}} get_{{node.name}}_{{attr.name}}(const ir_node *node);
497 FIRM_API void set_{{node.name}}_{{attr.name}}(ir_node *node, {{attr.type}} {{attr.name}});
498 {% endfor -%}
499 {% endfor -%}
500
501 /** @} */
502
503 #endif
504 ''')
505
506 opcodes_h_template = env.from_string('''
507 /* Warning: automatically generated code */
508 #ifndef FIRM_IR_OPCODES_H
509 #define FIRM_IR_OPCODES_H
510
511 /** The opcodes of the libFirm predefined operations. */
512 typedef enum ir_opcode {
513 {%- for node in nodes %}
514         iro_{{node.name}},
515 {%- endfor %}
516         iro_First = iro_{{nodes[0].name}},
517         iro_Last = iro_{{nodes[-1].name}},
518
519         beo_First,
520         /* backend specific nodes */
521         beo_Spill = beo_First,
522         beo_Reload,
523         beo_Perm,
524         beo_MemPerm,
525         beo_Copy,
526         beo_Keep,
527         beo_CopyKeep,
528         beo_Call,
529         beo_Return,
530         beo_AddSP,
531         beo_SubSP,
532         beo_IncSP,
533         beo_Start,
534         beo_FrameAddr,
535         beo_Barrier,
536         /* last backend node number */
537         beo_Last = beo_Barrier,
538         iro_MaxOpcode
539 } ir_opcode;
540
541 {% for node in nodes %}
542 FIRM_API ir_op *op_{{node.name}};
543 {%- endfor %}
544
545 {% for node in nodes %}
546 FIRM_API ir_op *get_op_{{node.name}}(void);
547 {%- endfor %}
548
549 #endif
550 ''')
551
552 #############################
553
554 def prepare_nodes():
555         real_nodes = []
556         for node in nodes:
557                 if isAbstract(node):
558                         continue
559                 real_nodes.append(node)
560
561         for node in real_nodes:
562                 preprocess_node(node)
563
564         return real_nodes
565
566 def main(argv):
567         if len(argv) < 3:
568                 print "usage: %s specname(ignored) destdirectory" % argv[0]
569                 sys.exit(1)
570
571         gendir = argv[2]
572         # hardcoded path to libfirm/include/libfirm
573         gendir2 = argv[2] + "/../../include/libfirm"
574
575         # List of TODOs
576         niymap = [ "ASM", "Const", "Phi", "SymConst", "Sync"]
577
578         real_nodes = prepare_nodes()
579         file = open(gendir + "/gen_ir_cons.c.inl", "w")
580         for node in real_nodes:
581                 if node.name in niymap:
582                         continue
583
584                 if not isAbstract(node) and not hasattr(node, "singleton"):
585                         file.write(constructor_template.render(vars()))
586
587                         if hasattr(node, "special_constructors"):
588                                 for special in node.special_constructors:
589                                         node.constrname = special["constrname"]
590                                         special["attr"]["init"] = special["attr"]["special"]["init"]
591                                         file.write(constructor_template.render(vars()))
592         file.write("\n")
593         file.close()
594
595         file = open(gendir + "/gen_irnode.h", "w")
596         file.write(irnode_h_template.render(nodes = real_nodes))
597         file.close()
598
599         file = open(gendir + "/gen_irnode.c.inl", "w")
600         file.write(irnode_template.render(nodes = real_nodes))
601         file.close()
602
603         file = open(gendir + "/gen_irop.c.inl", "w")
604         file.write(irop_template.render(nodes = real_nodes))
605         file.close()
606
607         file = open(gendir2 + "/opcodes.h", "w")
608         file.write(opcodes_h_template.render(nodes = real_nodes))
609         file.close()
610
611         file = open(gendir2 + "/nodeops.h", "w")
612         file.write(nodeops_h_template.render(nodes = real_nodes))
613         file.close()
614
615 main(sys.argv)