Fixed doxygen comments for ir_printf and friends, fixed printf attribute handling.
[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         noconstructor    = True
57         customSerializer = 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         customSerializer = True
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
100 class Bad(Op):
101         mode          = "mode_T"
102         flags         = [ "cfopcode", "start_block", "dump_noblock" ]
103         pinned        = "yes"
104         knownBlock    = True
105         block         = "get_irg_start_block(irg)"
106         singleton     = True
107         attr_struct   = "bad_attr"
108         init = '''
109         res->attr.bad.irg.irg = irg;
110         '''
111
112 class Deleted(Op):
113         mode             = "mode_Bad"
114         flags            = [ ]
115         pinned           = "yes"
116         noconstructor    = True
117         customSerializer = True
118
119 class Block(Op):
120         mode             = "mode_BB"
121         knownBlock       = True
122         block            = "NULL"
123         pinned           = "yes"
124         arity            = "variable"
125         flags            = [ "labeled" ]
126         attr_struct      = "block_attr"
127         customSerializer = True
128
129         init = '''
130         res->attr.block.irg.irg     = irg;
131         res->attr.block.backedge    = new_backedge_arr(irg->obst, arity);
132         set_Block_matured(res, 1);
133
134         /* Create and initialize array for Phi-node construction. */
135         if (get_irg_phase_state(irg) == phase_building) {
136                 res->attr.block.graph_arr = NEW_ARR_D(ir_node *, irg->obst, irg->n_loc);
137                 memset(res->attr.block.graph_arr, 0, irg->n_loc * sizeof(ir_node*));
138         }
139         '''
140
141         java_add   = '''
142         public void addPred(Node node) {
143                 binding_ircons.add_immBlock_pred(ptr, node.ptr);
144         }
145
146         public void mature() {
147                 binding_ircons.mature_immBlock(ptr);
148         }
149
150         @Override
151         public Block getBlock() {
152                 return null;
153         }
154
155         public boolean blockVisited() {
156                 return 0 != binding_irnode.Block_block_visited(ptr);
157         }
158
159         public void markBlockVisited() {
160                 binding_irnode.mark_Block_block_visited(ptr);
161         }
162
163         public boolean isBad() {
164                 return binding_irnode.is_Bad(ptr) != 0;
165         }
166         '''
167
168 class Borrow(Binop):
169         flags = []
170
171 class Bound(Op):
172         ins    = [ "mem", "index", "lower", "upper" ]
173         outs  = [
174                 ("M",         "memory result",                         "pn_Generic_M"),
175                 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
176                 ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
177                 ("res",       "the checked index",                     "pn_Generic_other"),
178         ]
179         flags  = [ "fragile", "highlevel" ]
180         pinned = "exception"
181         pinned_init = "op_pin_state_pinned"
182         attr_struct = "bound_attr"
183         attrs_name  = "bound"
184
185 class Builtin(Op):
186         ins      = [ "mem" ]
187         arity    = "variable"
188         outs     = [
189                 ("M",        "memory result", "pn_Generic_M"),
190                 ("1_result", "first result",  "pn_Generic_other"),
191         ]
192         flags    = [ "uses_memory" ]
193         attrs    = [
194                 dict(
195                         type = "ir_builtin_kind",
196                         name = "kind"
197                 ),
198                 dict(
199                         type = "ir_type*",
200                         name = "type"
201                 )
202         ]
203         pinned      = "memory"
204         pinned_init = "op_pin_state_pinned"
205         attr_struct = "builtin_attr"
206         init   = '''
207         assert((get_unknown_type() == type) || is_Method_type(type));
208         '''
209
210 class Call(Op):
211         ins      = [ "mem", "ptr" ]
212         arity    = "variable"
213         outs     = [
214                 ("M",                "memory result",                         "pn_Generic_M"),
215                 ("X_regular",        "control flow when no exception occurs", "pn_Generic_X_regular"),
216                 ("X_except",         "control flow when exception occured",   "pn_Generic_X_except"),
217                 ("T_result",         "tuple containing all results",          "pn_Generic_other"),
218                 ("P_value_res_base", "pointer to memory register containing copied results passed by value"),
219         ]
220         flags    = [ "fragile", "uses_memory" ]
221         attrs    = [
222                 dict(
223                         type = "ir_type*",
224                         name = "type"
225                 ),
226                 dict(
227                         type = "unsigned",
228                         name = "tail_call",
229                         # the tail call attribute can only be set by analysis
230                         init = "0"
231                 )
232         ]
233         attr_struct = "call_attr"
234         pinned      = "memory"
235         pinned_init = "op_pin_state_pinned"
236         init = '''
237         assert((get_unknown_type() == type) || is_Method_type(type));
238         '''
239
240 class Carry(Binop):
241         flags = [ "commutative" ]
242
243 class Cast(Unop):
244         mode     = "get_irn_mode(irn_op)"
245         flags    = [ "highlevel" ]
246         attrs    = [
247                 dict(
248                         type = "ir_type*",
249                         name = "type"
250                 )
251         ]
252         attr_struct = "cast_attr"
253         init     = "assert(is_atomic_type(type));"
254
255 class Cmp(Binop):
256         outs  = [
257                 ("False", "always false",                            "0"),
258                 ("Eq",    "equal",                                   "1"),
259                 ("Lt",    "less",                                    "2"),
260                 ("Le",    "less or equal",                           "pn_Cmp_Eq|pn_Cmp_Lt"),
261                 ("Gt",    "greater",                                 "4"),
262                 ("Ge",    "greater or equal",                        "pn_Cmp_Eq|pn_Cmp_Gt"),
263                 ("Lg",    "less or greater ('not equal' for integer numbers)", "pn_Cmp_Lt|pn_Cmp_Gt"),
264                 ("Leg",   "less, equal or greater ('not unordered')", "pn_Cmp_Lt|pn_Cmp_Eq|pn_Cmp_Gt"),
265                 ("Uo",    "unordered",                               "8"),
266                 ("Ue",    "unordered or equal",                      "pn_Cmp_Uo|pn_Cmp_Eq"),
267                 ("Ul",    "unordered or less",                       "pn_Cmp_Uo|pn_Cmp_Lt"),
268                 ("Ule",   "unordered, less or equal",                "pn_Cmp_Uo|pn_Cmp_Lt|pn_Cmp_Eq"),
269                 ("Ug",    "unordered or greater",                    "pn_Cmp_Uo|pn_Cmp_Gt"),
270                 ("Uge",   "onordered, greater or equal",             "pn_Cmp_Uo|pn_Cmp_Gt|pn_Cmp_Eq"),
271                 ("Ne",    "unordered, less or greater ('not equal' for floatingpoint numbers)", "pn_Cmp_Uo|pn_Cmp_Lt|pn_Cmp_Gt"),
272                 ("True",  "always true",                             "15"),
273         ]
274         flags = []
275
276 class Cond(Op):
277         ins      = [ "selector" ]
278         outs     = [
279                 ("false", "control flow if operand is \"false\""),
280                 ("true",  "control flow if operand is \"true\""),
281         ]
282         flags    = [ "cfopcode", "forking" ]
283         pinned   = "yes"
284         attrs    = [
285                 dict(
286                         name = "default_proj",
287                         type = "long",
288                         init = "0"
289                 ),
290                 dict(
291                         name = "jmp_pred",
292                         type = "cond_jmp_predicate",
293                         init = "COND_JMP_PRED_NONE"
294                 )
295         ]
296         attr_struct = "cond_attr"
297
298 class Confirm(Op):
299         ins      = [ "value", "bound" ]
300         mode     = "get_irn_mode(irn_value)"
301         flags    = [ "highlevel" ]
302         pinned   = "yes"
303         attrs    = [
304                 dict(
305                         name = "cmp",
306                         type = "pn_Cmp"
307                 ),
308         ]
309         attr_struct = "confirm_attr"
310         attrs_name  = "confirm"
311
312 class Const(Op):
313         mode       = ""
314         flags      = [ "constlike", "start_block" ]
315         knownBlock = True
316         pinned     = "no"
317         attrs_name = "con"
318         attrs      = [
319                 dict(
320                         type = "ir_tarval*",
321                         name = "tarval",
322                 )
323         ]
324         attr_struct = "const_attr"
325
326 class Conv(Unop):
327         flags = []
328         attrs = [
329                 dict(
330                         name = "strict",
331                         type = "int",
332                         init = "0",
333                         special = dict(
334                                 prefix = "strict",
335                                 init = "1"
336                         )
337                 )
338         ]
339         attr_struct = "conv_attr"
340         attrs_name  = "conv"
341
342 class CopyB(Op):
343         ins   = [ "mem", "dst", "src" ]
344         outs  = [
345                 ("M",         "memory result",                         "pn_Generic_M"),
346                 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
347                 ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
348         ]
349         flags = [ "fragile", "highlevel", "uses_memory" ]
350         attrs = [
351                 dict(
352                         name = "type",
353                         type = "ir_type*"
354                 )
355         ]
356         attr_struct = "copyb_attr"
357         attrs_name  = "copyb"
358         pinned      = "memory"
359         pinned_init = "op_pin_state_pinned"
360
361 class Div(Op):
362         ins   = [ "mem", "left", "right" ]
363         outs  = [
364                 ("M",         "memory result",                         "pn_Generic_M"),
365                 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
366                 ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
367                 ("res",       "result of computation",                 "pn_Generic_other"),
368         ]
369         flags = [ "fragile", "uses_memory" ]
370         attrs_name = "divmod"
371         attrs = [
372                 dict(
373                         type = "ir_mode*",
374                         name = "resmode"
375                 ),
376                 dict(
377                         name = "no_remainder",
378                         type = "int",
379                         init = "0",
380                         special = dict(
381                                 suffix = "RL",
382                                 init = "1"
383                         )
384                 )
385         ]
386         attr_struct = "divmod_attr"
387         pinned      = "exception"
388         op_index    = 1
389         arity_override = "oparity_binary"
390
391 class DivMod(Op):
392         ins   = [ "mem", "left", "right" ]
393         outs  = [
394                 ("M",         "memory result",                         "pn_Generic_M"),
395                 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
396                 ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
397                 ("res_div",   "result of computation a/b",             "pn_Generic_other"),
398                 ("res_mod",   "result of computation a%b"),
399         ]
400         flags = [ "fragile", "uses_memory" ]
401         attrs_name = "divmod"
402         attrs = [
403                 dict(
404                         type = "ir_mode*",
405                         name = "resmode"
406                 ),
407         ]
408         attr_struct = "divmod_attr"
409         pinned      = "exception"
410         op_index    = 1
411         arity_override = "oparity_binary"
412
413 class Dummy(Op):
414         ins        = []
415         flags      = [ "cfopcode", "start_block", "constlike", "dump_noblock" ]
416         knownBlock = True
417         pinned     = "yes"
418         block      = "get_irg_start_block(irg)"
419
420 class End(Op):
421         mode             = "mode_X"
422         pinned           = "yes"
423         arity            = "dynamic"
424         flags            = [ "cfopcode" ]
425         knownBlock       = True
426         block            = "get_irg_end_block(irg)"
427         singleton        = True
428         customSerializer = 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         block         = "get_irg_start_block(irg)"
553         singleton     = True
554
555 class Not(Unop):
556         flags = []
557
558 class Or(Binop):
559         flags = [ "commutative" ]
560
561 class Phi(Op):
562         pinned        = "yes"
563         arity         = "variable"
564         flags         = []
565         attr_struct   = "phi_attr"
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         customSerializer = True
588         attrs      = [
589                 dict(
590                         type = "long",
591                         name = "proj",
592                         initname = "",
593                         noprop = False,
594                 )
595         ]
596         attr_struct = "long"
597
598 class Quot(Op):
599         ins   = [ "mem", "left", "right" ]
600         outs  = [
601                 ("M",         "memory result",                         "pn_Generic_M"),
602                 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
603                 ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
604                 ("res",       "result of computation",                 "pn_Generic_other"),
605         ]
606         flags = [ "fragile", "uses_memory" ]
607         attrs_name = "divmod"
608         attrs = [
609                 dict(
610                         type = "ir_mode*",
611                         name = "resmode"
612                 ),
613         ]
614         attr_struct = "divmod_attr"
615         pinned      = "exception"
616         op_index    = 1
617         arity_override = "oparity_binary"
618
619 class Raise(Op):
620         ins    = [ "mem", "exo_ptr" ]
621         outs  = [
622                 ("M", "memory result",                     "pn_Generic_M"),
623                 ("X", "control flow to exception handler", "pn_Generic_X_regular"),
624         ]
625         flags  = [ "highlevel", "cfopcode" ]
626         pinned = "yes"
627
628 class Return(Op):
629         ins      = [ "mem" ]
630         arity    = "variable"
631         mode     = "mode_X"
632         flags    = [ "cfopcode" ]
633         pinned   = "yes"
634
635 class Rotl(Binop):
636         flags    = []
637
638 class Sel(Op):
639         ins    = [ "mem", "ptr" ]
640         arity  = "variable"
641         flags  = []
642         mode   = "is_Method_type(get_entity_type(entity)) ? mode_P_code : mode_P_data"
643         pinned = "no"
644         attrs  = [
645                 dict(
646                         type = "ir_entity*",
647                         name = "entity"
648                 )
649         ]
650         attr_struct = "sel_attr"
651
652 class Shl(Binop):
653         flags = []
654
655 class Shr(Binop):
656         flags = []
657
658 class Shrs(Binop):
659         flags = []
660
661 class Start(Op):
662         outs       = [
663                 ("X_initial_exec", "control flow"),
664                 ("M",              "initial memory"),
665                 ("P_frame_base",   "frame base pointer"),
666                 ("P_tls",          "pointer to thread local storage segment"),
667                 ("T_args",         "function arguments")
668         ]
669         mode             = "mode_T"
670         pinned           = "yes"
671         flags            = [ "cfopcode" ]
672         singleton        = True
673         knownBlock       = True
674         customSerializer = True
675         block            = "get_irg_start_block(irg)"
676
677 class Store(Op):
678         ins      = [ "mem", "ptr", "value" ]
679         outs  = [
680                 ("M",         "memory result",                         "pn_Generic_M"),
681                 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
682                 ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
683         ]
684         flags    = [ "fragile", "uses_memory" ]
685         pinned   = "exception"
686         attr_struct = "store_attr"
687         pinned_init = "flags & cons_floats ? op_pin_state_floats : op_pin_state_pinned"
688         constructor_args = [
689                 dict(
690                         type = "ir_cons_flags",
691                         name = "flags",
692                 ),
693         ]
694
695 class Sub(Binop):
696         flags = []
697
698 class SymConst(Op):
699         mode       = "mode_P"
700         flags      = [ "constlike", "start_block" ]
701         knownBlock = True
702         pinned     = "no"
703         attrs      = [
704                 dict(
705                         type = "ir_entity*",
706                         name = "entity",
707                         noprop = True
708                 )
709         ]
710         attr_struct = "symconst_attr"
711         customSerializer = True
712
713 class Sync(Op):
714         mode     = "mode_M"
715         flags    = []
716         pinned   = "no"
717         arity    = "dynamic"
718
719 class Tuple(Op):
720         arity  = "variable"
721         mode   = "mode_T"
722         pinned = "no"
723         flags  = [ "labeled" ]
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))