Leave a bit space between cases.
[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", "X_regular", "X_except", "T_result", "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", "X_regular", "X_except", "T_result", "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(Unop):
275         mode     = "get_irn_mode(irn_op)"
276         flags    = [ "highlevel" ]
277         attrs    = [
278                 dict(
279                         type = "ir_type*",
280                         name = "type"
281                 )
282         ]
283         attr_struct = "cast_attr"
284         init     = "assert(is_atomic_type(type));"
285
286 class Cmp(Binop):
287         outs  = [ "False", "Eq", "Lt", "Le", "Gt", "Ge", "Lg", "Leg", "Uo", "Ue", "Ul", "Ule", "Ug", "Uge", "Ne", "True" ]
288         flags = []
289
290 class Cond(Op):
291         ins      = [ "selector" ]
292         outs     = [ "false", "true" ]
293         flags    = [ "cfopcode", "forking" ]
294         pinned   = "yes"
295         attrs    = [
296                 dict(
297                         name = "default_proj",
298                         type = "long",
299                         init = "0"
300                 ),
301                 dict(
302                         name = "jmp_pred",
303                         type = "cond_jmp_predicate",
304                         init = "COND_JMP_PRED_NONE"
305                 )
306         ]
307         attr_struct = "cond_attr"
308
309 class Confirm(Op):
310         ins      = [ "value", "bound" ]
311         mode     = "get_irn_mode(irn_value)"
312         flags    = [ "highlevel" ]
313         pinned   = "yes"
314         attrs    = [
315                 dict(
316                         name = "cmp",
317                         type = "pn_Cmp"
318                 ),
319         ]
320         attr_struct = "confirm_attr"
321
322 class Const(Op):
323         mode       = ""
324         flags      = [ "constlike", "start_block" ]
325         knownBlock = True
326         pinned     = "no"
327         attrs_name = "con"
328         attrs      = [
329                 dict(
330                         type = "tarval*",
331                         name = "tarval",
332                 )
333         ]
334         attr_struct = "const_attr"
335
336 class Conv(Unop):
337         flags = []
338         attrs = [
339                 dict(
340                         name = "strict",
341                         type = "int",
342                         init = "0",
343                         special = dict(
344                                 prefix = "strict",
345                                 init = "1"
346                         )
347                 )
348         ]
349         attr_struct = "conv_attr"
350
351 class CopyB(Op):
352         ins   = [ "mem", "dst", "src" ]
353         outs  = [ "M", "X_regular", "X_except" ]
354         flags = [ "fragile", "highlevel", "uses_memory" ]
355         attrs = [
356                 dict(
357                         name = "type",
358                         type = "ir_type*"
359                 )
360         ]
361         attr_struct = "copyb_attr"
362         pinned      = "memory"
363         pinned_init = "op_pin_state_pinned"
364         d_post = '''
365         firm_alloc_frag_arr(res, op_CopyB, &res->attr.copyb.exc.frag_arr);
366         '''
367
368 class Div(Op):
369         ins   = [ "mem", "left", "right" ]
370         outs  = [ "M", "X_regular", "X_except", "res" ]
371         flags = [ "fragile", "uses_memory" ]
372         attrs_name = "divmod"
373         attrs = [
374                 dict(
375                         type = "ir_mode*",
376                         name = "resmode"
377                 ),
378                 dict(
379                         name = "no_remainder",
380                         type = "int",
381                         init = "0",
382                         special = dict(
383                                 suffix = "RL",
384                                 init = "1"
385                         )
386                 )
387         ]
388         attr_struct = "divmod_attr"
389         pinned      = "exception"
390         op_index    = 1
391         arity_override = "oparity_binary"
392         d_post = '''
393         firm_alloc_frag_arr(res, op_Div, &res->attr.except.frag_arr);
394         '''
395
396 class DivMod(Op):
397         ins   = [ "mem", "left", "right" ]
398         outs  = [ "M", "X_regular", "X_except", "res_div", "res_mod" ]
399         flags = [ "fragile", "uses_memory" ]
400         attrs_name = "divmod"
401         attrs = [
402                 dict(
403                         type = "ir_mode*",
404                         name = "resmode"
405                 ),
406         ]
407         attr_struct = "divmod_attr"
408         pinned      = "exception"
409         op_index    = 1
410         arity_override = "oparity_binary"
411         d_post = '''
412         firm_alloc_frag_arr(res, op_DivMod, &res->attr.except.frag_arr);
413         '''
414
415 class Dummy(Op):
416         ins   = []
417         flags = [ "cfopcode", "fragile", "start_block", "constlike",
418                   "dump_noblock" ]
419         knownBlock = True
420         pinned     = "yes"
421         block      = "get_irg_start_block(irg)"
422
423 class End(Op):
424         mode       = "mode_X"
425         pinned     = "yes"
426         arity      = "dynamic"
427         flags      = [ "cfopcode" ]
428         singleton  = True
429
430 class EndExcept(Op):
431         mode      = "mode_X"
432         pinned    = "yes"
433         arity     = "dynamic"
434         flags     = [ "cfopcode", "ip_cfopcode" ]
435         singleton = True
436
437 class EndReg(Op):
438         mode      = "mode_X"
439         pinned    = "yes"
440         arity     = "dynamic"
441         flags     = [ "cfopcode", "ip_cfopcode" ]
442         singleton = True
443
444 class Eor(Binop):
445         flags    = [ "commutative" ]
446
447 class Filter(Op):
448         ins   = [ "pred" ]
449         flags = []
450         attrs = [
451                 dict(
452                         name = "proj",
453                         type = "long"
454                 )
455         ]
456         pinned      = "yes"
457         attr_struct = "filter_attr"
458         java_noconstr = True
459
460 class Free(Op):
461         ins    = [ "mem", "ptr", "size" ]
462         mode   = "mode_M"
463         flags  = [ "uses_memory" ]
464         pinned = "yes"
465         attrs  = [
466                 dict(
467                         name = "type",
468                         type = "ir_type*"
469                 ),
470                 dict(
471                         name = "where",
472                         type = "ir_where_alloc"
473                 )
474         ]
475         attr_struct = "free_attr"
476
477 class Id(Op):
478         ins    = [ "pred" ]
479         pinned = "no"
480         flags  = []
481
482 class IJmp(Op):
483         mode     = "mode_X"
484         pinned   = "yes"
485         ins      = [ "target" ]
486         flags    = [ "cfopcode", "forking", "keep" ]
487
488 class InstOf(Op):
489         ins   = [ "store", "obj" ]
490         outs  = [ "M", "X_regular", "X_except", "res" ]
491         flags = [ "highlevel" ]
492         attrs = [
493                 dict(
494                         name = "type",
495                         type = "ir_type*"
496                 )
497         ]
498         attr_struct = "io_attr"
499         pinned      = "memory"
500         pinned_init = "op_pin_state_floats"
501
502 class Jmp(Op):
503         mode     = "mode_X"
504         pinned   = "yes"
505         ins      = []
506         flags    = [ "cfopcode" ]
507
508 class Load(Op):
509         ins      = [ "mem", "ptr" ]
510         outs     = [ "M", "X_regular", "X_except", "res" ]
511         flags    = [ "fragile", "uses_memory" ]
512         pinned   = "exception"
513         pinned_init = "flags & cons_floats ? op_pin_state_floats : op_pin_state_pinned"
514         attrs    = [
515                 dict(
516                         type = "ir_mode*",
517                         name = "mode",
518                         java_name = "load_mode"
519                 ),
520         ]
521         attr_struct = "load_attr"
522         constructor_args = [
523                 dict(
524                         type = "ir_cons_flags",
525                         name = "flags",
526                 ),
527         ]
528         d_post = '''
529         firm_alloc_frag_arr(res, op_Load, &res->attr.load.exc.frag_arr);
530         '''
531
532 class Minus(Unop):
533         flags = []
534
535 class Mod(Op):
536         ins   = [ "mem", "left", "right" ]
537         outs  = [ "M", "X_regular", "X_except", "res" ]
538         flags = [ "fragile", "uses_memory" ]
539         attrs_name = "divmod"
540         attrs = [
541                 dict(
542                         type = "ir_mode*",
543                         name = "resmode"
544                 ),
545         ]
546         attr_struct = "divmod_attr"
547         pinned      = "exception"
548         op_index    = 1
549         arity_override = "oparity_binary"
550         d_post = '''
551         firm_alloc_frag_arr(res, op_Mod, &res->attr.except.frag_arr);
552         '''
553
554 class Mul(Binop):
555         flags = [ "commutative" ]
556
557 class Mulh(Binop):
558         flags = [ "commutative" ]
559
560 class Mux(Op):
561         ins    = [ "sel", "false", "true" ]
562         flags  = []
563         pinned = "no"
564
565 class NoMem(Op):
566         mode       = "mode_M"
567         flags      = [ "dump_noblock", "dump_noinput" ]
568         pinned     = "yes"
569         knownBlock = True
570         singleton  = True
571
572 class Not(Unop):
573         flags = []
574
575 class Or(Binop):
576         flags = [ "commutative" ]
577
578 class Phi(Op):
579         pinned      = "yes"
580         arity       = "variable"
581         flags       = []
582         attr_struct = "phi_attr"
583         custom_is   = True
584         java_noconstr = True
585         init = '''
586         /* Memory Phis in endless loops must be kept alive.
587            As we can't distinguish these easily we keep all of them alive. */
588         if (is_Phi(res) && mode == mode_M)
589                 add_End_keepalive(get_irg_end(irg), res);
590         '''
591
592 class Pin(Op):
593         ins      = [ "op" ]
594         mode     = "get_irn_mode(irn_op)"
595         flags    = [ "highlevel" ]
596         pinned   = "yes"
597
598 class Proj(Op):
599         ins      = [ "pred" ]
600         flags    = []
601         pinned   = "no"
602         attrs    = [
603                 dict(
604                         type = "long",
605                         name = "proj",
606                         initname = ""
607                 )
608         ]
609         attr_struct = "long"
610         custom_is   = True
611
612 class Quot(Op):
613         ins   = [ "mem", "left", "right" ]
614         outs  = [ "M", "X_regular", "X_except", "res" ]
615         flags = [ "fragile", "uses_memory" ]
616         attrs_name = "divmod"
617         attrs = [
618                 dict(
619                         type = "ir_mode*",
620                         name = "resmode"
621                 ),
622         ]
623         attr_struct = "divmod_attr"
624         pinned      = "exception"
625         op_index    = 1
626         arity_override = "oparity_binary"
627         d_post = '''
628         firm_alloc_frag_arr(res, op_Quot, &res->attr.except.frag_arr);
629         '''
630
631 class Raise(Op):
632         ins    = [ "mem", "exo_ptr" ]
633         outs   = [ "M", "X" ]
634         flags  = [ "highlevel", "cfopcode" ]
635         pinned = "yes"
636
637 class Return(Op):
638         ins      = [ "mem" ]
639         arity    = "variable"
640         mode     = "mode_X"
641         flags    = [ "cfopcode" ]
642         pinned   = "yes"
643
644 class Rotl(Binop):
645         flags    = []
646
647 class Sel(Op):
648         ins    = [ "mem", "ptr" ]
649         arity  = "variable"
650         flags  = []
651         mode   = "is_Method_type(get_entity_type(entity)) ? mode_P_code : mode_P_data"
652         pinned = "no"
653         attrs  = [
654                 dict(
655                         type = "ir_entity*",
656                         name = "entity"
657                 )
658         ]
659         attr_struct = "sel_attr"
660
661 class Shl(Binop):
662         flags = []
663
664 class Shr(Binop):
665         flags = []
666
667 class Shrs(Binop):
668         flags = []
669
670 class Start(Op):
671         mode       = "mode_T"
672         pinned     = "yes"
673         flags      = [ "cfopcode" ]
674         singleton  = True
675
676 class Store(Op):
677         ins      = [ "mem", "ptr", "value" ]
678         outs     = [ "M", "X_regular", "X_except" ]
679         flags    = [ "fragile", "uses_memory" ]
680         pinned   = "exception"
681         attr_struct = "store_attr"
682         pinned_init = "flags & cons_floats ? op_pin_state_floats : op_pin_state_pinned"
683         constructor_args = [
684                 dict(
685                         type = "ir_cons_flags",
686                         name = "flags",
687                 ),
688         ]
689         d_post = '''
690         firm_alloc_frag_arr(res, op_Store, &res->attr.store.exc.frag_arr);
691         '''
692
693 class Sub(Binop):
694         flags = []
695
696 class SymConst(Op):
697         mode       = "mode_P"
698         flags      = [ "constlike", "start_block" ]
699         knownBlock = True
700         pinned     = "no"
701         attrs      = [
702                 dict(
703                         type = "ir_entity*",
704                         name = "entity"
705                 )
706         ]
707         attr_struct = "symconst_attr"
708         java_noconstr = True
709
710 class Sync(Op):
711         mode     = "mode_M"
712         flags    = []
713         pinned   = "no"
714         optimize = False
715         arity    = "dynamic"
716
717 class Tuple(Op):
718         arity  = "variable"
719         mode   = "mode_T"
720         pinned = "no"
721         flags  = [ "labeled" ]
722         java_noconstr = True
723
724 class Unknown(Op):
725         knownBlock = True
726         pinned     = "yes"
727         block      = "get_irg_start_block(irg)"
728         flags      = [ "cfopcode", "fragile", "start_block", "constlike",
729                        "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))