put node descriptions into the spec file
[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         """returns the sum of its operands"""
25         flags = ["commutative"]
26
27 class Alloc(Op):
28         """allocates a block of memory.
29         It can be specified whether the variable should be allocated to the stack
30         or to the heap."""
31         ins   = [ "mem", "count" ]
32         outs  = [
33                 ("M",         "memory result",                         "pn_Generic_M"),
34                 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
35                 ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
36                 ("res",       "pointer to newly allocated memory",     "pn_Generic_other"),
37         ]
38         flags = [ "fragile", "uses_memory" ]
39         attrs = [
40                 dict(
41                         name = "type",
42                         type = "ir_type*"
43                 ),
44                 dict(
45                         name = "where",
46                         type = "ir_where_alloc"
47                 )
48         ]
49         pinned      = "yes"
50         attr_struct = "alloc_attr"
51
52 class Anchor(Op):
53         """utiliy node used to "hold" nodes in a graph that might possibly not be
54         reachable by other means or which should be reachable immediately without
55         searching through the graph.
56         Each firm-graph contains exactly one anchor node whose address is always
57         known. All other well-known graph-nodes like Start, End, NoMem, Bad, ...
58         are found by looking at the respective Anchor operand."""
59         mode             = "mode_ANY"
60         arity            = "variable"
61         flags            = [ "dump_noblock" ]
62         pinned           = "yes"
63         attr_struct      = "irg_attr"
64         knownBlock       = True
65         singleton        = True
66         noconstructor    = True
67         customSerializer = True
68
69 class And(Binop):
70         """returns the result of a bitwise and operation of its operands"""
71         flags    = [ "commutative" ]
72
73 class ASM(Op):
74         """executes assembler fragments of the target machine"""
75         mode             = "mode_T"
76         arity            = "variable"
77         flags            = [ "keep", "uses_memory" ]
78         pinned           = "memory"
79         pinned_init      = "op_pin_state_pinned"
80         attr_struct      = "asm_attr"
81         attrs_name       = "assem"
82         customSerializer = True
83
84 class Bad(Op):
85         """Bad nodes indicate invalid input, which is values which should never be
86         computed.
87
88         The typical use case for the Bad node is removing unreachable code.
89         Frontends should set the current_block to Bad when it is clear that
90         following code must be unreachable (ie. after a goto or return statement).
91         Optimisations also set block predecessors to Bad when it becomes clear,
92         that a control flow edge can never be executed.
93
94         The gigo optimisations ensures that nodes with Bad as their block, get
95         replaced by Bad themselfes. Nodes with at least 1 Bad input get exchanged
96         with Bad too. Exception to this rule are Block, Phi, Tuple and End node;
97         This is because removing inputs from a Block is hairy operation (requiring,
98         Phis to be shortened too for example). So instead of removing block inputs
99         they are set to Bad, and the actual removal is left to the control flow
100         optimisation phase. Block, Phi, Tuple with only Bad inputs however are
101         replaced by Bad right away."""
102         mode          = "mode_T"
103         flags         = [ "cfopcode", "start_block", "dump_noblock" ]
104         pinned        = "yes"
105         knownBlock    = True
106         block         = "get_irg_start_block(irg)"
107         singleton     = True
108         attr_struct   = "bad_attr"
109         init = '''
110         res->attr.bad.irg.irg = irg;
111         '''
112
113 class Deleted(Op):
114         """Internal node which is temporary set to nodes which are already removed
115         from the graph."""
116         mode             = "mode_Bad"
117         flags            = [ ]
118         pinned           = "yes"
119         noconstructor    = True
120         customSerializer = True
121
122 class Block(Op):
123         """A basic block"""
124         mode             = "mode_BB"
125         knownBlock       = True
126         block            = "NULL"
127         pinned           = "yes"
128         arity            = "variable"
129         flags            = [ "labeled" ]
130         attr_struct      = "block_attr"
131         customSerializer = True
132
133         init = '''
134         res->attr.block.irg.irg     = irg;
135         res->attr.block.backedge    = new_backedge_arr(irg->obst, arity);
136         set_Block_matured(res, 1);
137
138         /* Create and initialize array for Phi-node construction. */
139         if (get_irg_phase_state(irg) == phase_building) {
140                 res->attr.block.graph_arr = NEW_ARR_D(ir_node *, irg->obst, irg->n_loc);
141                 memset(res->attr.block.graph_arr, 0, irg->n_loc * sizeof(ir_node*));
142         }
143         '''
144
145 class Borrow(Binop):
146         """Returns the borrow bit from and implied subtractions of its 2 operands"""
147         flags = []
148
149 class Bound(Op):
150         """Performs a bounds-check: if lower <= index < upper then return index,
151         otherwise throw an exception."""
152         ins    = [ "mem", "index", "lower", "upper" ]
153         outs  = [
154                 ("M",         "memory result",                         "pn_Generic_M"),
155                 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
156                 ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
157                 ("res",       "the checked index",                     "pn_Generic_other"),
158         ]
159         flags  = [ "fragile", "highlevel" ]
160         pinned = "exception"
161         pinned_init = "op_pin_state_pinned"
162         attr_struct = "bound_attr"
163         attrs_name  = "bound"
164
165 class Builtin(Op):
166         """performs a backend-specific builtin."""
167         ins      = [ "mem" ]
168         arity    = "variable"
169         outs     = [
170                 ("M",        "memory result", "pn_Generic_M"),
171                 ("1_result", "first result",  "pn_Generic_other"),
172         ]
173         flags    = [ "uses_memory" ]
174         attrs    = [
175                 dict(
176                         type = "ir_builtin_kind",
177                         name = "kind"
178                 ),
179                 dict(
180                         type = "ir_type*",
181                         name = "type"
182                 )
183         ]
184         pinned      = "memory"
185         pinned_init = "op_pin_state_pinned"
186         attr_struct = "builtin_attr"
187         init   = '''
188         assert((get_unknown_type() == type) || is_Method_type(type));
189         '''
190
191 class Call(Op):
192         """Calls other code. Control flow is transfered to ptr, additional
193         operands are passed to the called code. Called code usually performs a
194         return operation. The operands of this return operation are the result
195         of the Call node."""
196         ins      = [ "mem", "ptr" ]
197         arity    = "variable"
198         outs     = [
199                 ("M",                "memory result",                         "pn_Generic_M"),
200                 ("X_regular",        "control flow when no exception occurs", "pn_Generic_X_regular"),
201                 ("X_except",         "control flow when exception occured",   "pn_Generic_X_except"),
202                 ("T_result",         "tuple containing all results",          "pn_Generic_other"),
203                 ("P_value_res_base", "pointer to memory register containing copied results passed by value"),
204         ]
205         flags    = [ "fragile", "uses_memory" ]
206         attrs    = [
207                 dict(
208                         type = "ir_type*",
209                         name = "type"
210                 ),
211                 dict(
212                         type = "unsigned",
213                         name = "tail_call",
214                         # the tail call attribute can only be set by analysis
215                         init = "0"
216                 )
217         ]
218         attr_struct = "call_attr"
219         pinned      = "memory"
220         pinned_init = "op_pin_state_pinned"
221         init = '''
222         assert((get_unknown_type() == type) || is_Method_type(type));
223         '''
224
225 class Carry(Binop):
226         """Computes the value of the carry-bit that would result when adding the 2
227         operands"""
228         flags = [ "commutative" ]
229
230 class Cast(Unop):
231         """perform a high-level type cast"""
232         mode     = "get_irn_mode(irn_op)"
233         flags    = [ "highlevel" ]
234         attrs    = [
235                 dict(
236                         type = "ir_type*",
237                         name = "type"
238                 )
239         ]
240         attr_struct = "cast_attr"
241         init     = "assert(is_atomic_type(type));"
242
243 class Cmp(Binop):
244         """Returns the relation of 2 operands"""
245         outs  = [
246                 ("False", "always false",                            "0"),
247                 ("Eq",    "equal",                                   "1"),
248                 ("Lt",    "less",                                    "2"),
249                 ("Le",    "less or equal",                           "pn_Cmp_Eq|pn_Cmp_Lt"),
250                 ("Gt",    "greater",                                 "4"),
251                 ("Ge",    "greater or equal",                        "pn_Cmp_Eq|pn_Cmp_Gt"),
252                 ("Lg",    "less or greater ('not equal' for integer numbers)", "pn_Cmp_Lt|pn_Cmp_Gt"),
253                 ("Leg",   "less, equal or greater ('not unordered')", "pn_Cmp_Lt|pn_Cmp_Eq|pn_Cmp_Gt"),
254                 ("Uo",    "unordered",                               "8"),
255                 ("Ue",    "unordered or equal",                      "pn_Cmp_Uo|pn_Cmp_Eq"),
256                 ("Ul",    "unordered or less",                       "pn_Cmp_Uo|pn_Cmp_Lt"),
257                 ("Ule",   "unordered, less or equal",                "pn_Cmp_Uo|pn_Cmp_Lt|pn_Cmp_Eq"),
258                 ("Ug",    "unordered or greater",                    "pn_Cmp_Uo|pn_Cmp_Gt"),
259                 ("Uge",   "onordered, greater or equal",             "pn_Cmp_Uo|pn_Cmp_Gt|pn_Cmp_Eq"),
260                 ("Ne",    "unordered, less or greater ('not equal' for floatingpoint numbers)", "pn_Cmp_Uo|pn_Cmp_Lt|pn_Cmp_Gt"),
261                 ("True",  "always true",                             "15"),
262         ]
263         flags = []
264
265 class Cond(Op):
266         """Conditionally change control flow. There are two versions of this node:
267
268         Boolean Cond:
269         Input:  A value of mode_b
270         Output: A tuple of two control flows. The first is taken if the input is
271                 false, the second if it is true.
272
273         Switch Cond:
274         Input:  A value of mode_Iu
275         Output: A tuple of n control flows. If the Cond's input is i, control flow
276         will proceed along output i. If the input is >= n control flow proceeds
277         along output def_proj.
278         """
279         ins      = [ "selector" ]
280         outs     = [
281                 ("false", "control flow if operand is \"false\""),
282                 ("true",  "control flow if operand is \"true\""),
283         ]
284         flags    = [ "cfopcode", "forking" ]
285         pinned   = "yes"
286         attrs    = [
287                 dict(
288                         name = "default_proj",
289                         type = "long",
290                         init = "0"
291                 ),
292                 dict(
293                         name = "jmp_pred",
294                         type = "cond_jmp_predicate",
295                         init = "COND_JMP_PRED_NONE"
296                 )
297         ]
298         attr_struct = "cond_attr"
299
300 class Confirm(Op):
301         """Specifies constraints for a value. This allows explicit representation
302         of path-sensitive properties. (Example: This value is always >= 0 on 1
303         if-branch then all users within that branch are rerouted to a confirm-node
304         specifying this property).
305
306         A constraint is specified for the relation between value and bound.
307         value is always returned.
308         Note that this node does NOT check or assert the constraint, it merely
309         specifies it."""
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         attrs_name  = "confirm"
322
323 class Const(Op):
324         """Returns a constant value."""
325         mode       = ""
326         flags      = [ "constlike", "start_block" ]
327         knownBlock = True
328         pinned     = "no"
329         attrs_name = "con"
330         attrs      = [
331                 dict(
332                         type = "ir_tarval*",
333                         name = "tarval",
334                 )
335         ]
336         attr_struct = "const_attr"
337
338 class Conv(Unop):
339         """Converts values between modes"""
340         flags = []
341         attrs = [
342                 dict(
343                         name = "strict",
344                         type = "int",
345                         init = "0",
346                         special = dict(
347                                 prefix = "strict",
348                                 init = "1"
349                         )
350                 )
351         ]
352         attr_struct = "conv_attr"
353         attrs_name  = "conv"
354
355 class CopyB(Op):
356         """Copies a block of memory"""
357         ins   = [ "mem", "dst", "src" ]
358         outs  = [
359                 ("M",         "memory result",                         "pn_Generic_M"),
360                 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
361                 ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
362         ]
363         flags = [ "fragile", "uses_memory" ]
364         attrs = [
365                 dict(
366                         name = "type",
367                         type = "ir_type*"
368                 )
369         ]
370         attr_struct = "copyb_attr"
371         attrs_name  = "copyb"
372         pinned      = "memory"
373         pinned_init = "op_pin_state_pinned"
374
375 class Div(Op):
376         """returns the quotient of its 2 operands, integer version"""
377         ins   = [ "mem", "left", "right" ]
378         outs  = [
379                 ("M",         "memory result",                         "pn_Generic_M"),
380                 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
381                 ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
382                 ("res",       "result of computation",                 "pn_Generic_other"),
383         ]
384         flags = [ "fragile", "uses_memory" ]
385         attrs_name = "divmod"
386         attrs = [
387                 dict(
388                         type = "ir_mode*",
389                         name = "resmode"
390                 ),
391                 dict(
392                         name = "no_remainder",
393                         type = "int",
394                         init = "0",
395                         special = dict(
396                                 suffix = "RL",
397                                 init = "1"
398                         )
399                 )
400         ]
401         attr_struct = "divmod_attr"
402         pinned      = "exception"
403         op_index    = 1
404         arity_override = "oparity_binary"
405
406 class DivMod(Op):
407         """divides its 2 operands and computes the remainder of the division"""
408         ins   = [ "mem", "left", "right" ]
409         outs  = [
410                 ("M",         "memory result",                         "pn_Generic_M"),
411                 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
412                 ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
413                 ("res_div",   "result of computation a/b",             "pn_Generic_other"),
414                 ("res_mod",   "result of computation a%b"),
415         ]
416         flags = [ "fragile", "uses_memory" ]
417         attrs_name = "divmod"
418         attrs = [
419                 dict(
420                         type = "ir_mode*",
421                         name = "resmode"
422                 ),
423         ]
424         attr_struct = "divmod_attr"
425         pinned      = "exception"
426         op_index    = 1
427         arity_override = "oparity_binary"
428
429 class Dummy(Op):
430         """A placeholder value. This is used when constructing cyclic graphs where
431         you have cases where not all predecessors of a phi-node are known. Dummy
432         nodes are used for the unknown predecessors and replaced later."""
433         ins        = []
434         flags      = [ "cfopcode", "start_block", "constlike", "dump_noblock" ]
435         knownBlock = True
436         pinned     = "yes"
437         block      = "get_irg_start_block(irg)"
438
439 class End(Op):
440         """Last node of a graph. It references nodes in endless loops (so called
441         keepalive edges)"""
442         mode             = "mode_X"
443         pinned           = "yes"
444         arity            = "dynamic"
445         flags            = [ "cfopcode" ]
446         knownBlock       = True
447         block            = "get_irg_end_block(irg)"
448         singleton        = True
449         customSerializer = True
450
451 class Eor(Binop):
452         """returns the result of a bitwise exclusive or operation of its operands"""
453         flags    = [ "commutative" ]
454
455 class Free(Op):
456         """Frees a block of memory previously allocated by an Alloc node"""
457         ins    = [ "mem", "ptr", "size" ]
458         mode   = "mode_M"
459         flags  = [ "uses_memory" ]
460         pinned = "yes"
461         attrs  = [
462                 dict(
463                         name = "type",
464                         type = "ir_type*"
465                 ),
466                 dict(
467                         name = "where",
468                         type = "ir_where_alloc"
469                 )
470         ]
471         attr_struct = "free_attr"
472
473 class Id(Op):
474         """Returns its operand unchanged."""
475         ins    = [ "pred" ]
476         pinned = "no"
477         flags  = []
478
479 class IJmp(Op):
480         """Jumps to the code in its argument. The code has to be in the same
481         function and the the destination must be one of the blocks reachable
482         by the tuple results"""
483         mode     = "mode_X"
484         pinned   = "yes"
485         ins      = [ "target" ]
486         flags    = [ "cfopcode", "forking", "keep" ]
487
488 class InstOf(Op):
489         """Tests wether an object is an instance of a class-type"""
490         ins   = [ "store", "obj" ]
491         outs  = [
492                 ("M",         "memory result",                         "pn_Generic_M"),
493                 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
494                 ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
495                 ("res",       "checked object pointer",                "pn_Generic_other"),
496         ]
497         flags = [ "highlevel" ]
498         attrs = [
499                 dict(
500                         name = "type",
501                         type = "ir_type*"
502                 )
503         ]
504         attr_struct = "io_attr"
505         pinned      = "memory"
506         pinned_init = "op_pin_state_floats"
507
508 class Jmp(Op):
509         """Jumps to the block connected through the out-value"""
510         mode     = "mode_X"
511         pinned   = "yes"
512         ins      = []
513         flags    = [ "cfopcode" ]
514
515 class Load(Op):
516         """Loads a value from memory (heap or stack)."""
517         ins      = [ "mem", "ptr" ]
518         outs  = [
519                 ("M",         "memory result",                         "pn_Generic_M"),
520                 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
521                 ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
522                 ("res",       "result of load operation",              "pn_Generic_other"),
523         ]
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
542 class Minus(Unop):
543         """returns the difference between its operands"""
544         flags = []
545
546 class Mod(Op):
547         """returns the remainder of its operands from an implied division.
548
549         Examples:
550         * mod(5,3)   produces 2
551         * mod(5,-3)  produces 2
552         * mod(-5,3)  produces -2
553         * mod(-5,-3) produces -2
554         """
555         ins   = [ "mem", "left", "right" ]
556         outs  = [
557                 ("M",         "memory result",                         "pn_Generic_M"),
558                 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
559                 ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
560                 ("res",       "result of computation",                 "pn_Generic_other"),
561         ]
562         flags = [ "fragile", "uses_memory" ]
563         attrs_name = "divmod"
564         attrs = [
565                 dict(
566                         type = "ir_mode*",
567                         name = "resmode"
568                 ),
569         ]
570         attr_struct = "divmod_attr"
571         pinned      = "exception"
572         op_index    = 1
573         arity_override = "oparity_binary"
574
575 class Mul(Binop):
576         """returns the product of its operands"""
577         flags = [ "commutative" ]
578
579 class Mulh(Binop):
580         """returns the upper word of the product of its operands (the part which
581         would not fit into the result mode of a normal Mul anymore)"""
582         flags = [ "commutative" ]
583
584 class Mux(Op):
585         """returns the false or true operand depending on the value of the sel
586         operand"""
587         ins    = [ "sel", "false", "true" ]
588         flags  = []
589         pinned = "no"
590
591 class NoMem(Op):
592         """Placeholder node for cases where you don't need any memory input"""
593         mode          = "mode_M"
594         flags         = [ "dump_noblock", "dump_noinput" ]
595         pinned        = "yes"
596         knownBlock    = True
597         block         = "get_irg_start_block(irg)"
598         singleton     = True
599
600 class Not(Unop):
601         """returns the logical complement of a value. Works for integer values too.
602         If the input is false/zero then true/one is returned, otherwise false/zero
603         is returned."""
604         flags = []
605
606 class Or(Binop):
607         """returns the result of a bitwise or operation of its operands"""
608         flags = [ "commutative" ]
609
610 class Phi(Op):
611         """Choose a value based on control flow. A phi node has 1 input for each
612         predecessor of its block. If a block is entered from its nth predecessor
613         all phi nodes produce their nth input as result."""
614         pinned        = "yes"
615         arity         = "variable"
616         flags         = []
617         attr_struct   = "phi_attr"
618         init = '''
619         /* Memory Phis in endless loops must be kept alive.
620            As we can't distinguish these easily we keep all of them alive. */
621         if (is_Phi(res) && mode == mode_M)
622                 add_End_keepalive(get_irg_end(irg), res);
623         '''
624
625 class Pin(Op):
626         """Pin the value of the node node in the current block. No users of the Pin
627         node can float above the Block of the Pin. The node cannot float behind
628         this block. Often used to Pin the NoMem node."""
629         ins      = [ "op" ]
630         mode     = "get_irn_mode(irn_op)"
631         flags    = [ "highlevel" ]
632         pinned   = "yes"
633
634 class Proj(Op):
635         """returns an entry of a tuple value"""
636         ins              = [ "pred" ]
637         flags            = []
638         pinned           = "no"
639         knownBlock       = True
640         knownGraph       = True
641         block            = "get_nodes_block(irn_pred)"
642         graph            = "get_irn_irg(irn_pred)"
643         customSerializer = True
644         attrs      = [
645                 dict(
646                         type = "long",
647                         name = "proj",
648                         initname = "",
649                         noprop = False,
650                 )
651         ]
652         attr_struct = "long"
653
654 class Quot(Op):
655         """returns the quotient of its 2 operands, floatingpoint version"""
656         ins   = [ "mem", "left", "right" ]
657         outs  = [
658                 ("M",         "memory result",                         "pn_Generic_M"),
659                 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
660                 ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
661                 ("res",       "result of computation",                 "pn_Generic_other"),
662         ]
663         flags = [ "fragile", "uses_memory" ]
664         attrs_name = "divmod"
665         attrs = [
666                 dict(
667                         type = "ir_mode*",
668                         name = "resmode"
669                 ),
670         ]
671         attr_struct = "divmod_attr"
672         pinned      = "exception"
673         op_index    = 1
674         arity_override = "oparity_binary"
675
676 class Raise(Op):
677         """Raises an exception. Unconditional change of control flow. Writes an
678         explicit Except variable to memory to pass it to the exception handler.
679         Must be lowered to a Call to a runtime check function."""
680         ins    = [ "mem", "exo_ptr" ]
681         outs  = [
682                 ("M", "memory result",                     "pn_Generic_M"),
683                 ("X", "control flow to exception handler", "pn_Generic_X_regular"),
684         ]
685         flags  = [ "highlevel", "cfopcode" ]
686         pinned = "yes"
687
688 class Return(Op):
689         """Returns from the current function. Takes memory and return values as
690         operands."""
691         ins      = [ "mem" ]
692         arity    = "variable"
693         mode     = "mode_X"
694         flags    = [ "cfopcode" ]
695         pinned   = "yes"
696
697 class Rotl(Binop):
698         """Returns its first operand bits rotated left by the amount in the 2nd
699         operand"""
700         flags    = []
701
702 class Sel(Op):
703         """Computes the address of a entity of a compound type given the base
704         address of an instance of the compound type."""
705         ins    = [ "mem", "ptr" ]
706         arity  = "variable"
707         flags  = []
708         mode   = "is_Method_type(get_entity_type(entity)) ? mode_P_code : mode_P_data"
709         pinned = "no"
710         attrs  = [
711                 dict(
712                         type = "ir_entity*",
713                         name = "entity"
714                 )
715         ]
716         attr_struct = "sel_attr"
717
718 class Shl(Binop):
719         """Returns its first operands bits shifted left by the amount of the 2nd
720         operand"""
721         flags = []
722
723 class Shr(Binop):
724         """Returns its first operands bits shifted right by the amount of the 2nd
725         operand. No special handling for the sign bit (zero extension)"""
726         flags = []
727
728 class Shrs(Binop):
729         """Returns its first operands bits shifted right by the amount of the 2nd
730         operand. The leftmost bit (usually the sign bit) stays the same
731         (sign extension)"""
732         flags = []
733
734 class Start(Op):
735         """The first node of a graph. Execution starts with this node."""
736         outs       = [
737                 ("X_initial_exec", "control flow"),
738                 ("M",              "initial memory"),
739                 ("P_frame_base",   "frame base pointer"),
740                 ("P_tls",          "pointer to thread local storage segment"),
741                 ("T_args",         "function arguments")
742         ]
743         mode             = "mode_T"
744         pinned           = "yes"
745         flags            = [ "cfopcode" ]
746         singleton        = True
747         knownBlock       = True
748         customSerializer = True
749         block            = "get_irg_start_block(irg)"
750
751 class Store(Op):
752         """Stores a value into memory (heap or stack)."""
753         ins      = [ "mem", "ptr", "value" ]
754         outs  = [
755                 ("M",         "memory result",                         "pn_Generic_M"),
756                 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
757                 ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
758         ]
759         flags    = [ "fragile", "uses_memory" ]
760         pinned   = "exception"
761         attr_struct = "store_attr"
762         pinned_init = "flags & cons_floats ? op_pin_state_floats : op_pin_state_pinned"
763         constructor_args = [
764                 dict(
765                         type = "ir_cons_flags",
766                         name = "flags",
767                 ),
768         ]
769
770 class Sub(Binop):
771         """returns the difference of its operands"""
772         flags = []
773
774 class SymConst(Op):
775         """A symbolic constant.
776
777          - symconst_type_tag   The symbolic constant represents a type tag.  The
778                                type the tag stands for is given explicitly.
779          - symconst_type_size  The symbolic constant represents the size of a type.
780                                The type of which the constant represents the size
781                                is given explicitly.
782          - symconst_type_align The symbolic constant represents the alignment of a
783                                type.  The type of which the constant represents the
784                                size is given explicitly.
785          - symconst_addr_ent   The symbolic constant represents the address of an
786                                entity (variable or method).  The variable is given
787                                explicitly by a firm entity.
788          - symconst_ofs_ent    The symbolic constant represents the offset of an
789                                entity in its owner type.
790          - symconst_enum_const The symbolic constant is a enumeration constant of
791                                an enumeration type."""
792         mode       = "mode_P"
793         flags      = [ "constlike", "start_block" ]
794         knownBlock = True
795         pinned     = "no"
796         attrs      = [
797                 dict(
798                         type = "ir_entity*",
799                         name = "entity",
800                         noprop = True
801                 )
802         ]
803         attr_struct = "symconst_attr"
804         customSerializer = True
805
806 class Sync(Op):
807         """The Sync operation unifies several partial memory blocks. These blocks
808         have to be pairwise disjunct or the values in common locations have to
809         be identical.  This operation allows to specify all operations that
810         eventually need several partial memory blocks as input with a single
811         entrance by unifying the memories with a preceding Sync operation."""
812         mode     = "mode_M"
813         flags    = []
814         pinned   = "no"
815         arity    = "dynamic"
816
817 class Tuple(Op):
818         """Builds a Tuple from single values.
819
820         This is needed to implement optimizations that remove a node that produced
821         a tuple.  The node can be replaced by the Tuple operation so that the
822         following Proj nodes have not to be changed. (They are hard to find due to
823         the implementation with pointers in only one direction.) The Tuple node is
824         smaller than any other node, so that a node can be changed into a Tuple by
825         just changing it's opcode and giving it a new in array."""
826         arity  = "variable"
827         mode   = "mode_T"
828         pinned = "no"
829         flags  = [ "labeled" ]
830
831 class Unknown(Op):
832         """Returns an unknown (at compile- and runtime) value. It is a valid
833         optimisation to replace an Unknown by any other constant value."""
834         knownBlock = True
835         pinned     = "yes"
836         block      = "get_irg_start_block(irg)"
837         flags      = [ "cfopcode", "start_block", "constlike", "dump_noblock" ]
838
839 # Prepare node list
840
841 def getOpList(namespace):
842         nodes = []
843         for t in namespace.values():
844                 if type(t) != type:
845                         continue
846
847                 if issubclass(t, Op):
848                         setnodedefaults(t)
849                         nodes.append(t)
850         return nodes
851
852 nodes = getOpList(globals())
853 nodes = sorted(nodes, lambda x,y: cmp(x.name, y.name))