- The pns of X_regular and X_except are annotated in the opcode now.
- The memory input is annotated in the opcode now
- only nodes with X_regular, X_except are marked fragile
ir_bk_inner_trampoline, /**< address of a trampoline for GCC inner functions */
} ir_builtin_kind;
-/**
- * Some projection numbers must be always equal to support automatic phi construction
- */
-enum pn_generic {
- pn_Generic_M = 0, /**< The memory result. */
- pn_Generic_X_regular = 1, /**< Execution result if no exception occurred. */
- pn_Generic_X_except = 2, /**< The control flow result branching to the exception handler */
- pn_Generic_other = 3 /**< First free projection number */
-};
-
/**
* Possible return values of value_classify().
*/
FIRM_API ir_node *get_binop_right(const ir_node *node);
FIRM_API void set_binop_right(ir_node *node, ir_node *right);
+/**
+ * Test wether a node is the X_except Proj of a fragile operation
+ */
+FIRM_API int is_x_except_Proj(const ir_node *node);
+
+/**
+ * Test wether a node is the X_regular Proj of a fragile operation
+ */
+FIRM_API int is_x_regular_Proj(const ir_node *node);
+
/** returns the name of an ir_relation */
FIRM_API const char *get_relation_string(ir_relation relation);
irop_flag_labeled = 1U << 0, /**< If set, output edge labels on in-edges in vcg graph. */
irop_flag_commutative = 1U << 1, /**< This operation is commutative. */
irop_flag_cfopcode = 1U << 2, /**< This operation is a control flow operation. */
- irop_flag_fragile = 1U << 3, /**< Set if the operation can change the control flow because
- of an exception. */
+ irop_flag_fragile = 1U << 3, /**< Set if the operation can change the
+ control flow because of an exception.
+ */
irop_flag_forking = 1U << 4, /**< Forking control flow at this operation. */
irop_flag_highlevel = 1U << 5, /**< This operation is a pure high-level one and can be
skipped in low-level optimizations. */
unsigned flags, op_arity opar, int op_index,
size_t attr_size, const ir_op_ops *ops);
+/**
+ * Set proj-number for X_regular and X_except projs of fragile nodes.
+ * Note: should only be used immediately after new_ir_op
+ */
+FIRM_API void ir_op_set_fragile_indices(ir_op *op, int fragile_mem_index,
+ int pn_x_regular, int pn_x_except);
+
/** Returns the ir_op_ops of an ir_op. */
FIRM_API const ir_op_ops *get_op_ops(const ir_op *op);
cfop = get_Block_cfgpred(blk, i);
if (is_Proj(cfop)) {
ir_node *op = skip_Proj(cfop);
- if (is_fragile_op(op) && get_Proj_proj(cfop) == pn_Generic_X_except) {
+ if (is_x_except_Proj(cfop)) {
/*
* Skip the Proj for the exception flow only, leave the
* not exception flow Proj's intact.
# Load / Store
Load => {
- op_flags => [ "labeled", "fragile" ],
+ op_flags => [ "labeled" ],
irn_flags => [ "rematerializable" ],
state => "exc_pinned",
reg_req => { in => [ "gp", "none" ], out => [ "gp" ] },
},
Store => {
- op_flags => [ "labeled", "fragile" ],
+ op_flags => [ "labeled" ],
irn_flags => [ "rematerializable" ],
state => "exc_pinned",
reg_req => { in => [ "gp", "gp", "none" ] },
# Load / Store
fLoad => {
- op_flags => [ "labeled", "fragile" ],
+ op_flags => [ "labeled" ],
irn_flags => [ "rematerializable" ],
state => "exc_pinned",
reg_req => { in => [ "gp", "none" ], out => [ "fp" ] },
},
fStore => {
- op_flags => [ "labeled", "fragile" ],
+ op_flags => [ "labeled" ],
irn_flags => [ "rematerializable" ],
state => "exc_pinned",
reg_req => { in => [ "gp", "fp", "none" ] },
mode => "mode_T",
},
Load => {
- op_flags => [ "labeled", "fragile" ],
+ op_flags => [ "labeled" ],
state => "exc_pinned",
reg_req => { in => [ "gp", "none" ],
out => [ "gp", "none" ] },
mode => $mode_gp,
},
Store => {
- op_flags => [ "labeled", "fragile" ],
+ op_flags => [ "labeled" ],
state => "exc_pinned",
reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
ins => [ "ptr", "val", "mem" ],
},
CopyB => {
- op_flags => [ "fragile" ],
state => "pinned",
attr => "unsigned size",
attr_type => "arm_CopyB_attr_t",
},
Ldr => {
- op_flags => [ "labeled", "fragile" ],
+ op_flags => [ "labeled" ],
state => "exc_pinned",
ins => [ "ptr", "mem" ],
outs => [ "res", "M" ],
},
Str => {
- op_flags => [ "labeled", "fragile" ],
+ op_flags => [ "labeled" ],
state => "exc_pinned",
ins => [ "ptr", "val", "mem" ],
outs => [ "M" ],
},
StoreStackM4Inc => {
- op_flags => [ "labeled", "fragile" ],
+ op_flags => [ "labeled" ],
irn_flags => [ "rematerializable" ],
state => "exc_pinned",
reg_req => { in => [ "sp", "gp", "gp", "gp", "gp", "none" ], out => [ "sp:I|S", "none" ] },
},
LoadStackM3Epilogue => {
- op_flags => [ "labeled", "fragile" ],
+ op_flags => [ "labeled" ],
irn_flags => [ "rematerializable" ],
state => "exc_pinned",
reg_req => { in => [ "sp", "none" ], out => [ "r11:I", "sp:I|S", "pc:I", "none" ] },
},
Ldf => {
- op_flags => [ "labeled", "fragile" ],
+ op_flags => [ "labeled" ],
state => "exc_pinned",
ins => [ "ptr", "mem" ],
outs => [ "res", "M" ],
},
Stf => {
- op_flags => [ "labeled", "fragile" ],
+ op_flags => [ "labeled" ],
state => "exc_pinned",
ins => [ "ptr", "val", "mem" ],
outs => [ "M" ],
op_flags => [ "fragile", "labeled" ],
state => "exc_pinned",
reg_req => { in => [ "gp", "gp", "none", "gp", "eax", "edx" ],
- out => [ "eax", "flags", "none", "edx", "none" ] },
+ out => [ "eax", "flags", "none", "edx", "none", "none" ] },
ins => [ "base", "index", "mem", "divisor", "dividend_low", "dividend_high" ],
- outs => [ "div_res", "flags", "M", "mod_res", "X_exc" ],
+ outs => [ "div_res", "flags", "M", "mod_res", "X_regular", "X_except" ],
am => "source,unary",
emit => ". idiv%M %unop3",
latency => 25,
op_flags => [ "fragile", "labeled" ],
state => "exc_pinned",
reg_req => { in => [ "gp", "gp", "none", "gp", "eax", "edx" ],
- out => [ "eax", "flags", "none", "edx", "none" ] },
+ out => [ "eax", "flags", "none", "edx", "none", "none" ] },
ins => [ "base", "index", "mem", "divisor", "dividend_low", "dividend_high" ],
- outs => [ "div_res", "flags", "M", "mod_res", "X_exc" ],
+ outs => [ "div_res", "flags", "M", "mod_res", "X_regular", "X_except" ],
am => "source,unary",
emit => ". div%M %unop3",
latency => 25,
},
FldCW => {
- op_flags => [ "fragile", "labeled" ],
+ op_flags => [ "labeled" ],
state => "pinned",
reg_req => { in => [ "gp", "gp", "none" ], out => [ "fpcw:I" ] },
ins => [ "base", "index", "mem" ],
},
FnstCW => {
- op_flags => [ "fragile", "labeled" ],
+ op_flags => [ "labeled" ],
state => "pinned",
reg_req => { in => [ "gp", "gp", "none", "fp_cw" ], out => [ "none" ] },
ins => [ "base", "index", "mem", "fpcw" ],
},
FnstCWNOP => {
- op_flags => [ "fragile", "labeled" ],
+ op_flags => [ "labeled" ],
state => "pinned",
reg_req => { in => [ "fp_cw" ], out => [ "none" ] },
ins => [ "fpcw" ],
op_flags => [ "fragile", "labeled" ],
state => "exc_pinned",
reg_req => { in => [ "gp", "gp", "none" ],
- out => [ "gp", "none", "none", "none" ] },
+ out => [ "gp", "none", "none", "none", "none" ] },
ins => [ "base", "index", "mem" ],
- outs => [ "res", "unused", "M", "X_exc" ],
+ outs => [ "res", "unused", "M", "X_regular", "X_except" ],
latency => 0,
emit => ". mov%EX%.l %AM, %D0",
units => [ "GP" ],
Store => {
op_flags => [ "fragile", "labeled" ],
state => "exc_pinned",
- reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "none", "none" ] },
+ reg_req => { in => [ "gp", "gp", "none", "gp" ],
+ out => [ "none", "none", "none" ] },
ins => [ "base", "index", "mem", "val" ],
- outs => [ "M", "X_exc" ],
+ outs => [ "M", "X_regular", "X_except" ],
emit => '. mov%M %SI3, %AM',
latency => 2,
units => [ "GP" ],
Store8Bit => {
op_flags => [ "fragile", "labeled" ],
state => "exc_pinned",
- reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => ["none", "none" ] },
+ reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ],
+ out => ["none", "none", "none" ] },
ins => [ "base", "index", "mem", "val" ],
- outs => [ "M", "X_exc" ],
+ outs => [ "M", "X_regular", "X_except" ],
emit => '. mov%M %SB3, %AM',
latency => 2,
units => [ "GP" ],
# Intel style prefetching
#
Prefetch0 => {
- op_flags => [ "fragile", "labeled" ],
+ op_flags => [ "labeled" ],
state => "exc_pinned",
reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
ins => [ "base", "index", "mem" ],
},
Prefetch1 => {
- op_flags => [ "fragile", "labeled" ],
+ op_flags => [ "labeled" ],
state => "exc_pinned",
reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
ins => [ "base", "index", "mem" ],
},
Prefetch2 => {
- op_flags => [ "fragile", "labeled" ],
+ op_flags => [ "labeled" ],
state => "exc_pinned",
reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
ins => [ "base", "index", "mem" ],
},
PrefetchNTA => {
- op_flags => [ "fragile", "labeled" ],
+ op_flags => [ "labeled" ],
state => "exc_pinned",
reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
ins => [ "base", "index", "mem" ],
# 3DNow! prefetch instructions
#
Prefetch => {
- op_flags => [ "fragile", "labeled" ],
+ op_flags => [ "labeled" ],
state => "exc_pinned",
reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
ins => [ "base", "index", "mem" ],
},
PrefetchW => {
- op_flags => [ "fragile", "labeled" ],
+ op_flags => [ "labeled" ],
state => "exc_pinned",
reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
ins => [ "base", "index", "mem" ],
op_flags => [ "fragile", "labeled" ],
state => "exc_pinned",
reg_req => { in => [ "gp", "gp", "none" ],
- out => [ "xmm", "none", "none", "none" ] },
+ out => [ "xmm", "none", "none", "none", "none" ] },
ins => [ "base", "index", "mem" ],
- outs => [ "res", "unused", "M", "X_exc" ],
+ outs => [ "res", "unused", "M", "X_regular", "X_except" ],
emit => '. mov%XXM %AM, %D0',
attr => "ir_mode *load_mode",
init_attr => "attr->ls_mode = load_mode;",
xStore => {
op_flags => [ "fragile", "labeled" ],
state => "exc_pinned",
- reg_req => { in => [ "gp", "gp", "none", "xmm" ], out => [ "none", "none" ] },
+ reg_req => { in => [ "gp", "gp", "none", "xmm" ],
+ out => [ "none", "none", "none" ] },
ins => [ "base", "index", "mem", "val" ],
- outs => [ "M", "X_exc" ],
+ outs => [ "M", "X_regular", "X_except" ],
emit => '. mov%XXM %S3, %AM',
latency => 0,
units => [ "SSE" ],
xStoreSimple => {
op_flags => [ "fragile", "labeled" ],
state => "exc_pinned",
- reg_req => { in => [ "gp", "gp", "none", "xmm" ], out => [ "none" ] },
+ reg_req => { in => [ "gp", "gp", "none", "xmm" ],
+ out => [ "none", "none", "none" ] },
ins => [ "base", "index", "mem", "val" ],
- outs => [ "M" ],
+ outs => [ "M", "X_regular", "X_except" ],
emit => '. mov%XXM %S3, %AM',
latency => 0,
units => [ "SSE" ],
},
CvtSI2SS => {
- op_flags => [ "fragile", "labeled" ],
+ op_flags => [ "labeled" ],
state => "exc_pinned",
reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm" ] },
ins => [ "base", "index", "mem", "val" ],
},
CvtSI2SD => {
- op_flags => [ "fragile", "labeled" ],
+ op_flags => [ "labeled" ],
state => "exc_pinned",
reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm" ] },
ins => [ "base", "index", "mem", "val" ],
l_LLtoFloat => {
- op_flags => [ "fragile", "labeled" ],
+ op_flags => [ "labeled" ],
cmp_attr => "return 1;",
ins => [ "val_high", "val_low" ],
reg_req => { in => [ "none", "none" ], out => [ "none" ] }
},
l_FloattoLL => {
- op_flags => [ "fragile", "labeled" ],
+ op_flags => [ "labeled" ],
cmp_attr => "return 1;",
ins => [ "val" ],
outs => [ "res_high", "res_low" ],
CopyB => {
op_flags => [ "fragile" ],
state => "pinned",
- reg_req => { in => [ "edi", "esi", "ecx", "none" ], out => [ "edi", "esi", "ecx", "none" ] },
- outs => [ "DST", "SRC", "CNT", "M" ],
+ reg_req => { in => [ "edi", "esi", "ecx", "none" ],
+ out => [ "edi", "esi", "ecx", "none", "none", "none" ] },
+ ins => [ "dest", "source", "count", "mem" ],
+ outs => [ "dest", "source", "count", "M", "X_regular", "X_except" ],
attr_type => "ia32_copyb_attr_t",
attr => "unsigned size",
units => [ "GP" ],
- latency => 3,
+ latency => 3,
# we don't care about this flag, so no need to mark this node
# modified_flags => [ "DF" ]
},
CopyB_i => {
op_flags => [ "fragile" ],
state => "pinned",
- reg_req => { in => [ "edi", "esi", "none" ], out => [ "edi", "esi", "none" ] },
- outs => [ "DST", "SRC", "M" ],
+ reg_req => { in => [ "edi", "esi", "none" ],
+ out => [ "edi", "esi", "none", "none", "none" ] },
+ ins => [ "dest", "source", "mem" ],
+ outs => [ "dest", "source", "M", "X_regular", "X_except" ],
attr_type => "ia32_copyb_attr_t",
attr => "unsigned size",
units => [ "GP" ],
- latency => 3,
+ latency => 3,
# we don't care about this flag, so no need to mark this node
# modified_flags => [ "DF" ]
},
op_flags => [ "fragile", "labeled" ],
state => "exc_pinned",
reg_req => { in => [ "gp", "gp", "none" ],
- out => [ "vfp", "none", "none", "none" ] },
+ out => [ "vfp", "none", "none", "none", "none" ] },
ins => [ "base", "index", "mem" ],
- outs => [ "res", "unused", "M", "X_exc" ],
+ outs => [ "res", "unused", "M", "X_regular", "X_except" ],
attr => "ir_mode *load_mode",
init_attr => "attr->attr.ls_mode = load_mode;",
latency => 2,
op_flags => [ "fragile", "labeled" ],
state => "exc_pinned",
reg_req => { in => [ "gp", "gp", "none", "vfp" ],
- out => [ "none", "none" ] },
+ out => [ "none", "none", "none" ] },
ins => [ "base", "index", "mem", "val" ],
- outs => [ "M", "X_exc" ],
+ outs => [ "M", "X_regular", "X_except" ],
attr => "ir_mode *store_mode",
init_attr => "attr->attr.ls_mode = store_mode;",
latency => 2,
fld => {
irn_flags => [ "rematerializable" ],
- op_flags => [ "fragile", "labeled" ],
+ op_flags => [ "labeled" ],
state => "exc_pinned",
emit => '. fld%XM %AM',
attr_type => "ia32_x87_attr_t",
fst => {
irn_flags => [ "rematerializable" ],
- op_flags => [ "fragile", "labeled" ],
+ op_flags => [ "labeled" ],
state => "exc_pinned",
emit => '. fst%XM %AM',
mode => "mode_M",
fstp => {
irn_flags => [ "rematerializable" ],
- op_flags => [ "fragile", "labeled" ],
+ op_flags => [ "labeled" ],
state => "exc_pinned",
emit => '. fstp%XM %AM',
mode => "mode_M",
xxLoad => {
op_flags => [ "fragile", "labeled" ],
state => "exc_pinned",
- reg_req => { in => [ "gp", "gp", "none" ], out => [ "xmm", "none" ] },
+ reg_req => { in => [ "gp", "gp", "none" ],
+ out => [ "xmm", "none", "none", "none" ] },
emit => '. movdqu %D0, %AM',
- outs => [ "res", "M" ],
+ ins => [ "base", "index", "mem" ],
+ outs => [ "res", "M", "X_regular", "X_except" ],
units => [ "SSE" ],
latency => 1,
},
xxStore => {
op_flags => [ "fragile", "labeled" ],
state => "exc_pinned",
- reg_req => { in => [ "gp", "gp", "none", "xmm" ] },
+ reg_req => { in => [ "gp", "gp", "none", "xmm" ],
+ out => [ "none", "none", "none" ] },
ins => [ "base", "index", "mem", "val" ],
+ outs => [ "M", "X_regular", "X_except" ],
emit => '. movdqu %binop',
units => [ "SSE" ],
- latency => 1,
+ latency => 1,
mode => "mode_M",
},
static ir_node *gen_Proj_Load(ir_node *node)
{
ir_node *new_pred;
- ir_node *block = be_transform_node(get_nodes_block(node));
- ir_node *pred = get_Proj_pred(node);
- dbg_info *dbgi = get_irn_dbg_info(node);
- long proj = get_Proj_proj(node);
+ ir_node *pred = get_Proj_pred(node);
+ dbg_info *dbgi = get_irn_dbg_info(node);
+ long proj = get_Proj_proj(node);
/* loads might be part of source address mode matches, so we don't
* transform the ProjMs yet (with the exception of loads whose result is
/* renumber the proj */
new_pred = be_transform_node(pred);
if (is_ia32_Load(new_pred)) {
- switch (proj) {
+ switch ((pn_Load)proj) {
case pn_Load_res:
return new_rd_Proj(dbgi, new_pred, mode_Iu, pn_ia32_Load_res);
case pn_Load_M:
return new_rd_Proj(dbgi, new_pred, mode_M, pn_ia32_Load_M);
- case pn_Load_X_regular:
- return new_rd_Jmp(dbgi, block);
case pn_Load_X_except:
/* This Load might raise an exception. Mark it. */
set_ia32_exc_label(new_pred, 1);
- return new_rd_Proj(dbgi, new_pred, mode_X, pn_ia32_Load_X_exc);
- default:
+ return new_rd_Proj(dbgi, new_pred, mode_X, pn_ia32_Load_X_except);
+ case pn_Load_X_regular:
+ return new_rd_Proj(dbgi, new_pred, mode_X, pn_ia32_Load_X_regular);
+ case pn_Load_max:
break;
}
} else if (is_ia32_Conv_I2I(new_pred) ||
return new_rd_Proj(dbgi, new_pred, mode_M, pn_ia32_mem);
}
} else if (is_ia32_xLoad(new_pred)) {
- switch (proj) {
+ switch ((pn_Load)proj) {
case pn_Load_res:
return new_rd_Proj(dbgi, new_pred, mode_xmm, pn_ia32_xLoad_res);
case pn_Load_M:
return new_rd_Proj(dbgi, new_pred, mode_M, pn_ia32_xLoad_M);
- case pn_Load_X_regular:
- return new_rd_Jmp(dbgi, block);
case pn_Load_X_except:
/* This Load might raise an exception. Mark it. */
set_ia32_exc_label(new_pred, 1);
- return new_rd_Proj(dbgi, new_pred, mode_X, pn_ia32_xLoad_X_exc);
- default:
+ return new_rd_Proj(dbgi, new_pred, mode_X, pn_ia32_xLoad_X_except);
+ case pn_Load_X_regular:
+ return new_rd_Proj(dbgi, new_pred, mode_X, pn_ia32_xLoad_X_regular);
+ case pn_Load_max:
break;
}
} else if (is_ia32_vfld(new_pred)) {
- switch (proj) {
+ switch ((pn_Load)proj) {
case pn_Load_res:
return new_rd_Proj(dbgi, new_pred, mode_vfp, pn_ia32_vfld_res);
case pn_Load_M:
return new_rd_Proj(dbgi, new_pred, mode_M, pn_ia32_vfld_M);
- case pn_Load_X_regular:
- return new_rd_Jmp(dbgi, block);
case pn_Load_X_except:
/* This Load might raise an exception. Mark it. */
set_ia32_exc_label(new_pred, 1);
- return new_rd_Proj(dbgi, new_pred, mode_X, pn_ia32_vfld_X_exc);
- default:
+ return new_rd_Proj(dbgi, new_pred, mode_X, pn_ia32_vfld_X_except);
+ case pn_Load_X_regular:
+ return new_rd_Proj(dbgi, new_pred, mode_X, pn_ia32_vfld_X_regular);
+ case pn_Load_max:
break;
}
} else {
*/
static ir_node *gen_Proj_Div(ir_node *node)
{
- ir_node *block = be_transform_node(get_nodes_block(node));
ir_node *pred = get_Proj_pred(node);
ir_node *new_pred = be_transform_node(pred);
dbg_info *dbgi = get_irn_dbg_info(node);
- long proj = get_Proj_proj(node);
+ long proj = get_Proj_proj(node);
assert((long)pn_ia32_Div_M == (long)pn_ia32_IDiv_M);
assert((long)pn_ia32_Div_div_res == (long)pn_ia32_IDiv_div_res);
- switch (proj) {
+ switch ((pn_Div)proj) {
case pn_Div_M:
if (is_ia32_Div(new_pred) || is_ia32_IDiv(new_pred)) {
return new_rd_Proj(dbgi, new_pred, mode_M, pn_ia32_Div_M);
} else {
panic("Div transformed to unexpected thing %+F", new_pred);
}
- case pn_Div_X_regular:
- return new_rd_Jmp(dbgi, block);
case pn_Div_X_except:
set_ia32_exc_label(new_pred, 1);
- return new_rd_Proj(dbgi, new_pred, mode_X, pn_ia32_Div_X_exc);
- default:
+ return new_rd_Proj(dbgi, new_pred, mode_X, pn_ia32_Div_X_except);
+ case pn_Div_X_regular:
+ return new_rd_Proj(dbgi, new_pred, mode_X, pn_ia32_Div_X_regular);
+ case pn_Div_max:
break;
}
assert((long)pn_ia32_Div_M == (long)pn_ia32_IDiv_M);
assert((long)pn_ia32_Div_mod_res == (long)pn_ia32_IDiv_mod_res);
- switch (proj) {
+ switch ((pn_Mod)proj) {
case pn_Mod_M:
return new_rd_Proj(dbgi, new_pred, mode_M, pn_ia32_Div_M);
case pn_Mod_res:
return new_rd_Proj(dbgi, new_pred, mode_Iu, pn_ia32_Div_mod_res);
case pn_Mod_X_except:
set_ia32_exc_label(new_pred, 1);
- return new_rd_Proj(dbgi, new_pred, mode_X, pn_ia32_Div_X_exc);
- default:
+ return new_rd_Proj(dbgi, new_pred, mode_X, pn_ia32_Div_X_except);
+ case pn_Mod_X_regular:
+ return new_rd_Proj(dbgi, new_pred, mode_X, pn_ia32_Div_X_regular);
+ case pn_Mod_max:
break;
}
panic("No idea how to transform proj->Mod");
"start_block", "uses_memory", "dump_noblock", "dump_noinput",
"machine", "machine_op", "cse_neutral"
);
+ my $is_fragile = 0;
foreach my $flag (@{$n{"op_flags"}}) {
if (not defined($known_flags{$flag})) {
print STDERR "WARNING: Flag '$flag' in opcode $op is unknown\n";
}
+ if ($flag eq "fragile") {
+ $is_fragile = 1;
+ }
}
my @mapped = map { "irop_flag_$_" } @{$n{"op_flags"}};
my $op_flags = join('|', @mapped);
$temp = "\top_$op = new_ir_op(cur_opcode + iro_$op, \"$op\", op_pin_state_".$n{"state"}.", $op_flags";
$temp .= "|irop_flag_machine, ".translate_arity($arity).", 0, ${attr_size}, &ops);\n";
push(@obst_new_irop, $temp);
+ if ($is_fragile) {
+ push(@obst_new_irop, "\tir_op_set_fragile_indices(op_${op}, n_${op}_mem, pn_${op}_X_regular, pn_${op}_X_except);\n");
+ }
push(@obst_new_irop, "\tset_op_tag(op_$op, $arch\_op_tag);\n");
if(defined($default_op_attr_type)) {
push(@obst_new_irop, "\tattr = &attrs[iro_$op];\n");
# Load / Store
Ld => {
- op_flags => [ "labeled", "fragile" ],
+ op_flags => [ "labeled" ],
state => "exc_pinned",
constructors => {
imm => {
},
St => {
- op_flags => [ "labeled", "fragile" ],
+ op_flags => [ "labeled" ],
mode => "mode_M",
state => "exc_pinned",
constructors => {
},
Ldf => {
- op_flags => [ "labeled", "fragile" ],
+ op_flags => [ "labeled" ],
state => "exc_pinned",
constructors => {
s => {
},
Stf => {
- op_flags => [ "labeled", "fragile" ],
+ op_flags => [ "labeled" ],
state => "exc_pinned",
constructors => {
s => {
return _is_arg_Proj(node);
}
+int is_x_except_Proj(const ir_node *node)
+{
+ ir_node *pred;
+ if (!is_Proj(node))
+ return false;
+ pred = get_Proj_pred(node);
+ if (!is_fragile_op(pred))
+ return false;
+ return get_Proj_proj(node) == pred->op->pn_x_except;
+}
+
+int is_x_regular_Proj(const ir_node *node)
+{
+ ir_node *pred;
+ if (!is_Proj(node))
+ return false;
+ pred = get_Proj_pred(node);
+ if (!is_fragile_op(pred))
+ return false;
+ return get_Proj_proj(node) == pred->op->pn_x_except;
+}
+
ir_node **get_Tuple_preds_arr(ir_node *node)
{
assert(is_Tuple(node));
ir_node *get_fragile_op_mem(ir_node *node)
{
assert(node && is_fragile_op(node));
-
- switch (get_irn_opcode(node)) {
- case iro_Call :
- case iro_Div :
- case iro_Mod :
- case iro_Load :
- case iro_Store :
- case iro_Alloc :
- case iro_Bound :
- case iro_CopyB :
- return get_irn_n(node, pn_Generic_M);
- case iro_Bad :
- case iro_Unknown:
- return node;
- default:
- panic("should not be reached");
- }
+ return get_irn_n(node, node->op->fragile_mem_index);
}
/* Returns true if the operation is a forking control flow operation. */
free(code);
} /* free_ir_op */
+void ir_op_set_fragile_indices(ir_op *op, int fragile_mem_index,
+ int pn_x_regular, int pn_x_except)
+{
+ op->fragile_mem_index = fragile_mem_index;
+ op->pn_x_regular = pn_x_regular;
+ op->pn_x_except = pn_x_except;
+}
+
/* Returns the string for the opcode. */
const char *get_op_name (const ir_op *op)
{
/** The type of an ir_op. */
struct ir_op {
- unsigned code; /**< The unique opcode of the op. */
- ident *name; /**< The name of the op. */
- size_t attr_size; /**< Space needed in memory for private attributes. */
- op_pin_state pin_state; /**< How to deal with the node in CSE, PRE. */
- op_arity opar; /**< The arity of operator. */
- int op_index; /**< The index of the first data operand, 0 for most cases, 1 for Div etc. */
- unsigned flags; /**< Flags describing the behavior of the ir_op, a bitmasks of irop_flags. */
- unsigned tag; /**< Some custom TAG value the op's creator set to. */
- void *attr; /**< custom pointer where op's creator can attach attribute stuff to. */
-
- ir_op_ops ops; /**< The operations of the this op. */
+ unsigned code; /**< The unique opcode of the op. */
+ ident *name; /**< The name of the op. */
+ size_t attr_size; /**< Space needed in memory for private attributes
+ */
+ op_pin_state pin_state; /**< How to deal with the node in CSE, PRE. */
+ op_arity opar; /**< The arity of operator. */
+ int op_index; /**< The index of the first data operand, 0 for
+ most cases, 1 for Div etc. */
+ int fragile_mem_index; /**< index of memory input for fragile nodes */
+ int pn_x_regular; /**< for fragile ops the position of the
+ X_regular output */
+ int pn_x_except; /**< for fragile ops the position of the
+ X_except output */
+ unsigned flags; /**< Flags describing the behavior of the ir_op,
+ a bitmasks of irop_flags. */
+ unsigned tag; /**< Some custom TAG value the op's creator set */
+ void *attr; /**< custom pointer where op's creator can attach
+ attribute stuff to. */
+ ir_op_ops ops; /**< The operations of the this op. */
};
/**
cfop = get_irn_op(skip_Proj(pre));
if (is_op_fragile(cfop)) {
- if (cenv->ignore_exc_edges && get_Proj_proj(pre) == pn_Generic_X_except)
+ if (cenv->ignore_exc_edges && is_x_except_Proj(pre))
continue;
goto insert;
}
if (is_Proj(proj)) {
pred = get_Proj_pred(proj);
- is_exc = get_Proj_proj(proj) == pn_Generic_X_except;
+ is_exc = is_x_except_Proj(proj);
}
/* ignore Bad predecessors, they will be removed later */
*
* @param m the memop
*/
-static void update_DivOp_memop(memop_t *m)
+static void update_Div_memop(memop_t *m)
{
ir_node *div = m->node;
int i;
continue;
switch (get_Proj_proj(proj)) {
- case pn_Generic_X_except:
+ case pn_Div_X_except:
m->flags |= FLAG_EXCEPTION;
break;
- case pn_Generic_M:
+ case pn_Div_M:
m->mem = proj;
break;
}
}
-} /* update_DivOp_memop */
+}
+
+static void update_Mod_memop(memop_t *m)
+{
+ ir_node *div = m->node;
+ int i;
+
+ for (i = get_irn_n_outs(div) - 1; i >= 0; --i) {
+ ir_node *proj = get_irn_out(div, i);
+
+ /* beware of keep edges */
+ if (is_End(proj))
+ continue;
+
+ switch (get_Proj_proj(proj)) {
+ case pn_Mod_X_except:
+ m->flags |= FLAG_EXCEPTION;
+ break;
+ case pn_Mod_M:
+ m->mem = proj;
+ break;
+ }
+ }
+}
/**
* Update a memop for a Phi.
/* we can those to find the memory edge */
break;
case iro_Div:
+ update_Div_memop(op);
+ break;
case iro_Mod:
- update_DivOp_memop(op);
+ update_Mod_memop(op);
break;
case iro_Builtin:
{{node|attr_size}}
NULL
{% endfilter %});
+ {%- if "fragile" in node.flags: %}
+ ir_op_set_fragile_indices(op_{{node.name}}, n_{{node.name}}_mem, pn_{{node.name}}_X_regular, pn_{{node.name}}_X_except);
+ {%- endif -%}
{%- endfor %}
be_init_op();
("count", "number of objects to allocate" ),
]
outs = [
- ("M", "memory result", "pn_Generic_M"),
- ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
- ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
- ("res", "pointer to newly allocated memory", "pn_Generic_other"),
+ ("M", "memory result"),
+ ("X_regular", "control flow when no exception occurs"),
+ ("X_except", "control flow when exception occured"),
+ ("res", "pointer to newly allocated memory"),
]
attrs = [
dict(
("upper", "upper bound (exclusive)"),
]
outs = [
- ("M", "memory result", "pn_Generic_M"),
- ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
- ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
- ("res", "the checked index", "pn_Generic_other"),
+ ("M", "memory result"),
+ ("X_regular", "control flow when no exception occurs"),
+ ("X_except", "control flow when exception occured"),
+ ("res", "the checked index"),
]
flags = [ "fragile", "highlevel" ]
pinned = "exception"
]
arity = "variable"
outs = [
- ("M", "memory result", "pn_Generic_M"),
- ("1_result", "first result", "pn_Generic_other"),
+ ("M", "memory result"),
+ ("1_result", "first result"),
]
flags = [ "uses_memory" ]
attrs = [
]
arity = "variable"
outs = [
- ("M", "memory result", "pn_Generic_M"),
- ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
- ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
- ("T_result", "tuple containing all results", "pn_Generic_other"),
+ ("M", "memory result"),
+ ("X_regular", "control flow when no exception occurs"),
+ ("X_except", "control flow when exception occured"),
+ ("T_result", "tuple containing all results"),
]
flags = [ "fragile", "uses_memory" ]
attrs = [
("src", "source address"),
]
outs = [
- ("M", "memory result", "pn_Generic_M"),
- ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
- ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
+ ("M", "memory result"),
+ ("X_regular", "control flow when no exception occurs"),
+ ("X_except", "control flow when exception occured"),
]
flags = [ "fragile", "uses_memory" ]
attrs = [
("right", "second operand"),
]
outs = [
- ("M", "memory result", "pn_Generic_M"),
- ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
- ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
- ("res", "result of computation", "pn_Generic_other"),
+ ("M", "memory result"),
+ ("X_regular", "control flow when no exception occurs"),
+ ("X_except", "control flow when exception occured"),
+ ("res", "result of computation"),
]
flags = [ "fragile", "uses_memory" ]
attrs_name = "div"
("obj", "pointer to object being queried")
]
outs = [
- ("M", "memory result", "pn_Generic_M"),
- ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
- ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
- ("res", "checked object pointer", "pn_Generic_other"),
+ ("M", "memory result"),
+ ("X_regular", "control flow when no exception occurs"),
+ ("X_except", "control flow when exception occured"),
+ ("res", "checked object pointer"),
]
flags = [ "highlevel" ]
attrs = [
("ptr", "address to load from"),
]
outs = [
- ("M", "memory result", "pn_Generic_M"),
- ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
- ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
- ("res", "result of load operation", "pn_Generic_other"),
+ ("M", "memory result"),
+ ("X_regular", "control flow when no exception occurs"),
+ ("X_except", "control flow when exception occured"),
+ ("res", "result of load operation"),
]
flags = [ "fragile", "uses_memory" ]
pinned = "exception"
("right", "second operand"),
]
outs = [
- ("M", "memory result", "pn_Generic_M"),
- ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
- ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
- ("res", "result of computation", "pn_Generic_other"),
+ ("M", "memory result"),
+ ("X_regular", "control flow when no exception occurs"),
+ ("X_except", "control flow when exception occured"),
+ ("res", "result of computation"),
]
flags = [ "fragile", "uses_memory" ]
attrs_name = "mod"
("exo_ptr", "pointer to exception object to be thrown"),
]
outs = [
- ("M", "memory result", "pn_Generic_M"),
- ("X", "control flow to exception handler", "pn_Generic_X_regular"),
+ ("M", "memory result"),
+ ("X", "control flow to exception handler"),
]
flags = [ "highlevel", "cfopcode" ]
pinned = "yes"
("value", "value to store"),
]
outs = [
- ("M", "memory result", "pn_Generic_M"),
- ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
- ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
+ ("M", "memory result"),
+ ("X_regular", "control flow when no exception occurs"),
+ ("X_except", "control flow when exception occured"),
]
flags = [ "fragile", "uses_memory" ]
pinned = "exception"
def is_dynamic_pinned(node):
return node.pinned in ["memory", "exception"]
+def inout_contains(l, name):
+ for entry in l:
+ if entry[0] == name:
+ return True
+ return False
+
def verify_node(node):
if not hasattr(node, "pinned"):
print "%s: NO PINNED SET" % node.__name__
print "WARNING: no flags specified for %s\n" % node.__name__
elif type(node.flags) != list:
print "ERROR: flags of %s not a list" % node.__name__
+ if hasattr(node, "flags"):
+ flags = node.flags
+ if "fragile" in flags:
+ if not inout_contains(node.ins, "mem"):
+ print "ERROR: fragile node %s needs an input named 'mem'" % node.__name__
+ if not inout_contains(node.outs, "X_regular"):
+ print "ERROR: fragile node %s needs an output named 'X_regular'" % node.__name__
+ if not inout_contains(node.outs, "X_except"):
+ print "ERROR: fragile node %s needs an output named 'X_except'" % node.__name__
def setldefault(node, attr, val):
# Don't use hasattr, as these things should not be inherited