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