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