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