# This is the specification for the IR nodes
# Code is generated by scripts/gen_ir.pl
#
# $Id$

$NONE            = "#_#_#_#_#_NONE_#_#_#_#_#";
$MANUALFROMPARAM = "#_#_#_#_#_MANUALFROMPARAM_#_#_#_#_#";

# The IR node description is done as a perl hash with the following structure:
#
# %nodes = (
#
# <opname> => {
#  op          => use given node type instead of opname
#                 or 0 is this is an abstract node type (default: none)
#                 when present, no ir_op will be created
#  is_a        => name of another IR node description from which all data
#                 except "op" is inherited (default: none),
#  mode        => the mode of the op (default: parameter),
#  op_flags    => "N|L|C|X|I|F|Y|H|c|K|S|M|NB|NI" (default: "N"),
#  state       => "floats|pinned|mem_pinned|exc_pinned" (default: "floats"),
#  arity       => "dynamic|variable"
#                 dynamic allows to add inputs later,
#                 variable means, that the ins are given at construction time
#                 (default: automatically from args)
#  block       => the block for the node (default: parameter)
#  ins         => [ "in1", "in2", ... ] list of node inputs (default: none)
#  attrs_name  => name of the attribute structure
#                 (default if attrs exists: lcfirst(opname)),
#  attrs_type  => type of the attribute structure (default: auto generated),
#  attrs       => ordered list of attributes which will default to parameters
#                 after the ins and the mode parameters
#                 [
#                    {
#                       type  => the C type of the attribute or "bit",
#                       name  => the name of the attribute,
#                       init  => an initializer instead of a parameter
#                                or $MANUALFROMPARAM to disable automatic
#                                initialization but still using a parameter
#                                or $NONE to disable initialization completely
#                                by also not using a parameter
#                                (default: parameter),
#                       initname => name to access attribute
#                                when present, attribute will not be added
#                                to the according attribute struct
#                                (default: ".".name)
#                       comment => documentation for the attribute
#                    }, ...
#                 ] (default: none),
#  init        => additional initialization code to be emitted after the
#                 attribute initialization (default: none)
#  optimize    => whether optimize_node should be called (0|1, default: 1),
#  d_pre       => code to be inserted at the begining of the new_d_* function
#                 (may include declarations and statements, default: none),
#  d_post      => code to be inserted into the new_d_* function after the call
#                 to the new_rd_* function whose result is stored in the
#                 local variable res (default: none)
# },
#
# <more nodes>
#
# ); # close the %nodes initializer
#

# op_flags: flags for the operation corresponding to the firm irop_flags:
#	N   irop_flag_none
#	L   irop_flag_labeled
#	C   irop_flag_commutative
#	X   irop_flag_cfopcode
#	I   irop_flag_ip_cfopcode
#	F   irop_flag_fragile
#	Y   irop_flag_forking
#	H   irop_flag_highlevel
#	c   irop_flag_constlike
#	K   irop_flag_keep
#	S   irop_flag_start_block
#	M   irop_flag_uses_memory
#	NB  irop_flag_dump_noblock
#	NI  irop_flag_dump_noinput
#

