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