rework python generators: we can make use of the classes/inheritance language feature...
[libfirm] / scripts / ir_spec.py
1 from spec_util import abstract, setnodedefaults
2
3 class Op(object):
4         "Base class for firm nodes"
5 abstract(Op)
6
7 class Unop(Op):
8         "Unary nodes have exactly 1 input"
9         name     = "unop"
10         ins      = [ "op" ]
11         op_index = 0
12         pinned   = "no"
13 abstract(Unop)
14
15 class Binop(Op):
16         "Binary nodes have exactly 2 inputs"
17         name     = "binop"
18         ins      = [ "left", "right" ]
19         op_index = 0
20         pinned   = "no"
21 abstract(Binop)
22
23 class Abs(Unop):
24         flags = []
25
26 class Add(Binop):
27         flags = ["commutative"]
28
29 class Alloc(Op):
30         ins   = [ "mem", "size" ]
31         outs  = [ "M", "X_regular", "X_except", "res" ]
32         flags = [ "fragile", "uses_memory" ]
33         attrs = [
34                 dict(
35                         name = "type",
36                         type = "ir_type*"
37                 ),
38                 dict(
39                         name = "where",
40                         type = "ir_where_alloc"
41                 )
42         ]
43         pinned      = "yes"
44         attr_struct = "alloc_attr"
45         d_post = '''
46         #if PRECISE_EXC_CONTEXT
47         firm_alloc_frag_arr(res, op_Alloc, &res->attr.alloc.exc.frag_arr);
48         #endif
49         '''
50
51 class Anchor(Op):
52         mode        = "mode_ANY"
53         arity       = "variable"
54         flags       = [ "dump_noblock" ]
55         pinned      = "yes"
56         knownBlock  = True
57         singleton   = True
58
59 class And(Binop):
60         flags    = [ "commutative" ]
61
62 class ASM(Op):
63         mode          = "mode_T"
64         arity         = "variable"
65         flags         = [ "keep", "uses_memory" ]
66         attr_struct   = "asm_attr"
67         pinned        = "memory"
68         pinned_init   = "op_pin_state_pinned"
69         attrs = [
70                 dict(
71                         name = "input_constraints",
72                         type = "ir_asm_constraint*",
73                 ),
74                 dict(
75                         name = "n_output_constraints",
76                         type = "int",
77                 ),
78                 dict(
79                         name = "output_constraints",
80                         type = "ir_asm_constraint*",
81                 ),
82                 dict(
83                         name = "n_clobbers",
84                         type = "int",
85                 ),
86                 dict(
87                         name = "clobbers",
88                         type = "ident**",
89                 ),
90                 dict(
91                         name = "text",
92                         type = "ident*",
93                 ),
94         ]
95         java_noconstr = True
96
97 class Bad(Op):
98         mode       = "mode_Bad"
99         flags      = [ "cfopcode", "fragile", "start_block", "dump_noblock" ]
100         pinned     = "yes"
101         knownBlock = True
102         singleton  = True
103         init = '''
104         res->attr.irg.irg = irg;
105         '''
106
107 class Block(Op):
108         mode        = "mode_BB"
109         knownBlock  = True
110         block       = "NULL"
111         pinned      = "yes"
112         optimize    = False
113         arity       = "variable"
114         flags       = [ "labeled" ]
115         attr_struct = "block_attr"
116         java_noconstr = True
117
118         init = '''
119         /* macroblock header */
120         res->in[0] = res;
121
122         res->attr.block.is_dead     = 0;
123         res->attr.block.is_mb_head  = 1;
124         res->attr.block.irg.irg     = irg;
125         res->attr.block.backedge    = new_backedge_arr(irg->obst, arity);
126         res->attr.block.in_cg       = NULL;
127         res->attr.block.cg_backedge = NULL;
128         res->attr.block.extblk      = NULL;
129         res->attr.block.mb_depth    = 0;
130         res->attr.block.entity      = NULL;
131
132         set_Block_matured(res, 1);
133         set_Block_block_visited(res, 0);
134         '''
135
136         d_pre = '''
137         int i;
138         int has_unknown = 0;
139         '''
140
141         d_post = '''
142         /* Create and initialize array for Phi-node construction. */
143         if (get_irg_phase_state(current_ir_graph) == phase_building) {
144                 res->attr.block.graph_arr = NEW_ARR_D(ir_node *, current_ir_graph->obst,
145                                                       current_ir_graph->n_loc);
146                 memset(res->attr.block.graph_arr, 0, sizeof(ir_node *)*current_ir_graph->n_loc);
147         }
148
149         for (i = arity - 1; i >= 0; i--)
150                 if (is_Unknown(in[i])) {
151                         has_unknown = 1;
152                         break;
153                 }
154
155         if (!has_unknown) res = optimize_node(res);
156
157         current_ir_graph->current_block = res;
158
159         IRN_VRFY_IRG(res, current_ir_graph);
160         '''
161
162         java_add   = '''
163         public void addPred(Node node) {
164                 binding_cons.add_immBlock_pred(ptr, node.ptr);
165         }
166
167         public void mature() {
168                 binding_cons.mature_immBlock(ptr);
169         }
170
171         @Override
172         public Block getBlock() {
173                 return null;
174         }
175
176         public boolean blockVisited() {
177                 return 0 != binding.Block_block_visited(ptr);
178         }
179
180         public void markBlockVisited() {
181                 binding.mark_Block_block_visited(ptr);
182         }
183
184         public boolean isBad() {
185                 return binding.is_Bad(ptr) != 0;
186         }
187         '''
188
189 class Borrow(Binop):
190         flags = []
191
192 class Bound(Op):
193         ins    = [ "mem", "index", "lower", "upper" ]
194         outs   = [ "M", "X_regular", "X_except", "res" ]
195         flags  = [ "fragile", "highlevel" ]
196         pinned = "exception"
197         pinned_init = "op_pin_state_pinned"
198         attr_struct = "bound_attr"
199         d_post = '''
200         #if PRECISE_EXC_CONTEXT
201         firm_alloc_frag_arr(res, op_Bound, &res->attr.bound.exc.frag_arr);
202         #endif
203         '''
204
205 class Break(Op):
206         mode   = "mode_X"
207         flags  = [ "cfopcode" ]
208         pinned = "yes"
209
210 class Builtin(Op):
211         ins      = [ "mem" ]
212         arity    = "variable"
213         outs     = [ "M_regular", "X_regular", "X_except", "T_result", "M_except", "P_value_res_base" ]
214         flags    = [ "uses_memory" ]
215         attrs    = [
216                 dict(
217                         type = "ir_builtin_kind",
218                         name = "kind"
219                 ),
220                 dict(
221                         type = "ir_type*",
222                         name = "type"
223                 )
224         ]
225         pinned      = "memory"
226         pinned_init = "op_pin_state_pinned"
227         attr_struct = "builtin_attr"
228         init   = '''
229         assert((get_unknown_type() == type) || is_Method_type(type));
230         '''
231
232 class Call(Op):
233         ins      = [ "mem", "ptr" ]
234         arity    = "variable"
235         outs     = [ "M_regular", "X_regular", "X_except", "T_result", "M_except", "P_value_res_base" ]
236         flags    = [ "fragile", "uses_memory" ]
237         attrs    = [
238                 dict(
239                         type = "ir_type*",
240                         name = "type"
241                 )
242         ]
243         attr_struct = "call_attr"
244         pinned      = "memory"
245         pinned_init = "op_pin_state_pinned"
246         init = '''
247         assert((get_unknown_type() == type) || is_Method_type(type));
248         '''
249         d_post = '''
250         #if PRECISE_EXC_CONTEXT
251         firm_alloc_frag_arr(res, op_Call, &res->attr.call.exc.frag_arr);
252         #endif
253         '''
254
255 class CallBegin(Op):
256         ins   = [ "ptr" ]
257         outs  = [ "" ] # TODO
258         flags         = [ "cfopcode", "ip_cfopcode" ]
259         pinned        = "yes"
260         # TODO: attribute with call...
261         attr_struct   = "callbegin_attr"
262         attrs         = [
263                 dict(
264                         type = "ir_node*",
265                         name = "call"
266                 )
267         ]
268         java_noconstr = True
269
270 class Carry(Binop):
271         flags = [ "commutative" ]
272
273 class Cast(Op):
274         ins      = [ "op" ]
275         mode     = "get_irn_mode(irn_op)"
276         flags    = [ "highlevel" ]
277         pinned   = "no"
278         attrs    = [
279                 dict(
280                         type = "ir_type*",
281                         name = "type"
282                 )
283         ]
284         attr_struct = "cast_attr"
285         init     = "assert(is_atomic_type(type));"
286
287 class Cmp(Binop):
288         outs  = [ "False", "Eq", "Lt", "Le", "Gt", "Ge", "Lg", "Leg", "Uo", "Ue", "Ul", "Ule", "Ug", "Uge", "Ne", "True" ]
289         flags = []
290
291 class Cond(Op):
292         ins      = [ "selector" ]
293         outs     = [ "false", "true" ]
294         flags    = [ "cfopcode", "forking" ]
295         pinned   = "yes"
296         attrs    = [
297                 dict(
298                         name = "kind",
299                         type = "cond_kind",
300                         init = "dense"
301                 ),
302                 dict(
303                         name = "default_proj",
304                         type = "long",
305                         init = "0"
306                 ),
307                 dict(
308                         name = "jmp_pred",
309                         type = "cond_jmp_predicate",
310                         init = "COND_JMP_PRED_NONE"
311                 )
312         ]
313         attr_struct = "cond_attr"
314
315 class Confirm(Op):
316         ins      = [ "value", "bound" ]
317         mode     = "get_irn_mode(irn_value)"
318         flags    = [ "highlevel" ]
319         pinned   = "yes"
320         attrs    = [
321                 dict(
322                         name = "cmp",
323                         type = "pn_Cmp"
324                 ),
325         ]
326         attr_struct = "confirm_attr"
327
328 class Const(Op):
329         mode       = ""
330         flags      = [ "constlike", "start_block" ]
331         knownBlock = True
332         pinned     = "no"
333         attrs_name = "con"
334         attrs      = [
335                 dict(
336                         type = "tarval*",
337                         name = "tarval",
338                 )
339         ]
340         attr_struct = "const_attr"
341
342 class Conv(Unop):
343         flags = []
344         attrs = [
345                 dict(
346                         name = "strict",
347                         type = "int",
348                         init = "0",
349                         special = dict(
350                                 prefix = "strict",
351                                 init = "1"
352                         )
353                 )
354         ]
355         attr_struct = "conv_attr"
356
357 class CopyB(Op):
358         ins   = [ "mem", "dst", "src" ]
359         outs  = [ "M", "X_regular", "X_except" ]
360         flags = [ "fragile", "highlevel", "uses_memory" ]
361         attrs = [
362                 dict(
363                         name = "type",
364                         type = "ir_type*"
365                 )
366         ]
367         attr_struct = "copyb_attr"
368         pinned      = "memory"
369         pinned_init = "op_pin_state_pinned"
370         d_post = '''
371         #if PRECISE_EXC_CONTEXT
372         firm_alloc_frag_arr(res, op_CopyB, &res->attr.copyb.exc.frag_arr);
373         #endif
374         '''
375
376 class Div(Op):
377         ins   = [ "mem", "left", "right" ]
378         outs  = [ "M", "X_regular", "X_except", "res" ]
379         flags = [ "fragile", "uses_memory" ]
380         attrs_name = "divmod"
381         attrs = [
382                 dict(
383                         type = "ir_mode*",
384                         name = "resmode"
385                 ),
386                 dict(
387                         name = "no_remainder",
388                         type = "int",
389                         init = "0",
390                         special = dict(
391                                 suffix = "RL",
392                                 init = "1"
393                         )
394                 )
395         ]
396         attr_struct = "divmod_attr"
397         pinned      = "exception"
398         op_index    = 1
399         arity_override = "oparity_binary"
400         d_post = '''
401         #if PRECISE_EXC_CONTEXT
402         firm_alloc_frag_arr(res, op_Div, &res->attr.except.frag_arr);
403         #endif
404         '''
405
406 class DivMod(Op):
407         ins   = [ "mem", "left", "right" ]
408         outs  = [ "M", "X_regular", "X_except", "res_div", "res_mod" ]
409         flags = [ "fragile", "uses_memory" ]
410         attrs_name = "divmod"
411         attrs = [
412                 dict(
413                         type = "ir_mode*",
414                         name = "resmode"
415                 ),
416         ]
417         attr_struct = "divmod_attr"
418         pinned      = "exception"
419         op_index    = 1
420         arity_override = "oparity_binary"
421         d_post = '''
422         #if PRECISE_EXC_CONTEXT
423         firm_alloc_frag_arr(res, op_DivMod, &res->attr.except.frag_arr);
424         #endif
425         '''
426
427 class Dummy(Op):
428         ins   = []
429         flags = [ "cfopcode", "fragile", "start_block", "constlike",
430                   "dump_noblock" ]
431         knownBlock = True
432         pinned     = "yes"
433         block      = "get_irg_start_block(irg)"
434
435 class End(Op):
436         mode       = "mode_X"
437         pinned     = "yes"
438         arity      = "dynamic"
439         flags      = [ "cfopcode" ]
440         singleton  = True
441
442 class EndExcept(Op):
443         mode      = "mode_X"
444         pinned    = "yes"
445         arity     = "dynamic"
446         flags     = [ "cfopcode", "ip_cfopcode" ]
447         singleton = True
448
449 class EndReg(Op):
450         mode      = "mode_X"
451         pinned    = "yes"
452         arity     = "dynamic"
453         flags     = [ "cfopcode", "ip_cfopcode" ]
454         singleton = True
455
456 class Eor(Binop):
457         flags    = [ "commutative" ]
458
459 class Filter(Op):
460         ins   = [ "pred" ]
461         flags = []
462         attrs = [
463                 dict(
464                         name = "proj",
465                         type = "long"
466                 )
467         ]
468         pinned      = "yes"
469         attr_struct = "filter_attr"
470         java_noconstr = True
471
472 class Free(Op):
473         ins    = [ "mem", "ptr", "size" ]
474         mode   = "mode_M"
475         flags  = [ "uses_memory" ]
476         pinned = "yes"
477         attrs  = [
478                 dict(
479                         name = "type",
480                         type = "ir_type*"
481                 ),
482                 dict(
483                         name = "where",
484                         type = "ir_where_alloc"
485                 )
486         ]
487         attr_struct = "free_attr"
488
489 class Id(Op):
490         ins    = [ "pred" ]
491         pinned = "no"
492         flags  = []
493
494 class IJmp(Op):
495         mode     = "mode_X"
496         pinned   = "yes"
497         ins      = [ "target" ]
498         flags    = [ "cfopcode", "forking", "keep" ]
499
500 class InstOf(Op):
501         ins   = [ "store", "obj" ]
502         outs  = [ "M", "X_regular", "X_except", "res", "M_except" ]
503         flags = [ "highlevel" ]
504         attrs = [
505                 dict(
506                         name = "type",
507                         type = "ir_type*"
508                 )
509         ]
510         attr_struct = "io_attr"
511         pinned      = "memory"
512         pinned_init = "op_pin_state_floats"
513
514 class Jmp(Op):
515         mode     = "mode_X"
516         pinned   = "yes"
517         ins      = []
518         flags    = [ "cfopcode" ]
519
520 class Load(Op):
521         ins      = [ "mem", "ptr" ]
522         outs     = [ "M", "X_regular", "X_except", "res" ]
523         flags    = [ "fragile", "uses_memory" ]
524         pinned   = "exception"
525         pinned_init = "flags & cons_floats ? op_pin_state_floats : op_pin_state_pinned"
526         attrs    = [
527                 dict(
528                         type = "ir_mode*",
529                         name = "mode",
530                         java_name = "load_mode"
531                 ),
532         ]
533         attr_struct = "load_attr"
534         constructor_args = [
535                 dict(
536                         type = "ir_cons_flags",
537                         name = "flags",
538                 ),
539         ]
540         d_post = '''
541 #if PRECISE_EXC_CONTEXT
542         firm_alloc_frag_arr(res, op_Load, &res->attr.load.exc.frag_arr);
543 #endif
544         '''
545
546 class Minus(Unop):
547         flags = []
548
549 class Mod(Op):
550         ins   = [ "mem", "left", "right" ]
551         outs  = [ "M", "X_regular", "X_except", "res" ]
552         flags = [ "fragile", "uses_memory" ]
553         attrs_name = "divmod"
554         attrs = [
555                 dict(
556                         type = "ir_mode*",
557                         name = "resmode"
558                 ),
559         ]
560         attr_struct = "divmod_attr"
561         pinned      = "exception"
562         op_index    = 1
563         arity_override = "oparity_binary"
564         d_post = '''
565         #if PRECISE_EXC_CONTEXT
566         firm_alloc_frag_arr(res, op_Mod, &res->attr.except.frag_arr);
567         #endif
568         '''
569
570 class Mul(Binop):
571         flags = [ "commutative" ]
572
573 class Mulh(Binop):
574         flags = [ "commutative" ]
575
576 class Mux(Op):
577         ins    = [ "sel", "false", "true" ]
578         flags  = []
579         pinned = "no"
580
581 class NoMem(Op):
582         mode       = "mode_M"
583         flags      = [ "dump_noblock", "dump_noinput" ]
584         pinned     = "yes"
585         knownBlock = True
586         singleton  = True
587
588 class Not(Unop):
589         flags = []
590
591 class Or(Binop):
592         flags = [ "commutative" ]
593
594 class Phi(Op):
595         pinned      = "yes"
596         arity       = "variable"
597         flags       = []
598         attr_struct = "phi_attr"
599         custom_is   = True
600         java_noconstr = True
601         init = '''
602         /* Memory Phis in endless loops must be kept alive.
603            As we can't distinguish these easily we keep all of them alive. */
604         if (is_Phi(res) && mode == mode_M)
605                 add_End_keepalive(get_irg_end(irg), res);
606         '''
607
608 class Pin(Op):
609         ins      = [ "op" ]
610         mode     = "get_irn_mode(irn_op)"
611         flags    = [ "highlevel" ]
612         pinned   = "yes"
613
614 class Proj(Op):
615         ins      = [ "pred" ]
616         flags    = []
617         pinned   = "no"
618         attrs    = [
619                 dict(
620                         type = "long",
621                         name = "proj",
622                         initname = ""
623                 )
624         ]
625         attr_struct = "long"
626         custom_is   = True
627
628 class Quot(Op):
629         ins   = [ "mem", "left", "right" ]
630         outs  = [ "M", "X_regular", "X_except", "res" ]
631         flags = [ "fragile", "uses_memory" ]
632         attrs_name = "divmod"
633         attrs = [
634                 dict(
635                         type = "ir_mode*",
636                         name = "resmode"
637                 ),
638         ]
639         attr_struct = "divmod_attr"
640         pinned      = "exception"
641         op_index    = 1
642         arity_override = "oparity_binary"
643         d_post = '''
644         #if PRECISE_EXC_CONTEXT
645         firm_alloc_frag_arr(res, op_Quot, &res->attr.except.frag_arr);
646         #endif
647         '''
648
649 class Raise(Op):
650         ins    = [ "mem", "exo_ptr" ]
651         outs   = [ "M", "X" ]
652         flags  = [ "highlevel", "cfopcode" ]
653         pinned = "yes"
654
655 class Return(Op):
656         ins      = [ "mem" ]
657         arity    = "variable"
658         mode     = "mode_X"
659         flags    = [ "cfopcode" ]
660         pinned   = "yes"
661
662 class Rotl(Binop):
663         flags    = []
664
665 class Sel(Op):
666         ins    = [ "mem", "ptr" ]
667         arity  = "variable"
668         flags  = []
669         mode   = "is_Method_type(get_entity_type(entity)) ? mode_P_code : mode_P_data"
670         pinned = "no"
671         attrs  = [
672                 dict(
673                         type = "ir_entity*",
674                         name = "entity"
675                 )
676         ]
677         attr_struct = "sel_attr"
678
679 class Shl(Binop):
680         flags = []
681
682 class Shr(Binop):
683         flags = []
684
685 class Shrs(Binop):
686         flags = []
687
688 class Start(Op):
689         mode       = "mode_T"
690         pinned     = "yes"
691         flags      = [ "cfopcode" ]
692         singleton  = True
693
694 class Store(Op):
695         ins      = [ "mem", "ptr", "value" ]
696         outs     = [ "M", "X_regular", "X_except" ]
697         flags    = [ "fragile", "uses_memory" ]
698         pinned   = "exception"
699         attr_struct = "store_attr"
700         pinned_init = "flags & cons_floats ? op_pin_state_floats : op_pin_state_pinned"
701         constructor_args = [
702                 dict(
703                         type = "ir_cons_flags",
704                         name = "flags",
705                 ),
706         ]
707         d_post = '''
708 #if PRECISE_EXC_CONTEXT
709         firm_alloc_frag_arr(res, op_Store, &res->attr.store.exc.frag_arr);
710 #endif
711         '''
712
713 class Sub(Binop):
714         flags = []
715
716 class SymConst(Op):
717         mode       = "mode_P"
718         flags      = [ "constlike", "start_block" ]
719         knownBlock = True
720         pinned     = "no"
721         attrs      = [
722                 dict(
723                         type = "ir_entity*",
724                         name = "entity"
725                 )
726         ]
727         attr_struct = "symconst_attr"
728         java_noconstr = True
729
730 class Sync(Op):
731         mode     = "mode_M"
732         flags    = []
733         pinned   = "no"
734         optimize = False
735         arity    = "dynamic"
736
737 class Tuple(Op):
738         arity  = "variable"
739         mode   = "mode_T"
740         pinned = "no"
741         flags  = [ "labeled" ]
742         java_noconstr = True
743
744 class Unknown(Op):
745         knownBlock = True
746         pinned     = "yes"
747         block      = "get_irg_start_block(irg)"
748         flags      = [ "cfopcode", "fragile", "start_block", "constlike",
749                        "dump_noblock" ]
750
751 # Prepare node list
752
753 def getOpList(namespace):
754         nodes = []
755         for t in namespace.values():
756                 if type(t) != type:
757                         continue
758
759                 if issubclass(t, Op):
760                         setnodedefaults(t)
761                         nodes.append(t)
762         return nodes
763
764 nodes = getOpList(globals())
765 nodes = sorted(nodes, lambda x,y: cmp(x.name, y.name))