%nodes = (

Start => {
	mode        => "mode_T",
	op_flags    => "X",
	state       => "pinned"
},

End => {
	mode        => "mode_X",
	op_flags    => "X",
	state       => "pinned",
	arity       => "dynamic"
},

Block => {
	mode        => "mode_BB",
	op_flags    => "L",
	state       => "pinned",
	arity       => "variable",
	block       => "NULL",
	attrs       => [
		{
			type => "ir_graph *",
			name => "irg",
			init => "irg",
			comment => "The graph this block belongs to."
		},
		{
			type => "ir_visited_t",
			name => "block_visited",
			init => $NONE,
			comment => "For the walker that walks over all blocks."
		},
		{
			type => "bit",
			name => "is_matured",
			init => $NONE,
			comment => "If set, all in-nodes of the block are fixed."
		},
		{
			type => "bit",
			name => "is_dead",
			init => "0",
			comment => "If set, the block is dead (and could be replace by a Bad."
		},
		{
			type => "bit",
			name => "is_mb_head",
			init => "1",
			comment => "Set if this block is a macroblock head."
		},
		{
			type => "bit",
			name => "has_label",
			init => "0",
			comment => "Set if this block has a label assigned."
		},
		{
			type => "bit",
			name => "marked",
			init => $NONE,         # TODO: This is uninitialized!!
			comment => "Can be set/unset to temporary mark a block."
		},
		{
			type => "ir_node **",
			name => "graph_arr",
			init => $NONE,         # TODO: This is uninitialized!!
			comment => "An array to store all parameters."
		},
		{
			type => "ir_dom_info",
			name => "dom",
			init => $NONE,        # TODO: This is uninitialized!!
			comment => "Datastructure that holds information about dominators.
	                                 @@@ \@todo
	                                 Eventually overlay with graph_arr as only valid
	                                 in different phases.  Eventually inline the whole
	                                 datastructure."
		},
		{
			type => "ir_dom_info",
			name => "pdom",
			init => $NONE,        # TODO: This is uninitialized!!
			comment => "Datastructure that holds information about post-dominators."
		},
		{
			type => "ir_node **",
			name => "in_cg",
			init => "NULL",
			comment => "array with predecessors in
	                             * interprocedural_view, if they differ
	                             * from intraprocedural predecessors"
		},
		{
			type => "unsigned *",
			name => "backedge",
			init => "new_backedge_arr(irg->obst, arity)",
			comment => "Raw Bitfield n set to true if pred n is backedge."
		},
		{
			type => "unsigned *",
			name => "cg_backedge",
			init => "NULL",
			comment => "Raw Bitfield n set to true if pred n is interprocedural backedge."
		},
		{
			type => "ir_extblk *",
			name => "extblk",
			init => "NULL",
			comment => "The extended basic block this block belongs to."
		},
		{
			type => "ir_region *",
			name => "region",
			init => $NONE,        # TODO: This is uninitialized!!
			comment => "The immediate structural region this block belongs to."
		},
		{
			type => "unsigned",
			name => "mb_depth",
			init => "0",
			comment => "The macroblock depth: A distance from the macroblock header."
		},
		{
			type => "ir_label_t",
			name => "label",
			init => "0",
			comment => "The block label if assigned."
		},
		{
			type => "ir_node *",
			name => "phis",
			init => $NONE,        # TODO: This is uninitialized!!
			comment => "The list of Phi nodes in this block."
		},
		{
			type => "struct list_head",
			name => "succ_head",
			init => $NONE,        # TODO: This is uninitialized!!
			comment => "A list head for all successor edges of a block."
		},
	],
	init        => "\t/* macroblock header */\n".
				   "\tres->in[0] = res;\n\n".
				   "\tset_Block_matured(res, 1);\n".
				   "\tset_Block_block_visited(res, 0);\n",
	optimize    => 0,
	d_pre       => "\tint i;\n\tint has_unknown = 0;\n",
	d_post      => "\t/* Create and initialize array for Phi-node construction. */\n".
	               "\tif (get_irg_phase_state(current_ir_graph) == phase_building) {\n".
		           "\t\tres->attr.block.graph_arr = NEW_ARR_D(ir_node *, current_ir_graph->obst,\n".
		           "\t\t                                      current_ir_graph->n_loc);\n".
		           "\t\tmemset(res->attr.block.graph_arr, 0, sizeof(ir_node *) * current_ir_graph->n_loc);\n".
		           "\t}\n\n".
		           "\tfor (i = arity-1; i >= 0; i--)\n".
		           "\t\tif (is_Unknown(in[i])) {\n".
		           "\t\thas_unknown = 1;\n".
		           "\t\tbreak;\n".
		           "\t}\n".
		           "\tif (!has_unknown) res = optimize_node(res);\n".
		           "\tcurrent_ir_graph->current_block = res;\n".
		           "\tIRN_VRFY_IRG(res, current_ir_graph);\n"
},

Const_type => {
	op          => "Const",
	op_flags    => "c|S",
	mode        => "get_tarval_mode(tv)",
	block       => "get_irg_start_block(irg)",
	attrs_name  => "con",
	attrs       => [
		{
			type => "tarval *",
			name => "tv"
		},
		{
			type => "ir_type *",
			name => "tp",
			init => $MANUALFROMPARAM
		}
	],
	init        => "set_Const_type(res, tp);\n"
},

Id => {
	ins         => [ "val" ]
},

Proj => {
	ins         => [ "arg" ],
	attrs_type  => "long",
	attrs       => [
		{
			type => "long",
			name => "proj",
			initname => "",
		}
	],
	init        => "assert(get_Proj_pred(res));\n".
	               "\tassert(get_nodes_block(get_Proj_pred(res)));\n"
},

# Conv => {
# 	ins        => [ "op" ],
# 	attrs      => [
# 		{
# 			type => "char",
# 			name => "strict",
# 			#init => "0",
# 			comment => "If set, this is a strict Conv that cannot be removed."
# 		}
# 	]
# },

Cast => {
	op_flags   => "H",
	mode       => "get_irn_mode(op)",
	ins        => [ "op" ],
	attrs      => [
		{
			type => "ir_type *",
			name => "totype",
			comment => "Type of the casted node."
		}
	],
	init       => "assert(is_atomic_type(totype));\n"
},

Jmp => {
	op_flags    => "X",
	state       => "pinned",
	mode        => "mode_X"
},

IJmp => {
	op_flags    => "X",
	state       => "pinned",
	mode        => "mode_X",
	ins         => [ "target" ]
},

Cond => {
	op_flags    => "X|Y",
	state       => "pinned",
	mode        => "mode_T",
	ins         => [ "selector" ],
	attrs       => [
		{
			type => "cond_kind",
			name => "kind",
			init => "dense",
			comment => "Flavor of Cond."
		},
		{
			type => "long",
			name => "default_proj",
			init => "0",
			comment => "Only for non-binary Conds: biggest Proj number, i.e. the one used for default."
		},
		{
			type => "cond_jmp_predicate",
			name => "jmp_pred",
			init => "COND_JMP_PRED_NONE",
			comment => "Only for binary Conds: The jump predication."
		},

	]
},

Tuple => {
	op_flags    => "L",
	mode        => "mode_T",
	arity       => "variable"
},

BinOp => {
	op          => 0,
	ins         => [ "left", "right" ]
},

Cmp => {
	is_a        => "BinOp",
	mode        => "mode_T"
},

Add => {
	is_a        => "BinOp",
	op_flags    => "C",
},

Div => {
	mode        => "mode_T",
	op_flags    => "F|M",
	state       => "exc_pinned",
	ins         => [ "mem", "left", "right" ],
	attrs_name  => "divmod",
	attrs       => [
		{
			type => "except_attr",
			name => "exc",
			init => $NONE
		},
		{
			type => "ir_mode *",
			name => "res_mode"
		},
		{
			type => "op_pin_state",
			name => "state",
			initname => ".exc.pin_state"
		},
		{
			type => "char",
			name => "no_remainder",
			init => "0"
		}
	],
	d_post      => "\t#if PRECISE_EXC_CONTEXT\n".
	               "\tfirm_alloc_frag_arr(res, op_Div, &res->attr.except.frag_arr);\n".
	               "\t#endif\n"
}

);
