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