compile as C++ in msvc
[libfirm] / scripts / ir_spec.py
1 from spec_util import abstract, setnodedefaults
2
3 class Op(object):
4         "Base class for firm nodes"
5 abstract(Op)
6
7 class Unop(Op):
8         "Unary nodes have exactly 1 input"
9         name     = "unop"
10         ins      = [ "op" ]
11         op_index = 0
12         pinned   = "no"
13 abstract(Unop)
14
15 class Binop(Op):
16         "Binary nodes have exactly 2 inputs"
17         name     = "binop"
18         ins      = [ "left", "right" ]
19         op_index = 0
20         pinned   = "no"
21 abstract(Binop)
22
23 class Add(Binop):
24         flags = ["commutative"]
25
26 class Alloc(Op):
27         ins   = [ "mem", "count" ]
28         outs  = [
29                 ("M",         "memory result",                         "pn_Generic_M"),
30                 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
31                 ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
32                 ("res",       "pointer to newly allocated memory",     "pn_Generic_other"),
33         ]
34         flags = [ "fragile", "uses_memory" ]
35         attrs = [
36                 dict(
37                         name = "type",
38                         type = "ir_type*"
39                 ),
40                 dict(
41                         name = "where",
42                         type = "ir_where_alloc"
43                 )
44         ]
45         pinned      = "yes"
46         attr_struct = "alloc_attr"
47
48 class Anchor(Op):
49         mode        = "mode_ANY"
50         arity       = "variable"
51         flags       = [ "dump_noblock" ]
52         pinned      = "yes"
53         attr_struct = "irg_attr"
54         knownBlock  = True
55         singleton   = True
56         noconstructor = True
57
58 class And(Binop):
59         flags    = [ "commutative" ]
60
61 class ASM(Op):
62         mode          = "mode_T"
63         arity         = "variable"
64         flags         = [ "keep", "uses_memory" ]
65         pinned        = "memory"
66         pinned_init   = "op_pin_state_pinned"
67         attr_struct   = "asm_attr"
68         attrs_name    = "assem"
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                         noprop = True,
78                 ),
79                 dict(
80                         name = "output_constraints",
81                         type = "ir_asm_constraint*",
82                 ),
83                 dict(
84                         name = "n_clobbers",
85                         type = "int",
86                         noprop = True,
87                 ),
88                 dict(
89                         name = "clobbers",
90                         type = "ident**",
91                 ),
92                 dict(
93                         name = "text",
94                         type = "ident*",
95                 ),
96         ]
97
98 class Bad(Op):
99         mode          = "mode_T"
100         flags         = [ "cfopcode", "start_block", "dump_noblock" ]
101         pinned        = "yes"
102         knownBlock    = True
103         block         = "get_irg_start_block(irg)"
104         singleton     = True
105         attr_struct   = "bad_attr"
106         init = '''
107         res->attr.bad.irg.irg = irg;
108         '''
109
110 class Deleted(Op):
111         mode          = "mode_Bad"
112         flags         = [ ]
113         pinned        = "yes"
114         noconstructor = True
115
116 class Block(Op):
117         mode        = "mode_BB"
118         knownBlock  = True
119         block       = "NULL"
120         pinned      = "yes"
121         arity       = "variable"
122         flags       = [ "labeled" ]
123         attr_struct = "block_attr"
124
125         init = '''
126         res->attr.block.irg.irg     = irg;
127         res->attr.block.backedge    = new_backedge_arr(irg->obst, arity);
128         set_Block_matured(res, 1);
129
130         /* Create and initialize array for Phi-node construction. */
131         if (get_irg_phase_state(irg) == phase_building) {
132                 res->attr.block.graph_arr = NEW_ARR_D(ir_node *, irg->obst, irg->n_loc);
133                 memset(res->attr.block.graph_arr, 0, irg->n_loc * sizeof(ir_node*));
134         }
135         '''
136
137         java_add   = '''
138         public void addPred(Node node) {
139                 binding_ircons.add_immBlock_pred(ptr, node.ptr);
140         }
141
142         public void mature() {
143                 binding_ircons.mature_immBlock(ptr);
144         }
145
146         @Override
147         public Block getBlock() {
148                 return null;
149         }
150
151         public boolean blockVisited() {
152                 return 0 != binding_irnode.Block_block_visited(ptr);
153         }
154
155         public void markBlockVisited() {
156                 binding_irnode.mark_Block_block_visited(ptr);
157         }
158
159         public boolean isBad() {
160                 return binding_irnode.is_Bad(ptr) != 0;
161         }
162         '''
163
164 class Borrow(Binop):
165         flags = []
166
167 class Bound(Op):
168         ins    = [ "mem", "index", "lower", "upper" ]
169         outs  = [
170                 ("M",         "memory result",                         "pn_Generic_M"),
171                 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
172                 ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
173                 ("res",       "the checked index",                     "pn_Generic_other"),
174         ]
175         flags  = [ "fragile", "highlevel" ]
176         pinned = "exception"
177         pinned_init = "op_pin_state_pinned"
178         attr_struct = "bound_attr"
179         attrs_name  = "bound"
180
181 class Builtin(Op):
182         ins      = [ "mem" ]
183         arity    = "variable"
184         outs     = [
185                 ("M",        "memory result", "pn_Generic_M"),
186                 ("1_result", "first result",  "pn_Generic_other"),
187         ]
188         flags    = [ "uses_memory" ]
189         attrs    = [
190                 dict(
191                         type = "ir_builtin_kind",
192                         name = "kind"
193                 ),
194                 dict(
195                         type = "ir_type*",
196                         name = "type"
197                 )
198         ]
199         pinned      = "memory"
200         pinned_init = "op_pin_state_pinned"
201         attr_struct = "builtin_attr"
202         init   = '''
203         assert((get_unknown_type() == type) || is_Method_type(type));
204         '''
205
206 class Call(Op):
207         ins      = [ "mem", "ptr" ]
208         arity    = "variable"
209         outs     = [
210                 ("M",                "memory result",                         "pn_Generic_M"),
211                 ("X_regular",        "control flow when no exception occurs", "pn_Generic_X_regular"),
212                 ("X_except",         "control flow when exception occured",   "pn_Generic_X_except"),
213                 ("T_result",         "tuple containing all results",          "pn_Generic_other"),
214                 ("P_value_res_base", "pointer to memory register containing copied results passed by value"),
215         ]
216         flags    = [ "fragile", "uses_memory" ]
217         attrs    = [
218                 dict(
219                         type = "ir_type*",
220                         name = "type"
221                 ),
222                 dict(
223                         type = "unsigned",
224                         name = "tail_call",
225                         # the tail call attribute can only be set by analysis
226                         init = "0"
227                 )
228         ]
229         attr_struct = "call_attr"
230         pinned      = "memory"
231         pinned_init = "op_pin_state_pinned"
232         init = '''
233         assert((get_unknown_type() == type) || is_Method_type(type));
234         '''
235
236 class Carry(Binop):
237         flags = [ "commutative" ]
238
239 class Cast(Unop):
240         mode     = "get_irn_mode(irn_op)"
241         flags    = [ "highlevel" ]
242         attrs    = [
243                 dict(
244                         type = "ir_type*",
245                         name = "type"
246                 )
247         ]
248         attr_struct = "cast_attr"
249         init     = "assert(is_atomic_type(type));"
250
251 class Cmp(Binop):
252         outs  = [
253                 ("False", "always false",                            "0"),
254                 ("Eq",    "equal",                                   "1"),
255                 ("Lt",    "less",                                    "2"),
256                 ("Le",    "less or equal",                           "pn_Cmp_Eq|pn_Cmp_Lt"),
257                 ("Gt",    "greater",                                 "4"),
258                 ("Ge",    "greater or equal",                        "pn_Cmp_Eq|pn_Cmp_Gt"),
259                 ("Lg",    "less or greater ('not equal' for integer numbers)", "pn_Cmp_Lt|pn_Cmp_Gt"),
260                 ("Leg",   "less, equal or greater ('not unordered')", "pn_Cmp_Lt|pn_Cmp_Eq|pn_Cmp_Gt"),
261                 ("Uo",    "unordered",                               "8"),
262                 ("Ue",    "unordered or equal",                      "pn_Cmp_Uo|pn_Cmp_Eq"),
263                 ("Ul",    "unordered or less",                       "pn_Cmp_Uo|pn_Cmp_Lt"),
264                 ("Ule",   "unordered, less or equal",                "pn_Cmp_Uo|pn_Cmp_Lt|pn_Cmp_Eq"),
265                 ("Ug",    "unordered or greater",                    "pn_Cmp_Uo|pn_Cmp_Gt"),
266                 ("Uge",   "onordered, greater or equal",             "pn_Cmp_Uo|pn_Cmp_Gt|pn_Cmp_Eq"),
267                 ("Ne",    "unordered, less or greater ('not equal' for floatingpoint numbers)", "pn_Cmp_Uo|pn_Cmp_Lt|pn_Cmp_Gt"),
268                 ("True",  "always true",                             "15"),
269         ]
270         flags = []
271
272 class Cond(Op):
273         ins      = [ "selector" ]
274         outs     = [
275                 ("false", "control flow if operand is \"false\""),
276                 ("true",  "control flow if operand is \"true\""),
277         ]
278         flags    = [ "cfopcode", "forking" ]
279         pinned   = "yes"
280         attrs    = [
281                 dict(
282                         name = "default_proj",
283                         type = "long",
284                         init = "0"
285                 ),
286                 dict(
287                         name = "jmp_pred",
288                         type = "cond_jmp_predicate",
289                         init = "COND_JMP_PRED_NONE"
290                 )
291         ]
292         attr_struct = "cond_attr"
293
294 class Confirm(Op):
295         ins      = [ "value", "bound" ]
296         mode     = "get_irn_mode(irn_value)"
297         flags    = [ "highlevel" ]
298         pinned   = "yes"
299         attrs    = [
300                 dict(
301                         name = "cmp",
302                         type = "pn_Cmp"
303                 ),
304         ]
305         attr_struct = "confirm_attr"
306         attrs_name  = "confirm"
307
308 class Const(Op):
309         mode       = ""
310         flags      = [ "constlike", "start_block" ]
311         knownBlock = True
312         pinned     = "no"
313         attrs_name = "con"
314         attrs      = [
315                 dict(
316                         type = "ir_tarval*",
317                         name = "tarval",
318                 )
319         ]
320         attr_struct = "const_attr"
321
322 class Conv(Unop):
323         flags = []
324         attrs = [
325                 dict(
326                         name = "strict",
327                         type = "int",
328                         init = "0",
329                         special = dict(
330                                 prefix = "strict",
331                                 init = "1"
332                         )
333                 )
334         ]
335         attr_struct = "conv_attr"
336         attrs_name  = "conv"
337
338 class CopyB(Op):
339         ins   = [ "mem", "dst", "src" ]
340         outs  = [
341                 ("M",         "memory result",                         "pn_Generic_M"),
342                 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
343                 ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
344         ]
345         flags = [ "fragile", "highlevel", "uses_memory" ]
346         attrs = [
347                 dict(
348                         name = "type",
349                         type = "ir_type*"
350                 )
351         ]
352         attr_struct = "copyb_attr"
353         attrs_name  = "copyb"
354         pinned      = "memory"
355         pinned_init = "op_pin_state_pinned"
356
357 class Div(Op):
358         ins   = [ "mem", "left", "right" ]
359         outs  = [
360                 ("M",         "memory result",                         "pn_Generic_M"),
361                 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
362                 ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
363                 ("res",       "result of computation",                 "pn_Generic_other"),
364         ]
365         flags = [ "fragile", "uses_memory" ]
366         attrs_name = "divmod"
367         attrs = [
368                 dict(
369                         type = "ir_mode*",
370                         name = "resmode"
371                 ),
372                 dict(
373                         name = "no_remainder",
374                         type = "int",
375                         init = "0",
376                         special = dict(
377                                 suffix = "RL",
378                                 init = "1"
379                         )
380                 )
381         ]
382         attr_struct = "divmod_attr"
383         pinned      = "exception"
384         op_index    = 1
385         arity_override = "oparity_binary"
386
387 class DivMod(Op):
388         ins   = [ "mem", "left", "right" ]
389         outs  = [
390                 ("M",         "memory result",                         "pn_Generic_M"),
391                 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
392                 ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
393                 ("res_div",   "result of computation a/b",             "pn_Generic_other"),
394                 ("res_mod",   "result of computation a%b"),
395         ]
396         flags = [ "fragile", "uses_memory" ]
397         attrs_name = "divmod"
398         attrs = [
399                 dict(
400                         type = "ir_mode*",
401                         name = "resmode"
402                 ),
403         ]
404         attr_struct = "divmod_attr"
405         pinned      = "exception"
406         op_index    = 1
407         arity_override = "oparity_binary"
408
409 class Dummy(Op):
410         ins   = []
411         flags = [ "cfopcode", "start_block", "constlike", "dump_noblock" ]
412         knownBlock = True
413         pinned     = "yes"
414         block      = "get_irg_start_block(irg)"
415
416 class End(Op):
417         mode       = "mode_X"
418         pinned     = "yes"
419         arity      = "dynamic"
420         flags      = [ "cfopcode" ]
421         knownBlock = True
422         block      = "get_irg_end_block(irg)"
423         singleton  = True
424
425 class Eor(Binop):
426         flags    = [ "commutative" ]
427
428 class Free(Op):
429         ins    = [ "mem", "ptr", "size" ]
430         mode   = "mode_M"
431         flags  = [ "uses_memory" ]
432         pinned = "yes"
433         attrs  = [
434                 dict(
435                         name = "type",
436                         type = "ir_type*"
437                 ),
438                 dict(
439                         name = "where",
440                         type = "ir_where_alloc"
441                 )
442         ]
443         attr_struct = "free_attr"
444
445 class Id(Op):
446         ins    = [ "pred" ]
447         pinned = "no"
448         flags  = []
449
450 class IJmp(Op):
451         mode     = "mode_X"
452         pinned   = "yes"
453         ins      = [ "target" ]
454         flags    = [ "cfopcode", "forking", "keep" ]
455
456 class InstOf(Op):
457         ins   = [ "store", "obj" ]
458         outs  = [
459                 ("M",         "memory result",                         "pn_Generic_M"),
460                 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
461                 ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
462                 ("res",       "checked object pointer",                "pn_Generic_other"),
463         ]
464         flags = [ "highlevel" ]
465         attrs = [
466                 dict(
467                         name = "type",
468                         type = "ir_type*"
469                 )
470         ]
471         attr_struct = "io_attr"
472         pinned      = "memory"
473         pinned_init = "op_pin_state_floats"
474
475 class Jmp(Op):
476         mode     = "mode_X"
477         pinned   = "yes"
478         ins      = []
479         flags    = [ "cfopcode" ]
480
481 class Load(Op):
482         ins      = [ "mem", "ptr" ]
483         outs  = [
484                 ("M",         "memory result",                         "pn_Generic_M"),
485                 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
486                 ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
487                 ("res",       "result of load operation",              "pn_Generic_other"),
488         ]
489         flags    = [ "fragile", "uses_memory" ]
490         pinned   = "exception"
491         pinned_init = "flags & cons_floats ? op_pin_state_floats : op_pin_state_pinned"
492         attrs    = [
493                 dict(
494                         type = "ir_mode*",
495                         name = "mode",
496                         java_name = "load_mode"
497                 ),
498         ]
499         attr_struct = "load_attr"
500         constructor_args = [
501                 dict(
502                         type = "ir_cons_flags",
503                         name = "flags",
504                 ),
505         ]
506
507 class Minus(Unop):
508         flags = []
509
510 class Mod(Op):
511         ins   = [ "mem", "left", "right" ]
512         outs  = [
513                 ("M",         "memory result",                         "pn_Generic_M"),
514                 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
515                 ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
516                 ("res",       "result of computation",                 "pn_Generic_other"),
517         ]
518         flags = [ "fragile", "uses_memory" ]
519         attrs_name = "divmod"
520         attrs = [
521                 dict(
522                         type = "ir_mode*",
523                         name = "resmode"
524                 ),
525         ]
526         attr_struct = "divmod_attr"
527         pinned      = "exception"
528         op_index    = 1
529         arity_override = "oparity_binary"
530
531 class Mul(Binop):
532         flags = [ "commutative" ]
533
534 class Mulh(Binop):
535         flags = [ "commutative" ]
536
537 class Mux(Op):
538         ins    = [ "sel", "false", "true" ]
539         flags  = []
540         pinned = "no"
541
542 class NoMem(Op):
543         mode          = "mode_M"
544         flags         = [ "dump_noblock", "dump_noinput" ]
545         pinned        = "yes"
546         knownBlock    = True
547         block         = "get_irg_start_block(irg)"
548         singleton     = True
549
550 class Not(Unop):
551         flags = []
552
553 class Or(Binop):
554         flags = [ "commutative" ]
555
556 class Phi(Op):
557         pinned        = "yes"
558         arity         = "variable"
559         flags         = []
560         attr_struct   = "phi_attr"
561         init = '''
562         /* Memory Phis in endless loops must be kept alive.
563            As we can't distinguish these easily we keep all of them alive. */
564         if (is_Phi(res) && mode == mode_M)
565                 add_End_keepalive(get_irg_end(irg), res);
566         '''
567
568 class Pin(Op):
569         ins      = [ "op" ]
570         mode     = "get_irn_mode(irn_op)"
571         flags    = [ "highlevel" ]
572         pinned   = "yes"
573
574 class Proj(Op):
575         ins        = [ "pred" ]
576         flags      = []
577         pinned     = "no"
578         knownBlock = True
579         knownGraph = True
580         block      = "get_nodes_block(irn_pred)"
581         graph      = "get_irn_irg(irn_pred)"
582         attrs      = [
583                 dict(
584                         type = "long",
585                         name = "proj",
586                         initname = "",
587                         noprop = False,
588                 )
589         ]
590         attr_struct = "long"
591
592 class Quot(Op):
593         ins   = [ "mem", "left", "right" ]
594         outs  = [
595                 ("M",         "memory result",                         "pn_Generic_M"),
596                 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
597                 ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
598                 ("res",       "result of computation",                 "pn_Generic_other"),
599         ]
600         flags = [ "fragile", "uses_memory" ]
601         attrs_name = "divmod"
602         attrs = [
603                 dict(
604                         type = "ir_mode*",
605                         name = "resmode"
606                 ),
607         ]
608         attr_struct = "divmod_attr"
609         pinned      = "exception"
610         op_index    = 1
611         arity_override = "oparity_binary"
612
613 class Raise(Op):
614         ins    = [ "mem", "exo_ptr" ]
615         outs  = [
616                 ("M", "memory result",                     "pn_Generic_M"),
617                 ("X", "control flow to exception handler", "pn_Generic_X_regular"),
618         ]
619         flags  = [ "highlevel", "cfopcode" ]
620         pinned = "yes"
621
622 class Return(Op):
623         ins      = [ "mem" ]
624         arity    = "variable"
625         mode     = "mode_X"
626         flags    = [ "cfopcode" ]
627         pinned   = "yes"
628
629 class Rotl(Binop):
630         flags    = []
631
632 class Sel(Op):
633         ins    = [ "mem", "ptr" ]
634         arity  = "variable"
635         flags  = []
636         mode   = "is_Method_type(get_entity_type(entity)) ? mode_P_code : mode_P_data"
637         pinned = "no"
638         attrs  = [
639                 dict(
640                         type = "ir_entity*",
641                         name = "entity"
642                 )
643         ]
644         attr_struct = "sel_attr"
645
646 class Shl(Binop):
647         flags = []
648
649 class Shr(Binop):
650         flags = []
651
652 class Shrs(Binop):
653         flags = []
654
655 class Start(Op):
656         outs       = [
657                 ("X_initial_exec", "control flow"),
658                 ("M",              "initial memory"),
659                 ("P_frame_base",   "frame base pointer"),
660                 ("P_tls",          "pointer to thread local storage segment"),
661                 ("T_args",         "function arguments")
662         ]
663         mode       = "mode_T"
664         pinned     = "yes"
665         flags      = [ "cfopcode" ]
666         singleton  = True
667         knownBlock = True
668         block      = "get_irg_start_block(irg)"
669
670 class Store(Op):
671         ins      = [ "mem", "ptr", "value" ]
672         outs  = [
673                 ("M",         "memory result",                         "pn_Generic_M"),
674                 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
675                 ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
676         ]
677         flags    = [ "fragile", "uses_memory" ]
678         pinned   = "exception"
679         attr_struct = "store_attr"
680         pinned_init = "flags & cons_floats ? op_pin_state_floats : op_pin_state_pinned"
681         constructor_args = [
682                 dict(
683                         type = "ir_cons_flags",
684                         name = "flags",
685                 ),
686         ]
687
688 class Sub(Binop):
689         flags = []
690
691 class SymConst(Op):
692         mode       = "mode_P"
693         flags      = [ "constlike", "start_block" ]
694         knownBlock = True
695         pinned     = "no"
696         attrs      = [
697                 dict(
698                         type = "ir_entity*",
699                         name = "entity",
700                         noprop = True
701                 )
702         ]
703         attr_struct = "symconst_attr"
704
705 class Sync(Op):
706         mode     = "mode_M"
707         flags    = []
708         pinned   = "no"
709         arity    = "dynamic"
710
711 class Tuple(Op):
712         arity  = "variable"
713         mode   = "mode_T"
714         pinned = "no"
715         flags  = [ "labeled" ]
716
717 class Unknown(Op):
718         knownBlock = True
719         pinned     = "yes"
720         block      = "get_irg_start_block(irg)"
721         flags      = [ "cfopcode", "start_block", "constlike", "dump_noblock" ]
722
723 # Prepare node list
724
725 def getOpList(namespace):
726         nodes = []
727         for t in namespace.values():
728                 if type(t) != type:
729                         continue
730
731                 if issubclass(t, Op):
732                         setnodedefaults(t)
733                         nodes.append(t)
734         return nodes
735
736 nodes = getOpList(globals())
737 nodes = sorted(nodes, lambda x,y: cmp(x.name, y.name))