remove special case with ir_cons_flags argument
[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         init = '''
534         res->attr.load.volatility = flags & cons_volatile ? volatility_is_volatile : volatility_non_volatile;
535         res->attr.load.aligned = flags & cons_unaligned ? align_non_aligned : align_is_aligned;
536         '''
537
538 class Minus(Unop):
539         """returns the difference between its operands"""
540         flags = []
541
542 class Mod(Op):
543         """returns the remainder of its operands from an implied division.
544
545         Examples:
546         * mod(5,3)   produces 2
547         * mod(5,-3)  produces 2
548         * mod(-5,3)  produces -2
549         * mod(-5,-3) produces -2
550         """
551         ins   = [ "mem", "left", "right" ]
552         outs  = [
553                 ("M",         "memory result",                         "pn_Generic_M"),
554                 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
555                 ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
556                 ("res",       "result of computation",                 "pn_Generic_other"),
557         ]
558         flags = [ "fragile", "uses_memory" ]
559         attrs_name = "divmod"
560         attrs = [
561                 dict(
562                         type = "ir_mode*",
563                         name = "resmode"
564                 ),
565         ]
566         attr_struct = "divmod_attr"
567         pinned      = "exception"
568         op_index    = 1
569         arity_override = "oparity_binary"
570
571 class Mul(Binop):
572         """returns the product of its operands"""
573         flags = [ "commutative" ]
574
575 class Mulh(Binop):
576         """returns the upper word of the product of its operands (the part which
577         would not fit into the result mode of a normal Mul anymore)"""
578         flags = [ "commutative" ]
579
580 class Mux(Op):
581         """returns the false or true operand depending on the value of the sel
582         operand"""
583         ins    = [ "sel", "false", "true" ]
584         flags  = []
585         pinned = "no"
586
587 class NoMem(Op):
588         """Placeholder node for cases where you don't need any memory input"""
589         mode          = "mode_M"
590         flags         = [ "dump_noblock", "dump_noinput" ]
591         pinned        = "yes"
592         knownBlock    = True
593         block         = "get_irg_start_block(irg)"
594         singleton     = True
595
596 class Not(Unop):
597         """returns the logical complement of a value. Works for integer values too.
598         If the input is false/zero then true/one is returned, otherwise false/zero
599         is returned."""
600         flags = []
601
602 class Or(Binop):
603         """returns the result of a bitwise or operation of its operands"""
604         flags = [ "commutative" ]
605
606 class Phi(Op):
607         """Choose a value based on control flow. A phi node has 1 input for each
608         predecessor of its block. If a block is entered from its nth predecessor
609         all phi nodes produce their nth input as result."""
610         pinned        = "yes"
611         arity         = "variable"
612         flags         = []
613         attr_struct   = "phi_attr"
614         init = '''
615         /* Memory Phis in endless loops must be kept alive.
616            As we can't distinguish these easily we keep all of them alive. */
617         if (is_Phi(res) && mode == mode_M)
618                 add_End_keepalive(get_irg_end(irg), res);
619         '''
620
621 class Pin(Op):
622         """Pin the value of the node node in the current block. No users of the Pin
623         node can float above the Block of the Pin. The node cannot float behind
624         this block. Often used to Pin the NoMem node."""
625         ins      = [ "op" ]
626         mode     = "get_irn_mode(irn_op)"
627         flags    = [ "highlevel" ]
628         pinned   = "yes"
629
630 class Proj(Op):
631         """returns an entry of a tuple value"""
632         ins              = [ "pred" ]
633         flags            = []
634         pinned           = "no"
635         knownBlock       = True
636         knownGraph       = True
637         block            = "get_nodes_block(irn_pred)"
638         graph            = "get_irn_irg(irn_pred)"
639         customSerializer = True
640         attrs      = [
641                 dict(
642                         type = "long",
643                         name = "proj",
644                 ),
645         ]
646         attr_struct = "proj_attr"
647
648 class Quot(Op):
649         """returns the quotient of its 2 operands, floatingpoint version"""
650         ins   = [ "mem", "left", "right" ]
651         outs  = [
652                 ("M",         "memory result",                         "pn_Generic_M"),
653                 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
654                 ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
655                 ("res",       "result of computation",                 "pn_Generic_other"),
656         ]
657         flags = [ "fragile", "uses_memory" ]
658         attrs_name = "divmod"
659         attrs = [
660                 dict(
661                         type = "ir_mode*",
662                         name = "resmode"
663                 ),
664         ]
665         attr_struct = "divmod_attr"
666         pinned      = "exception"
667         op_index    = 1
668         arity_override = "oparity_binary"
669
670 class Raise(Op):
671         """Raises an exception. Unconditional change of control flow. Writes an
672         explicit Except variable to memory to pass it to the exception handler.
673         Must be lowered to a Call to a runtime check function."""
674         ins    = [ "mem", "exo_ptr" ]
675         outs  = [
676                 ("M", "memory result",                     "pn_Generic_M"),
677                 ("X", "control flow to exception handler", "pn_Generic_X_regular"),
678         ]
679         flags  = [ "highlevel", "cfopcode" ]
680         pinned = "yes"
681
682 class Return(Op):
683         """Returns from the current function. Takes memory and return values as
684         operands."""
685         ins      = [ "mem" ]
686         arity    = "variable"
687         mode     = "mode_X"
688         flags    = [ "cfopcode" ]
689         pinned   = "yes"
690
691 class Rotl(Binop):
692         """Returns its first operand bits rotated left by the amount in the 2nd
693         operand"""
694         flags    = []
695
696 class Sel(Op):
697         """Computes the address of a entity of a compound type given the base
698         address of an instance of the compound type."""
699         ins    = [ "mem", "ptr" ]
700         arity  = "variable"
701         flags  = []
702         mode   = "is_Method_type(get_entity_type(entity)) ? mode_P_code : mode_P_data"
703         pinned = "no"
704         attrs  = [
705                 dict(
706                         type = "ir_entity*",
707                         name = "entity"
708                 )
709         ]
710         attr_struct = "sel_attr"
711
712 class Shl(Binop):
713         """Returns its first operands bits shifted left by the amount of the 2nd
714         operand"""
715         flags = []
716
717 class Shr(Binop):
718         """Returns its first operands bits shifted right by the amount of the 2nd
719         operand. No special handling for the sign bit (zero extension)"""
720         flags = []
721
722 class Shrs(Binop):
723         """Returns its first operands bits shifted right by the amount of the 2nd
724         operand. The leftmost bit (usually the sign bit) stays the same
725         (sign extension)"""
726         flags = []
727
728 class Start(Op):
729         """The first node of a graph. Execution starts with this node."""
730         outs       = [
731                 ("X_initial_exec", "control flow"),
732                 ("M",              "initial memory"),
733                 ("P_frame_base",   "frame base pointer"),
734                 ("P_tls",          "pointer to thread local storage segment"),
735                 ("T_args",         "function arguments")
736         ]
737         mode             = "mode_T"
738         pinned           = "yes"
739         flags            = [ "cfopcode" ]
740         singleton        = True
741         knownBlock       = True
742         customSerializer = True
743         block            = "get_irg_start_block(irg)"
744
745 class Store(Op):
746         """Stores a value into memory (heap or stack)."""
747         ins      = [ "mem", "ptr", "value" ]
748         outs  = [
749                 ("M",         "memory result",                         "pn_Generic_M"),
750                 ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
751                 ("X_except",  "control flow when exception occured",   "pn_Generic_X_except"),
752         ]
753         flags    = [ "fragile", "uses_memory" ]
754         pinned   = "exception"
755         attr_struct = "store_attr"
756         pinned_init = "flags & cons_floats ? op_pin_state_floats : op_pin_state_pinned"
757         constructor_args = [
758                 dict(
759                         type = "ir_cons_flags",
760                         name = "flags",
761                 ),
762         ]
763         init = '''
764         res->attr.store.volatility = flags & cons_volatile ? volatility_is_volatile : volatility_non_volatile;
765         res->attr.store.aligned = flags & cons_unaligned ? align_non_aligned : align_is_aligned;
766         '''
767
768 class Sub(Binop):
769         """returns the difference of its operands"""
770         flags = []
771
772 class SymConst(Op):
773         """A symbolic constant.
774
775          - symconst_type_tag   The symbolic constant represents a type tag.  The
776                                type the tag stands for is given explicitly.
777          - symconst_type_size  The symbolic constant represents the size of a type.
778                                The type of which the constant represents the size
779                                is given explicitly.
780          - symconst_type_align The symbolic constant represents the alignment of a
781                                type.  The type of which the constant represents the
782                                size is given explicitly.
783          - symconst_addr_ent   The symbolic constant represents the address of an
784                                entity (variable or method).  The variable is given
785                                explicitly by a firm entity.
786          - symconst_ofs_ent    The symbolic constant represents the offset of an
787                                entity in its owner type.
788          - symconst_enum_const The symbolic constant is a enumeration constant of
789                                an enumeration type."""
790         mode       = "mode_P"
791         flags      = [ "constlike", "start_block" ]
792         knownBlock = True
793         pinned     = "no"
794         attrs      = [
795                 dict(
796                         type = "ir_entity*",
797                         name = "entity",
798                         noprop = True
799                 )
800         ]
801         attr_struct = "symconst_attr"
802         customSerializer = True
803
804 class Sync(Op):
805         """The Sync operation unifies several partial memory blocks. These blocks
806         have to be pairwise disjunct or the values in common locations have to
807         be identical.  This operation allows to specify all operations that
808         eventually need several partial memory blocks as input with a single
809         entrance by unifying the memories with a preceding Sync operation."""
810         mode     = "mode_M"
811         flags    = []
812         pinned   = "no"
813         arity    = "dynamic"
814
815 class Tuple(Op):
816         """Builds a Tuple from single values.
817
818         This is needed to implement optimizations that remove a node that produced
819         a tuple.  The node can be replaced by the Tuple operation so that the
820         following Proj nodes have not to be changed. (They are hard to find due to
821         the implementation with pointers in only one direction.) The Tuple node is
822         smaller than any other node, so that a node can be changed into a Tuple by
823         just changing it's opcode and giving it a new in array."""
824         arity  = "variable"
825         mode   = "mode_T"
826         pinned = "no"
827         flags  = [ "labeled" ]
828
829 class Unknown(Op):
830         """Returns an unknown (at compile- and runtime) value. It is a valid
831         optimisation to replace an Unknown by any other constant value."""
832         knownBlock = True
833         pinned     = "yes"
834         block      = "get_irg_start_block(irg)"
835         flags      = [ "cfopcode", "start_block", "constlike", "dump_noblock" ]
836
837 # Prepare node list
838
839 def getOpList(namespace):
840         nodes = []
841         for t in namespace.values():
842                 if type(t) != type:
843                         continue
844
845                 if issubclass(t, Op):
846                         setnodedefaults(t)
847                         nodes.append(t)
848         return nodes
849
850 nodes = getOpList(globals())
851 nodes = sorted(nodes, lambda x,y: cmp(x.name, y.name))