+ ]
+ flags = [ "fragile", "uses_memory" ]
+ pinned = "exception"
+ throws_init = "false"
+ pinned_init = "op_pin_state_pinned"
+ attr_struct = "alloc_attr"
+
+class Anchor(Op):
+ """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
+
+class And(Binop):
+ """returns the result of a bitwise and operation of its operands"""
+ flags = [ "commutative" ]
+
+class ASM(Op):
+ """executes assembler fragments of the target machine"""
+ mode = "mode_T"
+ arity = "variable"
+ flags = [ "keep", "uses_memory" ]
+ pinned = "memory"
+ pinned_init = "op_pin_state_pinned"
+ attr_struct = "asm_attr"
+ attrs_name = "assem"
+ customSerializer = True
+ 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
+
+class Bad(Op):
+ """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 themselfes. 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;
+ '''
+
+class Deleted(Op):
+ """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
+
+class Block(Op):
+ """A basic block"""
+ mode = "mode_BB"
+ knownBlock = True
+ block = "NULL"
+ pinned = "yes"
+ arity = "variable"
+ flags = [ "labeled" ]
+ attr_struct = "block_attr"
+ attrs = [
+ dict(
+ name = "entity",
+ type = "ir_entity*",
+ comment = "entity representing this block",
+ init = "NULL",
+ ),
+ ]
+ customSerializer = True