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