sparc: Use be_peephole_exchange instead of exchange to update liveness information.
[libfirm] / scripts / ir_spec.py
1 # Firm node specifications
2 # The comments are in (standard python) restructured text format and are used
3 # to generate documentation.
4 from spec_util import abstract, setnodedefaults
5
6 class Op(object):
7         """Base class for firm nodes"""
8 abstract(Op)
9
10 class Unop(Op):
11         """Unary nodes have exactly 1 input"""
12         name     = "unop"
13         ins      = [
14                 ("op",  "operand"),
15         ]
16         op_index = 0
17         pinned   = "no"
18 abstract(Unop)
19
20 class Binop(Op):
21         """Binary nodes have exactly 2 inputs"""
22         name     = "binop"
23         ins      = [
24                 ( "left",   "first operand" ),
25                 ( "right", "second operand" ),
26         ]
27         op_index = 0
28         pinned   = "no"
29 abstract(Binop)
30
31 class Add(Binop):
32         """returns the sum of its operands"""
33         flags = [ "commutative" ]
34
35 class Alloc(Op):
36         """allocates a block of memory.
37         It can be specified whether the memory should be allocated to the stack
38         or to the heap.
39         Allocates memory for one or more objects (depending on value on count input).
40         """
41         ins   = [
42                 ("mem",   "memory dependency" ),
43                 ("count", "number of objects to allocate" ),
44         ]
45         outs  = [
46                 ("M",         "memory result"),
47                 ("res",       "pointer to newly allocated memory"),
48                 ("X_regular", "control flow when no exception occurs"),
49                 ("X_except",  "control flow when exception occured"),
50         ]
51         attrs = [
52                 dict(
53                         name    = "type",
54                         type    = "ir_type*",
55                         comment = "type of the objects to allocate",
56                 ),
57                 dict(
58                         name    = "where",
59                         type    = "ir_where_alloc",
60                         comment = "whether to allocate the variable on the stack or heap",
61                 )
62         ]
63         flags       = [ "fragile", "uses_memory" ]
64         pinned      = "exception"
65         throws_init = "false"
66         pinned_init = "op_pin_state_pinned"
67         attr_struct = "alloc_attr"
68
69 class Anchor(Op):
70         """utiliy node used to "hold" nodes in a graph that might possibly not be
71         reachable by other means or which should be reachable immediately without
72         searching through the graph.
73         Each firm-graph contains exactly one anchor node whose address is always
74         known. All other well-known graph-nodes like Start, End, NoMem, Bad, ...
75         are found by looking at the respective Anchor operand."""
76         mode             = "mode_ANY"
77         arity            = "variable"
78         flags            = [ "dump_noblock" ]
79         pinned           = "yes"
80         attr_struct      = "irg_attr"
81         knownBlock       = True
82         singleton        = True
83         noconstructor    = True
84         customSerializer = True
85
86 class And(Binop):
87         """returns the result of a bitwise and operation of its operands"""
88         flags    = [ "commutative" ]
89
90 class ASM(Op):
91         """executes assembler fragments of the target machine.
92
93         The node contains a template for an assembler snippet. The compiler will
94         replace occurences of %0 to %9 with input/output registers,
95         %% with a single % char. Some backends allow additional specifiers (for
96         example %w3, %l3, %h3 on x86 to get a 16bit, 8hit low, 8bit high part
97         of a register).
98         After the replacements the text is emitted into the final assembly.
99
100         The clobber list contains names of registers which have an undefined value
101         after the assembler instruction is executed; it may also contain 'memory'
102         or 'cc' if global state/memory changes or the condition code registers
103         (some backends implicitely set cc, memory clobbers on all ASM statements).
104
105         Example (an i386 instruction)::
106
107                 ASM(text="btsl %1, %0",
108                         input_constraints = ["=m", "r"],
109                         clobbers = ["cc"])
110
111         As there are no output, the %0 references the first input which is just an
112         address which the asm operation writes to. %1 references to an input which
113         is passed as a register. The condition code register has an unknown value
114         after the instruction.
115
116         (This format is inspired by the gcc extended asm syntax)
117         """
118         mode             = "mode_T"
119         arity            = "variable"
120         flags            = [ "keep", "uses_memory" ]
121         pinned           = "memory"
122         pinned_init      = "op_pin_state_pinned"
123         attr_struct      = "asm_attr"
124         attrs_name       = "assem"
125         customSerializer = True
126         ins   = [
127                 ("mem",    "memory dependency"),
128         ]
129         attrs = [
130                 dict(
131                         name    = "input_constraints",
132                         type    = "ir_asm_constraint*",
133                         comment = "input constraints",
134                 ),
135                 dict(
136                         name    = "n_output_constraints",
137                         type    = "size_t",
138                         noprop  = True,
139                         comment = "number of output constraints",
140                 ),
141                 dict(
142                         name    = "output_constraints",
143                         type    = "ir_asm_constraint*",
144                         comment = "output constraints",
145                 ),
146                 dict(
147                         name    = "n_clobbers",
148                         type    = "size_t",
149                         noprop  = True,
150                         comment = "number of clobbered registers/memory",
151                 ),
152                 dict(
153                         name    = "clobbers",
154                         type    = "ident**",
155                         comment = "list of clobbered registers/memory",
156                 ),
157                 dict(
158                         name    = "text",
159                         type    = "ident*",
160                         comment = "assembler text",
161                 ),
162         ]
163         # constructor is written manually at the moment, because of the clobbers+
164         # constraints arrays needing special handling (2 arguments for 1 attribute)
165         noconstructor = True
166
167 class Bad(Op):
168         """Bad nodes indicate invalid input, which is values which should never be
169         computed.
170
171         The typical use case for the Bad node is removing unreachable code.
172         Frontends should set the current_block to Bad when it is clear that
173         following code must be unreachable (ie. after a goto or return statement).
174         Optimisations also set block predecessors to Bad when it becomes clear,
175         that a control flow edge can never be executed.
176
177         The gigo optimisations ensures that nodes with Bad as their block, get
178         replaced by Bad themselfes. Nodes with at least 1 Bad input get exchanged
179         with Bad too. Exception to this rule are Block, Phi, Tuple and End node;
180         This is because removing inputs from a Block is hairy operation (requiring,
181         Phis to be shortened too for example). So instead of removing block inputs
182         they are set to Bad, and the actual removal is left to the control flow
183         optimisation phase. Block, Phi, Tuple with only Bad inputs however are
184         replaced by Bad right away."""
185         flags         = [ "start_block", "dump_noblock" ]
186         pinned        = "yes"
187         knownBlock    = True
188         block         = "get_irg_start_block(irg)"
189         attr_struct   = "bad_attr"
190         init = '''
191         res->attr.bad.irg.irg = irg;
192         '''
193
194 class Deleted(Op):
195         """Internal node which is temporary set to nodes which are already removed
196         from the graph."""
197         mode             = "mode_Bad"
198         flags            = [ ]
199         pinned           = "yes"
200         noconstructor    = True
201         customSerializer = True # this has no serializer
202
203 class Block(Op):
204         """A basic block"""
205         mode             = "mode_BB"
206         knownBlock       = True
207         block            = "NULL"
208         pinned           = "yes"
209         arity            = "variable"
210         flags            = []
211         attr_struct      = "block_attr"
212         attrs            = [
213                 dict(
214                         name    = "entity",
215                         type    = "ir_entity*",
216                         comment = "entity representing this block",
217                         init    = "NULL",
218                 ),
219         ]
220         customSerializer = True
221
222         init = '''
223         res->attr.block.irg.irg     = irg;
224         res->attr.block.backedge    = new_backedge_arr(irg->obst, arity);
225         set_Block_matured(res, 1);
226
227         /* Create and initialize array for Phi-node construction. */
228         if (get_irg_phase_state(irg) == phase_building) {
229                 res->attr.block.graph_arr = NEW_ARR_D(ir_node *, irg->obst, irg->n_loc);
230                 memset(res->attr.block.graph_arr, 0, irg->n_loc * sizeof(ir_node*));
231         }
232         '''
233
234 class Borrow(Binop):
235         """Returns the borrow bit from and implied subtractions of its 2 operands"""
236         flags = []
237
238 class Bound(Op):
239         """Performs a bounds-check: if lower <= index < upper then return index,
240         otherwise throw an exception."""
241         ins    = [
242                 ("mem",    "memory dependency"),
243                 ("index",  "value to test"),
244                 ("lower",  "lower bound (inclusive)"),
245                 ("upper",  "upper bound (exclusive)"),
246         ]
247         outs  = [
248                 ("M",         "memory result"),
249                 ("res",       "the checked index"),
250                 ("X_regular", "control flow when no exception occurs"),
251                 ("X_except",  "control flow when exception occured"),
252         ]
253         flags  = [ "fragile", "highlevel" ]
254         pinned = "exception"
255         pinned_init = "op_pin_state_pinned"
256         throws_init = "false"
257         attr_struct = "bound_attr"
258
259 class Builtin(Op):
260         """performs a backend-specific builtin."""
261         ins      = [
262                 ("mem", "memory dependency"),
263         ]
264         arity    = "variable"
265         outs     = [
266                 ("M", "memory result"),
267                 # results follow here
268         ]
269         flags    = [ "uses_memory" ]
270         attrs    = [
271                 dict(
272                         type    = "ir_builtin_kind",
273                         name    = "kind",
274                         comment = "kind of builtin",
275                 ),
276                 dict(
277                         type    = "ir_type*",
278                         name    = "type",
279                         comment = "method type for the builtin call",
280                 )
281         ]
282         pinned      = "memory"
283         pinned_init = "op_pin_state_pinned"
284         attr_struct = "builtin_attr"
285         init   = '''
286         assert((get_unknown_type() == type) || is_Method_type(type));
287         '''
288
289 class Call(Op):
290         """Calls other code. Control flow is transfered to ptr, additional
291         operands are passed to the called code. Called code usually performs a
292         return operation. The operands of this return operation are the result
293         of the Call node."""
294         ins      = [
295                 ("mem",   "memory dependency"),
296                 ("ptr",   "pointer to called code"),
297         ]
298         arity    = "variable"
299         outs     = [
300                 ("M",                "memory result"),
301                 ("T_result",         "tuple containing all results"),
302                 ("X_regular",        "control flow when no exception occurs"),
303                 ("X_except",         "control flow when exception occured"),
304         ]
305         flags    = [ "fragile", "uses_memory" ]
306         attrs    = [
307                 dict(
308                         type    = "ir_type*",
309                         name    = "type",
310                         comment = "type of the call (usually type of the called procedure)",
311                 ),
312         ]
313         attr_struct = "call_attr"
314         pinned      = "memory"
315         pinned_init = "op_pin_state_pinned"
316         throws_init = "false"
317         init = '''
318         assert((get_unknown_type() == type) || is_Method_type(type));
319         '''
320
321 class Carry(Binop):
322         """Computes the value of the carry-bit that would result when adding the 2
323         operands"""
324         flags = [ "commutative" ]
325
326 class Cast(Unop):
327         """perform a high-level type cast"""
328         mode     = "get_irn_mode(irn_op)"
329         flags    = [ "highlevel" ]
330         attrs    = [
331                 dict(
332                         type    = "ir_type*",
333                         name    = "type",
334                         comment = "target type of the case",
335                 )
336         ]
337         attr_struct = "cast_attr"
338         init     = "assert(is_atomic_type(type));"
339
340 class Cmp(Binop):
341         """Compares its two operands and checks whether a specified
342            relation (like less or equal) is fulfilled."""
343         flags = []
344         mode  = "mode_b"
345         attrs = [
346                 dict(
347                         type    = "ir_relation",
348                         name    = "relation",
349                         comment = "Comparison relation"
350                 )
351         ]
352         attr_struct = "cmp_attr"
353
354 class Cond(Op):
355         """Conditionally change control flow."""
356         ins      = [
357                 ("selector",  "condition parameter"),
358         ]
359         outs     = [
360                 ("false", "control flow if operand is \"false\""),
361                 ("true",  "control flow if operand is \"true\""),
362         ]
363         flags    = [ "cfopcode", "forking" ]
364         pinned   = "yes"
365         attrs    = [
366                 dict(
367                         name    = "jmp_pred",
368                         type    = "cond_jmp_predicate",
369                         init    = "COND_JMP_PRED_NONE",
370                         comment = "can indicate the most likely jump",
371                 ),
372         ]
373         attr_struct = "cond_attr"
374
375 class Switch(Op):
376         """Change control flow. The destination is choosen based on an integer input value which is looked up in a table.
377
378         Backends can implement this efficiently using a jump table."""
379         ins    = [
380                 ("selector", "input selector"),
381         ]
382         outs   = [
383                 ("default", "control flow if no other case matches"),
384         ]
385         flags  = [ "cfopcode", "forking" ]
386         pinned = "yes"
387         attrs  = [
388                 dict(
389                         name    = "n_outs",
390                         type    = "unsigned",
391                         comment = "number of outputs (including pn_Switch_default)",
392                 ),
393                 dict(
394                         name    = "table",
395                         type    = "ir_switch_table*",
396                         comment = "table describing mapping from input values to Proj numbers",
397                 ),
398         ]
399         attr_struct = "switch_attr"
400         attrs_name  = "switcha"
401
402 class Confirm(Op):
403         """Specifies constraints for a value. This allows explicit representation
404         of path-sensitive properties. (Example: This value is always >= 0 on 1
405         if-branch then all users within that branch are rerouted to a confirm-node
406         specifying this property).
407
408         A constraint is specified for the relation between value and bound.
409         value is always returned.
410         Note that this node does NOT check or assert the constraint, it merely
411         specifies it."""
412         ins      = [
413                 ("value",  "value to express a constraint for"),
414                 ("bound",  "value to compare against"),
415         ]
416         mode     = "get_irn_mode(irn_value)"
417         flags    = [ "highlevel" ]
418         pinned   = "yes"
419         attrs    = [
420                 dict(
421                         name    = "relation",
422                         type    = "ir_relation",
423                         comment = "relation of value to bound",
424                 ),
425         ]
426         attr_struct = "confirm_attr"
427
428 class Const(Op):
429         """Returns a constant value."""
430         flags      = [ "constlike", "start_block" ]
431         block      = "get_irg_start_block(irg)"
432         mode       = "get_tarval_mode(tarval)"
433         knownBlock = True
434         pinned     = "no"
435         attrs      = [
436                 dict(
437                         type    = "ir_tarval*",
438                         name    = "tarval",
439                         comment = "constant value (a tarval object)",
440                 )
441         ]
442         attr_struct = "const_attr"
443         attrs_name  = "con"
444
445 class Conv(Unop):
446         """Converts values between modes"""
447         flags = []
448         attrs = [
449                 dict(
450                         name    = "strict",
451                         type    = "int",
452                         init    = "0",
453                         comment = "force floating point to restrict precision even if backend computes in higher precision (deprecated)",
454                 )
455         ]
456         attr_struct = "conv_attr"
457
458 class CopyB(Op):
459         """Copies a block of memory with statically known size/type."""
460         ins   = [
461                 ("mem",  "memory dependency"),
462                 ("dst",  "destination address"),
463                 ("src",  "source address"),
464         ]
465         outs  = [
466                 ("M",         "memory result"),
467                 ("X_regular", "control flow when no exception occurs"),
468                 ("X_except",  "control flow when exception occured"),
469         ]
470         flags = [ "fragile", "uses_memory" ]
471         attrs = [
472                 dict(
473                         name    = "type",
474                         type    = "ir_type*",
475                         comment = "type of copied data",
476                 )
477         ]
478         attr_struct = "copyb_attr"
479         pinned      = "memory"
480         pinned_init = "op_pin_state_pinned"
481         throws_init = "false"
482
483 class Div(Op):
484         """returns the quotient of its 2 operands"""
485         ins   = [
486                 ("mem",   "memory dependency"),
487                 ("left",  "first operand"),
488                 ("right", "second operand"),
489         ]
490         outs  = [
491                 ("M",         "memory result"),
492                 ("res",       "result of computation"),
493                 ("X_regular", "control flow when no exception occurs"),
494                 ("X_except",  "control flow when exception occured"),
495         ]
496         flags = [ "fragile", "uses_memory" ]
497         attrs = [
498                 dict(
499                         type    = "ir_mode*",
500                         name    = "resmode",
501                         comment = "mode of the result value",
502                 ),
503                 dict(
504                         name = "no_remainder",
505                         type = "int",
506                         init = "0",
507                 )
508         ]
509         attr_struct = "div_attr"
510         pinned      = "exception"
511         throws_init = "false"
512         op_index    = 1
513         arity_override = "oparity_binary"
514
515 class Dummy(Op):
516         """A placeholder value. This is used when constructing cyclic graphs where
517         you have cases where not all predecessors of a phi-node are known. Dummy
518         nodes are used for the unknown predecessors and replaced later."""
519         ins        = []
520         flags      = [ "cfopcode", "start_block", "constlike", "dump_noblock" ]
521         knownBlock = True
522         pinned     = "yes"
523         block      = "get_irg_start_block(irg)"
524
525 class End(Op):
526         """Last node of a graph. It references nodes in endless loops (so called
527         keepalive edges)"""
528         mode             = "mode_X"
529         pinned           = "yes"
530         arity            = "dynamic"
531         flags            = [ "cfopcode" ]
532         knownBlock       = True
533         block            = "get_irg_end_block(irg)"
534         singleton        = True
535
536 class Eor(Binop):
537         """returns the result of a bitwise exclusive or operation of its operands.
538
539         This is also known as the Xor operation."""
540         flags    = [ "commutative" ]
541
542 class Free(Op):
543         """Frees a block of memory previously allocated by an Alloc node"""
544         ins    = [
545                 ("mem",   "memory dependency" ),
546                 ("ptr",   "pointer to the object to free"),
547                 ("count", "number of objects to allocate" ),
548         ]
549         mode   = "mode_M"
550         flags  = [ "uses_memory" ]
551         pinned = "yes"
552         attrs  = [
553                 dict(
554                         name    = "type",
555                         type    = "ir_type*",
556                         comment = "type of the allocated variable",
557                 ),
558                 dict(
559                         name    = "where",
560                         type    = "ir_where_alloc",
561                         comment = "whether allocation was on the stack or heap",
562                 )
563         ]
564         attr_struct = "free_attr"
565
566 class Id(Op):
567         """Returns its operand unchanged.
568
569         This is mainly used when exchanging nodes. Usually you shouldn't see Id
570         nodes since the getters/setters for node inputs skip them automatically."""
571         ins    = [
572            ("pred", "the value which is returned unchanged")
573         ]
574         pinned = "no"
575         flags  = []
576
577 class IJmp(Op):
578         """Jumps to the code in its argument. The code has to be in the same
579         function and the the destination must be one of the blocks reachable
580         by the tuple results"""
581         mode     = "mode_X"
582         pinned   = "yes"
583         ins      = [
584            ("target", "target address of the jump"),
585         ]
586         flags    = [ "cfopcode", "forking", "keep", "unknown_jump" ]
587
588 class InstOf(Op):
589         """Tests whether an object is an instance of a class-type"""
590         ins   = [
591            ("store", "memory dependency"),
592            ("obj",   "pointer to object being queried")
593         ]
594         outs  = [
595                 ("M",         "memory result"),
596                 ("res",       "checked object pointer"),
597                 ("X_regular", "control flow when no exception occurs"),
598                 ("X_except",  "control flow when exception occured"),
599         ]
600         flags = [ "highlevel" ]
601         attrs = [
602                 dict(
603                         name    = "type",
604                         type    = "ir_type*",
605                         comment = "type to check ptr for",
606                 )
607         ]
608         attr_struct = "io_attr"
609         pinned      = "memory"
610         pinned_init = "op_pin_state_floats"
611
612 class Jmp(Op):
613         """Jumps to the block connected through the out-value"""
614         mode     = "mode_X"
615         pinned   = "yes"
616         ins      = []
617         flags    = [ "cfopcode" ]
618
619 class Load(Op):
620         """Loads a value from memory (heap or stack)."""
621         ins   = [
622                 ("mem", "memory dependency"),
623                 ("ptr",  "address to load from"),
624         ]
625         outs  = [
626                 ("M",         "memory result"),
627                 ("res",       "result of load operation"),
628                 ("X_regular", "control flow when no exception occurs"),
629                 ("X_except",  "control flow when exception occured"),
630         ]
631         flags    = [ "fragile", "uses_memory" ]
632         pinned   = "exception"
633         attrs    = [
634                 dict(
635                         type      = "ir_mode*",
636                         name      = "mode",
637                         comment   = "mode of the value to be loaded",
638                 ),
639                 dict(
640                         type      = "ir_volatility",
641                         name      = "volatility",
642                         comment   = "volatile loads are a visible side-effect and may not be optimized",
643                         init      = "flags & cons_volatile ? volatility_is_volatile : volatility_non_volatile",
644                         to_flags  = "%s == volatility_is_volatile ? cons_volatile : cons_none"
645                 ),
646                 dict(
647                         type      = "ir_align",
648                         name      = "unaligned",
649                         comment   = "pointers to unaligned loads don't need to respect the load-mode/type alignments",
650                         init      = "flags & cons_unaligned ? align_non_aligned : align_is_aligned",
651                         to_flags  = "%s == align_non_aligned ? cons_unaligned : cons_none"
652                 ),
653         ]
654         attr_struct = "load_attr"
655         constructor_args = [
656                 dict(
657                         type    = "ir_cons_flags",
658                         name    = "flags",
659                         comment = "specifies alignment, volatility and pin state",
660                 ),
661         ]
662         pinned_init = "flags & cons_floats ? op_pin_state_floats : op_pin_state_pinned"
663         throws_init = "(flags & cons_throws_exception) != 0"
664
665 class Minus(Unop):
666         """returns the difference between its operands"""
667         flags = []
668
669 class Mod(Op):
670         """returns the remainder of its operands from an implied division.
671
672         Examples:
673
674         * mod(5,3)   produces 2
675         * mod(5,-3)  produces 2
676         * mod(-5,3)  produces -2
677         * mod(-5,-3) produces -2
678         """
679         ins   = [
680                 ("mem",   "memory dependency"),
681                 ("left",  "first operand"),
682                 ("right", "second operand"),
683         ]
684         outs  = [
685                 ("M",         "memory result"),
686                 ("res",       "result of computation"),
687                 ("X_regular", "control flow when no exception occurs"),
688                 ("X_except",  "control flow when exception occured"),
689         ]
690         flags = [ "fragile", "uses_memory" ]
691         attrs = [
692                 dict(
693                         type    = "ir_mode*",
694                         name    = "resmode",
695                         comment = "mode of the result",
696                 ),
697         ]
698         attr_struct = "mod_attr"
699         pinned      = "exception"
700         throws_init = "false"
701         op_index    = 1
702         arity_override = "oparity_binary"
703
704 class Mul(Binop):
705         """returns the product of its operands"""
706         flags = [ "commutative" ]
707
708 class Mulh(Binop):
709         """returns the upper word of the product of its operands (the part which
710         would not fit into the result mode of a normal Mul anymore)"""
711         flags = [ "commutative" ]
712
713 class Mux(Op):
714         """returns the false or true operand depending on the value of the sel
715         operand"""
716         ins    = [
717            ("sel",   "value making the output selection"),
718            ("false", "selected if sel input is false"),
719            ("true",  "selected if sel input is true"),
720         ]
721         flags  = []
722         pinned = "no"
723
724 class NoMem(Op):
725         """Placeholder node for cases where you don't need any memory input"""
726         mode          = "mode_M"
727         flags         = [ "dump_noblock" ]
728         pinned        = "yes"
729         knownBlock    = True
730         block         = "get_irg_start_block(irg)"
731         singleton     = True
732
733 class Not(Unop):
734         """returns the bitwise complement of a value. Works for boolean values, too."""
735         flags = []
736
737 class Or(Binop):
738         """returns the result of a bitwise or operation of its operands"""
739         flags = [ "commutative" ]
740
741 class Phi(Op):
742         """Choose a value based on control flow. A phi node has 1 input for each
743         predecessor of its block. If a block is entered from its nth predecessor
744         all phi nodes produce their nth input as result."""
745         pinned        = "yes"
746         arity         = "variable"
747         flags         = []
748         attr_struct   = "phi_attr"
749         init          = '''
750         res->attr.phi.u.backedge = new_backedge_arr(irg->obst, arity);'''
751         init_after_opt = '''
752         /* Memory Phis in endless loops must be kept alive.
753            As we can't distinguish these easily we keep all of them alive. */
754         if (is_Phi(res) && mode == mode_M)
755                 add_End_keepalive(get_irg_end(irg), res);'''
756         customSerializer = True
757
758 class Pin(Op):
759         """Pin the value of the node node in the current block. No users of the Pin
760         node can float above the Block of the Pin. The node cannot float behind
761         this block. Often used to Pin the NoMem node."""
762         ins      = [
763                 ("op", "value which is pinned"),
764         ]
765         mode     = "get_irn_mode(irn_op)"
766         flags    = [ "highlevel" ]
767         pinned   = "yes"
768
769 class Proj(Op):
770         """returns an entry of a tuple value"""
771         ins              = [
772                 ("pred", "the tuple value from which a part is extracted"),
773         ]
774         flags            = []
775         pinned           = "no"
776         knownBlock       = True
777         knownGraph       = True
778         block            = "get_nodes_block(irn_pred)"
779         graph            = "get_irn_irg(irn_pred)"
780         attrs      = [
781                 dict(
782                         type    = "long",
783                         name    = "proj",
784                         comment = "number of tuple component to be extracted",
785                 ),
786         ]
787         attr_struct = "proj_attr"
788
789 class Raise(Op):
790         """Raises an exception. Unconditional change of control flow. Writes an
791         explicit Except variable to memory to pass it to the exception handler.
792         Must be lowered to a Call to a runtime check function."""
793         ins    = [
794                 ("mem",     "memory dependency"),
795                 ("exo_ptr", "pointer to exception object to be thrown"),
796         ]
797         outs  = [
798                 ("M", "memory result"),
799                 ("X", "control flow to exception handler"),
800         ]
801         flags  = [ "highlevel", "cfopcode" ]
802         pinned = "yes"
803
804 class Return(Op):
805         """Returns from the current function. Takes memory and return values as
806         operands."""
807         ins      = [
808                 ("mem", "memory dependency"),
809         ]
810         arity    = "variable"
811         mode     = "mode_X"
812         flags    = [ "cfopcode" ]
813         pinned   = "yes"
814
815 class Rotl(Binop):
816         """Returns its first operand bits rotated left by the amount in the 2nd
817         operand"""
818         flags    = []
819
820 class Sel(Op):
821         """Computes the address of a entity of a compound type given the base
822         address of an instance of the compound type.
823
824         Optimisations assume that a Sel node can only produce a NULL pointer if the
825         ptr input was NULL."""
826         ins    = [
827                 ("mem", "memory dependency"),
828                 ("ptr", "pointer to object to select from"),
829         ]
830         arity  = "variable"
831         flags  = []
832         mode   = "is_Method_type(get_entity_type(entity)) ? mode_P_code : mode_P_data"
833         pinned = "no"
834         attrs  = [
835                 dict(
836                         type    = "ir_entity*",
837                         name    = "entity",
838                         comment = "entity which is selected",
839                 )
840         ]
841         attr_struct = "sel_attr"
842
843 class Shl(Binop):
844         """Returns its first operands bits shifted left by the amount of the 2nd
845         operand.
846         The right input (shift amount) must be an unsigned integer value.
847         If the result mode has modulo_shift!=0, then the effective shift amount is
848         the right input modulo this modulo_shift amount."""
849         flags = []
850
851 class Shr(Binop):
852         """Returns its first operands bits shifted right by the amount of the 2nd
853         operand. No special handling for the sign bit is performed (zero extension).
854         The right input (shift amount) must be an unsigned integer value.
855         If the result mode has modulo_shift!=0, then the effective shift amount is
856         the right input modulo this modulo_shift amount."""
857         flags = []
858
859 class Shrs(Binop):
860         """Returns its first operands bits shifted right by the amount of the 2nd
861         operand. The leftmost bit (usually the sign bit) stays the same
862         (sign extension).
863         The right input (shift amount) must be an unsigned integer value.
864         If the result mode has modulo_shift!=0, then the effective shift amount is
865         the right input modulo this modulo_shift amount."""
866         flags = []
867
868 class Start(Op):
869         """The first node of a graph. Execution starts with this node."""
870         outs       = [
871                 ("X_initial_exec", "control flow"),
872                 ("M",              "initial memory"),
873                 ("P_frame_base",   "frame base pointer"),
874                 ("T_args",         "function arguments")
875         ]
876         mode             = "mode_T"
877         pinned           = "yes"
878         flags            = [ "cfopcode" ]
879         singleton        = True
880         knownBlock       = True
881         block            = "get_irg_start_block(irg)"
882
883 class Store(Op):
884         """Stores a value into memory (heap or stack)."""
885         ins   = [
886            ("mem",   "memory dependency"),
887            ("ptr",   "address to store to"),
888            ("value", "value to store"),
889         ]
890         outs  = [
891                 ("M",         "memory result"),
892                 ("X_regular", "control flow when no exception occurs"),
893                 ("X_except",  "control flow when exception occured"),
894         ]
895         flags    = [ "fragile", "uses_memory" ]
896         pinned   = "exception"
897         attr_struct = "store_attr"
898         pinned_init = "flags & cons_floats ? op_pin_state_floats : op_pin_state_pinned"
899         throws_init = "(flags & cons_throws_exception) != 0"
900         attrs = [
901                 dict(
902                         type      = "ir_volatility",
903                         name      = "volatility",
904                         comment   = "volatile stores are a visible side-effect and may not be optimized",
905                         init      = "flags & cons_volatile ? volatility_is_volatile : volatility_non_volatile",
906                         to_flags  = "%s == volatility_is_volatile ? cons_volatile : cons_none"
907                 ),
908                 dict(
909                         type      = "ir_align",
910                         name      = "unaligned",
911                         comment   = "pointers to unaligned stores don't need to respect the load-mode/type alignments",
912                         init      = "flags & cons_unaligned ? align_non_aligned : align_is_aligned",
913                         to_flags  = "%s == align_non_aligned ? cons_unaligned : cons_none"
914                 ),
915         ]
916         constructor_args = [
917                 dict(
918                         type    = "ir_cons_flags",
919                         name    = "flags",
920                         comment = "specifies alignment, volatility and pin state",
921                 ),
922         ]
923
924 class Sub(Binop):
925         """returns the difference of its operands"""
926         flags = []
927
928 class SymConst(Op):
929         """A symbolic constant.
930
931          - *symconst_type_size* The symbolic constant represents the size of a type.
932                                 The type of which the constant represents the size
933                                 is given explicitly.
934          - *symconst_type_align* The symbolic constant represents the alignment of a
935                                 type.  The type of which the constant represents the
936                                 size is given explicitly.
937          - *symconst_addr_ent*  The symbolic constant represents the address of an
938                                 entity (variable or method).  The variable is given
939                                 explicitly by a firm entity.
940          - *symconst_ofs_ent*   The symbolic constant represents the offset of an
941                                 entity in its owner type.
942          - *symconst_enum_const* The symbolic constant is a enumeration constant of
943                                 an enumeration type."""
944         mode       = "mode_P"
945         flags      = [ "constlike", "start_block" ]
946         knownBlock = True
947         pinned     = "no"
948         attrs      = [
949                 dict(
950                         type    = "ir_entity*",
951                         name    = "entity",
952                         noprop  = True,
953                         comment = "entity whose address is returned",
954                 )
955         ]
956         attr_struct = "symconst_attr"
957         customSerializer = True
958         # constructor is written manually at the moment, because of the strange
959         # union argument
960         noconstructor = True
961
962 class Sync(Op):
963         """The Sync operation unifies several partial memory blocks. These blocks
964         have to be pairwise disjunct or the values in common locations have to
965         be identical.  This operation allows to specify all operations that
966         eventually need several partial memory blocks as input with a single
967         entrance by unifying the memories with a preceding Sync operation."""
968         mode     = "mode_M"
969         flags    = []
970         pinned   = "no"
971         arity    = "dynamic"
972
973 class Tuple(Op):
974         """Builds a Tuple from single values.
975
976         This is needed to implement optimizations that remove a node that produced
977         a tuple.  The node can be replaced by the Tuple operation so that the
978         following Proj nodes have not to be changed. (They are hard to find due to
979         the implementation with pointers in only one direction.) The Tuple node is
980         smaller than any other node, so that a node can be changed into a Tuple by
981         just changing its opcode and giving it a new in array."""
982         arity  = "variable"
983         mode   = "mode_T"
984         pinned = "no"
985         flags  = []
986
987 class Unknown(Op):
988         """Returns an unknown (at compile- and runtime) value. It is a valid
989         optimisation to replace an Unknown by any other constant value."""
990         knownBlock = True
991         pinned     = "yes"
992         block      = "get_irg_start_block(irg)"
993         flags      = [ "start_block", "constlike", "dump_noblock" ]
994
995 # Prepare node list
996
997 def getOpList(namespace):
998         nodes = []
999         for t in namespace.values():
1000                 if type(t) != type:
1001                         continue
1002
1003                 if issubclass(t, Op):
1004                         setnodedefaults(t)
1005                         nodes.append(t)
1006         return nodes
1007
1008 nodes = getOpList(globals())
1009 nodes = sorted(nodes, lambda x,y: cmp(x.name, y.name))