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