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