+ ]
+ flags = [ "fragile", "uses_memory" ]
+ pinned = "exception"
+ throws_init = "false"
+ pinned_init = "op_pin_state_pinned"
+ attr_struct = "alloc_attr"
+
+@op
+class Anchor:
+ """utiliy node used to "hold" nodes in a graph that might possibly not be
+ reachable by other means or which should be reachable immediately without
+ searching through the graph.
+ Each firm-graph contains exactly one anchor node whose address is always
+ known. All other well-known graph-nodes like Start, End, NoMem, Bad, ...
+ are found by looking at the respective Anchor operand."""
+ mode = "mode_ANY"
+ arity = "variable"
+ flags = [ "dump_noblock" ]
+ pinned = "yes"
+ attr_struct = "irg_attr"
+ knownBlock = True
+ singleton = True
+ noconstructor = True
+ customSerializer = True
+
+@op
+class And(Binop):
+ """returns the result of a bitwise and operation of its operands"""
+ flags = [ "commutative" ]
+
+@op
+class ASM:
+ """executes assembler fragments of the target machine.
+
+ The node contains a template for an assembler snippet. The compiler will
+ replace occurences of %0 to %9 with input/output registers,
+ %% with a single % char. Some backends allow additional specifiers (for
+ example %w3, %l3, %h3 on x86 to get a 16bit, 8hit low, 8bit high part
+ of a register).
+ After the replacements the text is emitted into the final assembly.
+
+ The clobber list contains names of registers which have an undefined value
+ after the assembler instruction is executed; it may also contain 'memory'
+ or 'cc' if global state/memory changes or the condition code registers
+ (some backends implicitely set cc, memory clobbers on all ASM statements).
+
+ Example (an i386 instruction)::
+
+ ASM(text="btsl %1, %0",
+ input_constraints = ["=m", "r"],
+ clobbers = ["cc"])
+
+ As there are no output, the %0 references the first input which is just an
+ address which the asm operation writes to. %1 references to an input which
+ is passed as a register. The condition code register has an unknown value
+ after the instruction.
+
+ (This format is inspired by the gcc extended asm syntax)
+ """
+ mode = "mode_T"
+ arity = "variable"
+ input_name = "input"
+ flags = [ "keep", "uses_memory" ]
+ pinned = "memory"
+ pinned_init = "op_pin_state_pinned"
+ attr_struct = "asm_attr"
+ attrs_name = "assem"
+ customSerializer = True
+ ins = [
+ ("mem", "memory dependency"),
+ ]
+ attrs = [
+ dict(
+ name = "input_constraints",
+ type = "ir_asm_constraint*",
+ comment = "input constraints",
+ ),
+ dict(
+ name = "n_output_constraints",
+ type = "size_t",
+ noprop = True,
+ comment = "number of output constraints",
+ ),
+ dict(
+ name = "output_constraints",
+ type = "ir_asm_constraint*",
+ comment = "output constraints",
+ ),
+ dict(
+ name = "n_clobbers",
+ type = "size_t",
+ noprop = True,
+ comment = "number of clobbered registers/memory",
+ ),
+ dict(
+ name = "clobbers",
+ type = "ident**",
+ comment = "list of clobbered registers/memory",
+ ),
+ dict(
+ name = "text",
+ type = "ident*",
+ comment = "assembler text",
+ ),
+ ]
+ # constructor is written manually at the moment, because of the clobbers+
+ # constraints arrays needing special handling (2 arguments for 1 attribute)
+ noconstructor = True
+
+@op
+class Bad:
+ """Bad nodes indicate invalid input, which is values which should never be
+ computed.
+
+ The typical use case for the Bad node is removing unreachable code.
+ Frontends should set the current_block to Bad when it is clear that
+ following code must be unreachable (ie. after a goto or return statement).
+ Optimisations also set block predecessors to Bad when it becomes clear,
+ that a control flow edge can never be executed.
+
+ The gigo optimisations ensures that nodes with Bad as their block, get
+ replaced by Bad themselves. Nodes with at least 1 Bad input get exchanged
+ with Bad too. Exception to this rule are Block, Phi, Tuple and End node;
+ This is because removing inputs from a Block is hairy operation (requiring,
+ Phis to be shortened too for example). So instead of removing block inputs
+ they are set to Bad, and the actual removal is left to the control flow
+ optimisation phase. Block, Phi, Tuple with only Bad inputs however are
+ replaced by Bad right away."""
+ flags = [ "start_block", "dump_noblock" ]
+ pinned = "yes"
+ knownBlock = True
+ block = "get_irg_start_block(irg)"
+ attr_struct = "bad_attr"
+ init = '''
+ res->attr.bad.irg.irg = irg;
+ '''
+
+@op
+class Deleted:
+ """Internal node which is temporary set to nodes which are already removed
+ from the graph."""
+ mode = "mode_Bad"
+ flags = [ ]
+ pinned = "yes"
+ noconstructor = True
+ customSerializer = True # this has no serializer
+
+@op
+class Block:
+ """A basic block"""
+ mode = "mode_BB"
+ knownBlock = True
+ block = "NULL"
+ pinned = "yes"
+ arity = "variable"
+ input_name = "cfgpred"
+ flags = []
+ attr_struct = "block_attr"
+ attrs = [
+ dict(
+ name = "entity",
+ type = "ir_entity*",
+ comment = "entity representing this block",
+ init = "NULL",
+ ),
+ ]
+ customSerializer = True