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