65aa32ef5def7ad5cd7e4beff656967df01ee44b
[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                 )
347         ]
348         attr_struct = "conv_attr"
349         attrs_name  = "conv"
350
351 class CopyB(Op):
352         """Copies a block of memory"""
353         ins   = [ "mem", "dst", "src" ]
354         outs  = [
355                 ("M",         "memory result",                         "pn_Generic_M"),
356                 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
357                 ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
358         ]
359         flags = [ "fragile", "uses_memory" ]
360         attrs = [
361                 dict(
362                         name = "type",
363                         type = "ir_type*"
364                 )
365         ]
366         attr_struct = "copyb_attr"
367         attrs_name  = "copyb"
368         pinned      = "memory"
369         pinned_init = "op_pin_state_pinned"
370
371 class Div(Op):
372         """returns the quotient of its 2 operands, integer version"""
373         ins   = [ "mem", "left", "right" ]
374         outs  = [
375                 ("M",         "memory result",                         "pn_Generic_M"),
376                 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
377                 ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
378                 ("res",       "result of computation",                 "pn_Generic_other"),
379         ]
380         flags = [ "fragile", "uses_memory" ]
381         attrs_name = "divmod"
382         attrs = [
383                 dict(
384                         type = "ir_mode*",
385                         name = "resmode"
386                 ),
387                 dict(
388                         name = "no_remainder",
389                         type = "int",
390                         init = "0",
391                 )
392         ]
393         attr_struct = "divmod_attr"
394         pinned      = "exception"
395         op_index    = 1
396         arity_override = "oparity_binary"
397
398 class DivMod(Op):
399         """divides its 2 operands and computes the remainder of the division"""
400         ins   = [ "mem", "left", "right" ]
401         outs  = [
402                 ("M",         "memory result",                         "pn_Generic_M"),
403                 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
404                 ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
405                 ("res_div",   "result of computation a/b",             "pn_Generic_other"),
406                 ("res_mod",   "result of computation a%b"),
407         ]
408         flags = [ "fragile", "uses_memory" ]
409         attrs_name = "divmod"
410         attrs = [
411                 dict(
412                         type = "ir_mode*",
413                         name = "resmode"
414                 ),
415         ]
416         attr_struct = "divmod_attr"
417         pinned      = "exception"
418         op_index    = 1
419         arity_override = "oparity_binary"
420
421 class Dummy(Op):
422         """A placeholder value. This is used when constructing cyclic graphs where
423         you have cases where not all predecessors of a phi-node are known. Dummy
424         nodes are used for the unknown predecessors and replaced later."""
425         ins        = []
426         flags      = [ "cfopcode", "start_block", "constlike", "dump_noblock" ]
427         knownBlock = True
428         pinned     = "yes"
429         block      = "get_irg_start_block(irg)"
430
431 class End(Op):
432         """Last node of a graph. It references nodes in endless loops (so called
433         keepalive edges)"""
434         mode             = "mode_X"
435         pinned           = "yes"
436         arity            = "dynamic"
437         flags            = [ "cfopcode" ]
438         knownBlock       = True
439         block            = "get_irg_end_block(irg)"
440         singleton        = True
441         customSerializer = True
442
443 class Eor(Binop):
444         """returns the result of a bitwise exclusive or operation of its operands"""
445         flags    = [ "commutative" ]
446
447 class Free(Op):
448         """Frees a block of memory previously allocated by an Alloc node"""
449         ins    = [ "mem", "ptr", "size" ]
450         mode   = "mode_M"
451         flags  = [ "uses_memory" ]
452         pinned = "yes"
453         attrs  = [
454                 dict(
455                         name = "type",
456                         type = "ir_type*"
457                 ),
458                 dict(
459                         name = "where",
460                         type = "ir_where_alloc"
461                 )
462         ]
463         attr_struct = "free_attr"
464
465 class Id(Op):
466         """Returns its operand unchanged."""
467         ins    = [ "pred" ]
468         pinned = "no"
469         flags  = []
470
471 class IJmp(Op):
472         """Jumps to the code in its argument. The code has to be in the same
473         function and the the destination must be one of the blocks reachable
474         by the tuple results"""
475         mode     = "mode_X"
476         pinned   = "yes"
477         ins      = [ "target" ]
478         flags    = [ "cfopcode", "forking", "keep" ]
479
480 class InstOf(Op):
481         """Tests wether an object is an instance of a class-type"""
482         ins   = [ "store", "obj" ]
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",       "checked object pointer",                "pn_Generic_other"),
488         ]
489         flags = [ "highlevel" ]
490         attrs = [
491                 dict(
492                         name = "type",
493                         type = "ir_type*"
494                 )
495         ]
496         attr_struct = "io_attr"
497         pinned      = "memory"
498         pinned_init = "op_pin_state_floats"
499
500 class Jmp(Op):
501         """Jumps to the block connected through the out-value"""
502         mode     = "mode_X"
503         pinned   = "yes"
504         ins      = []
505         flags    = [ "cfopcode" ]
506
507 class Load(Op):
508         """Loads a value from memory (heap or stack)."""
509         ins      = [ "mem", "ptr" ]
510         outs  = [
511                 ("M",         "memory result",                         "pn_Generic_M"),
512                 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
513                 ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
514                 ("res",       "result of load operation",              "pn_Generic_other"),
515         ]
516         flags    = [ "fragile", "uses_memory" ]
517         pinned   = "exception"
518         pinned_init = "flags & cons_floats ? op_pin_state_floats : op_pin_state_pinned"
519         attrs    = [
520                 dict(
521                         type = "ir_mode*",
522                         name = "mode",
523                         java_name = "load_mode"
524                 ),
525         ]
526         attr_struct = "load_attr"
527         constructor_args = [
528                 dict(
529                         type = "ir_cons_flags",
530                         name = "flags",
531                 ),
532         ]
533
534 class Minus(Unop):
535         """returns the difference between its operands"""
536         flags = []
537
538 class Mod(Op):
539         """returns the remainder of its operands from an implied division.
540
541         Examples:
542         * mod(5,3)   produces 2
543         * mod(5,-3)  produces 2
544         * mod(-5,3)  produces -2
545         * mod(-5,-3) produces -2
546         """
547         ins   = [ "mem", "left", "right" ]
548         outs  = [
549                 ("M",         "memory result",                         "pn_Generic_M"),
550                 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
551                 ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
552                 ("res",       "result of computation",                 "pn_Generic_other"),
553         ]
554         flags = [ "fragile", "uses_memory" ]
555         attrs_name = "divmod"
556         attrs = [
557                 dict(
558                         type = "ir_mode*",
559                         name = "resmode"
560                 ),
561         ]
562         attr_struct = "divmod_attr"
563         pinned      = "exception"
564         op_index    = 1
565         arity_override = "oparity_binary"
566
567 class Mul(Binop):
568         """returns the product of its operands"""
569         flags = [ "commutative" ]
570
571 class Mulh(Binop):
572         """returns the upper word of the product of its operands (the part which
573         would not fit into the result mode of a normal Mul anymore)"""
574         flags = [ "commutative" ]
575
576 class Mux(Op):
577         """returns the false or true operand depending on the value of the sel
578         operand"""
579         ins    = [ "sel", "false", "true" ]
580         flags  = []
581         pinned = "no"
582
583 class NoMem(Op):
584         """Placeholder node for cases where you don't need any memory input"""
585         mode          = "mode_M"
586         flags         = [ "dump_noblock", "dump_noinput" ]
587         pinned        = "yes"
588         knownBlock    = True
589         block         = "get_irg_start_block(irg)"
590         singleton     = True
591
592 class Not(Unop):
593         """returns the logical complement of a value. Works for integer values too.
594         If the input is false/zero then true/one is returned, otherwise false/zero
595         is returned."""
596         flags = []
597
598 class Or(Binop):
599         """returns the result of a bitwise or operation of its operands"""
600         flags = [ "commutative" ]
601
602 class Phi(Op):
603         """Choose a value based on control flow. A phi node has 1 input for each
604         predecessor of its block. If a block is entered from its nth predecessor
605         all phi nodes produce their nth input as result."""
606         pinned        = "yes"
607         arity         = "variable"
608         flags         = []
609         attr_struct   = "phi_attr"
610         init = '''
611         /* Memory Phis in endless loops must be kept alive.
612            As we can't distinguish these easily we keep all of them alive. */
613         if (is_Phi(res) && mode == mode_M)
614                 add_End_keepalive(get_irg_end(irg), res);
615         '''
616
617 class Pin(Op):
618         """Pin the value of the node node in the current block. No users of the Pin
619         node can float above the Block of the Pin. The node cannot float behind
620         this block. Often used to Pin the NoMem node."""
621         ins      = [ "op" ]
622         mode     = "get_irn_mode(irn_op)"
623         flags    = [ "highlevel" ]
624         pinned   = "yes"
625
626 class Proj(Op):
627         """returns an entry of a tuple value"""
628         ins              = [ "pred" ]
629         flags            = []
630         pinned           = "no"
631         knownBlock       = True
632         knownGraph       = True
633         block            = "get_nodes_block(irn_pred)"
634         graph            = "get_irn_irg(irn_pred)"
635         customSerializer = True
636         attrs      = [
637                 dict(
638                         type = "long",
639                         name = "proj",
640                 )
641         ]
642         attr_struct = "proj_attr"
643
644 class Quot(Op):
645         """returns the quotient of its 2 operands, floatingpoint version"""
646         ins   = [ "mem", "left", "right" ]
647         outs  = [
648                 ("M",         "memory result",                         "pn_Generic_M"),
649                 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
650                 ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
651                 ("res",       "result of computation",                 "pn_Generic_other"),
652         ]
653         flags = [ "fragile", "uses_memory" ]
654         attrs_name = "divmod"
655         attrs = [
656                 dict(
657                         type = "ir_mode*",
658                         name = "resmode"
659                 ),
660         ]
661         attr_struct = "divmod_attr"
662         pinned      = "exception"
663         op_index    = 1
664         arity_override = "oparity_binary"
665
666 class Raise(Op):
667         """Raises an exception. Unconditional change of control flow. Writes an
668         explicit Except variable to memory to pass it to the exception handler.
669         Must be lowered to a Call to a runtime check function."""
670         ins    = [ "mem", "exo_ptr" ]
671         outs  = [
672                 ("M", "memory result",                     "pn_Generic_M"),
673                 ("X", "control flow to exception handler", "pn_Generic_X_regular"),
674         ]
675         flags  = [ "highlevel", "cfopcode" ]
676         pinned = "yes"
677
678 class Return(Op):
679         """Returns from the current function. Takes memory and return values as
680         operands."""
681         ins      = [ "mem" ]
682         arity    = "variable"
683         mode     = "mode_X"
684         flags    = [ "cfopcode" ]
685         pinned   = "yes"
686
687 class Rotl(Binop):
688         """Returns its first operand bits rotated left by the amount in the 2nd
689         operand"""
690         flags    = []
691
692 class Sel(Op):
693         """Computes the address of a entity of a compound type given the base
694         address of an instance of the compound type."""
695         ins    = [ "mem", "ptr" ]
696         arity  = "variable"
697         flags  = []
698         mode   = "is_Method_type(get_entity_type(entity)) ? mode_P_code : mode_P_data"
699         pinned = "no"
700         attrs  = [
701                 dict(
702                         type = "ir_entity*",
703                         name = "entity"
704                 )
705         ]
706         attr_struct = "sel_attr"
707
708 class Shl(Binop):
709         """Returns its first operands bits shifted left by the amount of the 2nd
710         operand"""
711         flags = []
712
713 class Shr(Binop):
714         """Returns its first operands bits shifted right by the amount of the 2nd
715         operand. No special handling for the sign bit (zero extension)"""
716         flags = []
717
718 class Shrs(Binop):
719         """Returns its first operands bits shifted right by the amount of the 2nd
720         operand. The leftmost bit (usually the sign bit) stays the same
721         (sign extension)"""
722         flags = []
723
724 class Start(Op):
725         """The first node of a graph. Execution starts with this node."""
726         outs       = [
727                 ("X_initial_exec", "control flow"),
728                 ("M",              "initial memory"),
729                 ("P_frame_base",   "frame base pointer"),
730                 ("P_tls",          "pointer to thread local storage segment"),
731                 ("T_args",         "function arguments")
732         ]
733         mode             = "mode_T"
734         pinned           = "yes"
735         flags            = [ "cfopcode" ]
736         singleton        = True
737         knownBlock       = True
738         customSerializer = True
739         block            = "get_irg_start_block(irg)"
740
741 class Store(Op):
742         """Stores a value into memory (heap or stack)."""
743         ins      = [ "mem", "ptr", "value" ]
744         outs  = [
745                 ("M",         "memory result",                         "pn_Generic_M"),
746                 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
747                 ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
748         ]
749         flags    = [ "fragile", "uses_memory" ]
750         pinned   = "exception"
751         attr_struct = "store_attr"
752         pinned_init = "flags & cons_floats ? op_pin_state_floats : op_pin_state_pinned"
753         constructor_args = [
754                 dict(
755                         type = "ir_cons_flags",
756                         name = "flags",
757                 ),
758         ]
759
760 class Sub(Binop):
761         """returns the difference of its operands"""
762         flags = []
763
764 class SymConst(Op):
765         """A symbolic constant.
766
767          - symconst_type_tag   The symbolic constant represents a type tag.  The
768                                type the tag stands for is given explicitly.
769          - symconst_type_size  The symbolic constant represents the size of a type.
770                                The type of which the constant represents the size
771                                is given explicitly.
772          - symconst_type_align The symbolic constant represents the alignment of a
773                                type.  The type of which the constant represents the
774                                size is given explicitly.
775          - symconst_addr_ent   The symbolic constant represents the address of an
776                                entity (variable or method).  The variable is given
777                                explicitly by a firm entity.
778          - symconst_ofs_ent    The symbolic constant represents the offset of an
779                                entity in its owner type.
780          - symconst_enum_const The symbolic constant is a enumeration constant of
781                                an enumeration type."""
782         mode       = "mode_P"
783         flags      = [ "constlike", "start_block" ]
784         knownBlock = True
785         pinned     = "no"
786         attrs      = [
787                 dict(
788                         type = "ir_entity*",
789                         name = "entity",
790                         noprop = True
791                 )
792         ]
793         attr_struct = "symconst_attr"
794         customSerializer = True
795
796 class Sync(Op):
797         """The Sync operation unifies several partial memory blocks. These blocks
798         have to be pairwise disjunct or the values in common locations have to
799         be identical.  This operation allows to specify all operations that
800         eventually need several partial memory blocks as input with a single
801         entrance by unifying the memories with a preceding Sync operation."""
802         mode     = "mode_M"
803         flags    = []
804         pinned   = "no"
805         arity    = "dynamic"
806
807 class Tuple(Op):
808         """Builds a Tuple from single values.
809
810         This is needed to implement optimizations that remove a node that produced
811         a tuple.  The node can be replaced by the Tuple operation so that the
812         following Proj nodes have not to be changed. (They are hard to find due to
813         the implementation with pointers in only one direction.) The Tuple node is
814         smaller than any other node, so that a node can be changed into a Tuple by
815         just changing it's opcode and giving it a new in array."""
816         arity  = "variable"
817         mode   = "mode_T"
818         pinned = "no"
819         flags  = [ "labeled" ]
820
821 class Unknown(Op):
822         """Returns an unknown (at compile- and runtime) value. It is a valid
823         optimisation to replace an Unknown by any other constant value."""
824         knownBlock = True
825         pinned     = "yes"
826         block      = "get_irg_start_block(irg)"
827         flags      = [ "cfopcode", "start_block", "constlike", "dump_noblock" ]
828
829 # Prepare node list
830
831 def getOpList(namespace):
832         nodes = []
833         for t in namespace.values():
834                 if type(t) != type:
835                         continue
836
837                 if issubclass(t, Op):
838                         setnodedefaults(t)
839                         nodes.append(t)
840         return nodes
841
842 nodes = getOpList(globals())
843 nodes = sorted(nodes, lambda x,y: cmp(x.name, y.name))