Commit b603a714 authored by Matthias Braun's avatar Matthias Braun
Browse files

don't fail if type mode can't be determine (which can happen when passing structs)

[r14479]
parent f6590e7b
......@@ -1603,11 +1603,13 @@ static void ia32_get_call_abi(const void *self, ir_type *method_type, be_abi_cal
for (i = 0; i < n; i++) {
const ir_mode *mode;
const arch_register_t *reg;
const arch_register_t *reg = NULL;
tp = get_method_param_type(method_type, i);
mode = get_type_mode(tp);
if(mode != NULL) {
reg = ia32_get_RegParam_reg(isa->cg, cc, i, mode);
}
if(reg != NULL) {
be_abi_call_param_reg(abi, i, reg);
......
......@@ -387,14 +387,24 @@ void ia32_emit_function_size(ia32_emit_env_t *env, const char *name)
}
static
void emit_ia32_Immediate(ia32_emit_env_t *env, const ir_node *node);
/**
* Emits registers and/or address mode of a binary operation.
*/
void ia32_emit_binop(ia32_emit_env_t *env, const ir_node *node) {
const ir_node *right_op;
switch(get_ia32_op_type(node)) {
case ia32_Normal:
if (is_ia32_ImmConst(node) || is_ia32_ImmSymConst(node)) {
right_op = get_irn_n(node, 3);
if(is_ia32_Immediate(right_op)) {
emit_ia32_Immediate(env, right_op);
be_emit_cstring(env, ", ");
ia32_emit_source_register(env, node, 2);
break;
} else if (is_ia32_ImmConst(node) || is_ia32_ImmSymConst(node)) {
ia32_emit_immediate(env, node);
be_emit_cstring(env, ", ");
ia32_emit_source_register(env, node, 2);
......@@ -433,7 +443,13 @@ void ia32_emit_binop(ia32_emit_env_t *env, const ir_node *node) {
}
break;
case ia32_AddrModeD:
if (is_ia32_ImmConst(node) || is_ia32_ImmSymConst(node)) {
right_op = get_irn_n(node, 3);
if(is_ia32_Immediate(right_op)) {
emit_ia32_Immediate(env, right_op);
be_emit_cstring(env, ", ");
ia32_emit_am(env, node);
break;
} else if (is_ia32_ImmConst(node) || is_ia32_ImmSymConst(node)) {
ia32_emit_immediate(env, node);
be_emit_cstring(env, ", ");
ia32_emit_am(env, node);
......@@ -495,26 +511,31 @@ void ia32_emit_x87_binop(ia32_emit_env_t *env, const ir_node *node) {
}
}
void ia32_emit_am_or_dest_register(ia32_emit_env_t *env, const ir_node *node,
int pos) {
if(get_ia32_op_type(node) == ia32_Normal) {
ia32_emit_dest_register(env, node, pos);
} else {
assert(get_ia32_op_type(node) == ia32_AddrModeD);
ia32_emit_am(env, node);
}
}
/**
* Emits registers and/or address mode of a unary operation.
*/
void ia32_emit_unop(ia32_emit_env_t *env, const ir_node *node) {
void ia32_emit_unop(ia32_emit_env_t *env, const ir_node *node, int pos) {
const ir_node *op;
switch(get_ia32_op_type(node)) {
case ia32_Normal:
if (is_ia32_ImmConst(node) || is_ia32_ImmSymConst(node)) {
op = get_irn_n(node, pos);
if (is_ia32_Immediate(op)) {
emit_ia32_Immediate(env, op);
} else if (is_ia32_ImmConst(node) || is_ia32_ImmSymConst(node)) {
ia32_emit_immediate(env, node);
} else {
if (is_ia32_Mul(node) || is_ia32_IMul1OP(node)) {
ia32_emit_source_register(env, node, 3);
} else if(is_ia32_IDiv(node) || is_ia32_Div(node)) {
ia32_emit_source_register(env, node, 4);
} else if(is_ia32_Push(node)) {
ia32_emit_source_register(env, node, 2);
} else if(is_ia32_Pop(node)) {
ia32_emit_dest_register(env, node, 1);
} else {
ia32_emit_dest_register(env, node, 0);
}
ia32_emit_source_register(env, node, pos);
}
break;
case ia32_AddrModeS:
......@@ -1317,6 +1338,7 @@ void emit_ia32_Immediate(ia32_emit_env_t *env, const ir_node *node)
{
const ia32_attr_t *attr = get_ia32_attr_const(node);
assert(attr->am_sc != NULL || attr->cnst_val.tv != NULL);
if(attr->am_sc != NULL) {
ident *id = get_entity_ld_ident(attr->am_sc);
......
......@@ -52,7 +52,9 @@ void ia32_emit_xmm_mode_suffix(ia32_emit_env_t *env, const ir_node *node);
void ia32_emit_xmm_mode_suffix_s(ia32_emit_env_t *env, const ir_node *node);
void ia32_emit_extend_suffix(ia32_emit_env_t *env, const ir_mode *mode);
void ia32_emit_binop(ia32_emit_env_t *env, const ir_node *node);
void ia32_emit_unop(ia32_emit_env_t *env, const ir_node *node);
void ia32_emit_am_or_dest_register(ia32_emit_env_t *env, const ir_node *node,
int pos);
void ia32_emit_unop(ia32_emit_env_t *env, const ir_node *node, int pos);
void ia32_emit_am(ia32_emit_env_t *env, const ir_node *node);
void ia32_emit_adr(ia32_emit_env_t *env, const ir_node *node);
void ia32_emit_x87_binop(ia32_emit_env_t *env, const ir_node *node);
......
......@@ -271,7 +271,13 @@ $arch = "ia32";
XXM => "${arch}_emit_xmm_mode_suffix(env, node);",
XSD => "${arch}_emit_xmm_mode_suffix_s(env, node);",
AM => "${arch}_emit_am(env, node);",
unop => "${arch}_emit_unop(env, node);",
unop0 => "${arch}_emit_unop(env, node, 0);",
unop1 => "${arch}_emit_unop(env, node, 1);",
unop2 => "${arch}_emit_unop(env, node, 2);",
unop3 => "${arch}_emit_unop(env, node, 3);",
unop4 => "${arch}_emit_unop(env, node, 4);",
DAM0 => "${arch}_emit_am_or_dest_register(env, node, 0);",
DAM1 => "${arch}_emit_am_or_dest_register(env, node, 0);",
binop => "${arch}_emit_binop(env, node);",
x87_binop => "${arch}_emit_x87_binop(env, node);",
);
......@@ -404,8 +410,9 @@ Mul => {
# we should not rematrialize this node. It produces 2 results and has
# very strict constrains
reg_req => { in => [ "gp", "gp", "eax", "gp", "none" ], out => [ "eax", "edx", "none" ] },
emit => '. mul%M %unop',
emit => '. mul%M %unop3',
outs => [ "EAX", "EDX", "M" ],
ins => [ "base", "index", "val_high", "val_low", "mem" ],
latency => 10,
units => [ "GP" ],
modified_flags => $status_flags
......@@ -433,8 +440,9 @@ IMul => {
IMul1OP => {
irn_flags => "R",
reg_req => { in => [ "gp", "gp", "eax", "gp", "none" ], out => [ "eax", "edx", "none" ] },
emit => '. imul%M %unop',
emit => '. imul%M %unop3',
outs => [ "EAX", "EDX", "M" ],
ins => [ "base", "index", "val_high", "val_low", "mem" ],
latency => 5,
units => [ "GP" ],
modified_flags => $status_flags
......@@ -531,7 +539,7 @@ IDiv => {
reg_req => { in => [ "gp", "gp", "eax", "edx", "gp", "none" ], out => [ "eax", "edx", "none" ] },
attr => "ia32_op_flavour_t dm_flav",
init_attr => "attr->data.op_flav = dm_flav;",
emit => ". idiv%M %unop",
emit => ". idiv%M %unop4",
outs => [ "div_res", "mod_res", "M" ],
latency => 25,
units => [ "GP" ],
......@@ -544,7 +552,7 @@ Div => {
reg_req => { in => [ "gp", "gp", "eax", "edx", "gp", "none" ], out => [ "eax", "edx", "none" ] },
attr => "ia32_op_flavour_t dm_flav",
init_attr => "attr->data.op_flav = dm_flav;",
emit => ". div%M %unop",
emit => ". div%M %unop4",
outs => [ "div_res", "mod_res", "M" ],
latency => 25,
units => [ "GP" ],
......@@ -696,7 +704,8 @@ Rol => {
Neg => {
irn_flags => "R",
reg_req => { in => [ "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
emit => '. neg%M %unop',
emit => '. neg%M %unop2',
ins => [ "base", "index", "val", "mem" ],
units => [ "GP" ],
mode => $mode_gp,
modified_flags => $status_flags
......@@ -725,7 +734,7 @@ l_Neg => {
Inc => {
irn_flags => "R",
reg_req => { in => [ "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
emit => '. inc%M %unop',
emit => '. inc%M %unop2',
units => [ "GP" ],
mode => $mode_gp,
modified_flags => [ "OF", "SF", "ZF", "AF", "PF" ]
......@@ -734,7 +743,7 @@ Inc => {
Dec => {
irn_flags => "R",
reg_req => { in => [ "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
emit => '. dec%M %unop',
emit => '. dec%M %unop2',
units => [ "GP" ],
mode => $mode_gp,
modified_flags => [ "OF", "SF", "ZF", "AF", "PF" ]
......@@ -743,7 +752,7 @@ Dec => {
Not => {
irn_flags => "R",
reg_req => { in => [ "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
emit => '. not%M %unop',
emit => '. not%M %unop2',
units => [ "GP" ],
mode => $mode_gp,
modified_flags => []
......@@ -962,7 +971,8 @@ Lea => {
Push => {
reg_req => { in => [ "gp", "gp", "gp", "esp", "none" ], out => [ "esp", "none" ] },
emit => '. push%M %unop',
emit => '. push%M %unop2',
ins => [ "base", "index", "val", "stack", "mem" ],
outs => [ "stack:I|S", "M" ],
latency => 3,
units => [ "GP" ],
......@@ -971,8 +981,9 @@ Push => {
Pop => {
reg_req => { in => [ "gp", "gp", "esp", "none" ], out => [ "esp", "gp", "none" ] },
emit => '. pop%M %unop',
emit => '. pop%M %DAM1',
outs => [ "stack:I|S", "res", "M" ],
ins => [ "base", "index", "stack", "mem" ],
latency => 4,
units => [ "GP" ],
modified_flags => [],
......@@ -1206,7 +1217,7 @@ CvtSI2SS => {
CvtSI2SD => {
op_flags => "L|F",
reg_req => { in => [ "gp", "gp", "gp", "none" ], out => [ "xmm" ] },
emit => '. cvtsi2sd %unop',
emit => '. cvtsi2sd %unop2',
latency => 2,
units => [ "SSE" ],
mode => $mode_xmm
......
......@@ -126,6 +126,8 @@ typedef ir_node *(transform_func)(ir_node *node);
static ir_node *duplicate_node(ir_node *node);
static ir_node *transform_node(ir_node *node);
static void duplicate_deps(ir_node *old_node, ir_node *new_node);
static ir_node *try_create_Immediate(ir_node *node,
char immediate_constraint_type);
static INLINE int mode_needs_gp_reg(ir_mode *mode)
{
......@@ -524,6 +526,7 @@ static void fold_immediate(ir_node *node, int in1, int in2) {
return;
}
clear_ia32_commutative(node);
set_ia32_am_support(node, get_ia32_am_support(node) & ~ia32_am_Source);
}
......@@ -536,17 +539,38 @@ static void fold_immediate(ir_node *node, int in1, int in2) {
* @return The constructed ia32 node.
*/
static ir_node *gen_binop(ir_node *node, ir_node *op1, ir_node *op2,
construct_binop_func *func)
construct_binop_func *func, int commutative)
{
ir_node *block = transform_node(get_nodes_block(node));
ir_node *new_op1 = transform_node(op1);
ir_node *new_op2 = transform_node(op2);
ir_node *new_op1 = NULL;
ir_node *new_op2 = NULL;
ir_node *new_node = NULL;
ir_graph *irg = env.irg;
dbg_info *dbgi = get_irn_dbg_info(node);
ir_node *noreg_gp = ia32_new_NoReg_gp(env.cg);
ir_node *nomem = new_NoMem();
if(commutative) {
new_op2 = try_create_Immediate(op1, 0);
if(new_op2 != NULL) {
new_op1 = transform_node(op2);
commutative = 0;
}
}
if(new_op2 == NULL) {
new_op2 = try_create_Immediate(op2, 0);
if(new_op2 != NULL) {
new_op1 = transform_node(op1);
commutative = 0;
}
}
if(new_op2 == NULL) {
new_op1 = transform_node(op1);
new_op2 = transform_node(op2);
}
new_node = func(dbgi, irg, block, noreg_gp, noreg_gp, new_op1, new_op2, nomem);
if (func == new_rd_ia32_IMul) {
set_ia32_am_support(new_node, ia32_am_Source);
......@@ -555,10 +579,9 @@ static ir_node *gen_binop(ir_node *node, ir_node *op1, ir_node *op2,
}
SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env.cg, node));
if (is_op_commutative(get_irn_op(node))) {
if (commutative) {
set_ia32_commutative(new_node);
}
fold_immediate(new_node, 2, 3);
return new_node;
}
......@@ -700,7 +723,6 @@ static ir_node *gen_unop(ir_node *node, ir_node *op, construct_unop_func *func)
return new_node;
}
/**
* Creates an ia32 Add.
*
......@@ -887,7 +909,7 @@ static ir_node *gen_Mul(ir_node *node) {
signed or unsigned multiplication so we use IMul as it has fewer
constraints
*/
return gen_binop(node, op1, op2, new_rd_ia32_IMul);
return gen_binop(node, op1, op2, new_rd_ia32_IMul, 1);
}
/**
......@@ -944,7 +966,7 @@ static ir_node *gen_And(ir_node *node) {
ir_node *op2 = get_And_right(node);
assert (! mode_is_float(get_irn_mode(node)));
return gen_binop(node, op1, op2, new_rd_ia32_And);
return gen_binop(node, op1, op2, new_rd_ia32_And, 1);
}
......@@ -959,7 +981,7 @@ static ir_node *gen_Or(ir_node *node) {
ir_node *op2 = get_Or_right(node);
assert (! mode_is_float(get_irn_mode(node)));
return gen_binop(node, op1, op2, new_rd_ia32_Or);
return gen_binop(node, op1, op2, new_rd_ia32_Or, 1);
}
......@@ -974,7 +996,7 @@ static ir_node *gen_Eor(ir_node *node) {
ir_node *op2 = get_Eor_right(node);
assert(! mode_is_float(get_irn_mode(node)));
return gen_binop(node, op1, op2, new_rd_ia32_Xor);
return gen_binop(node, op1, op2, new_rd_ia32_Xor, 1);
}
......@@ -1961,6 +1983,19 @@ static ir_node *gen_CopyB(ir_node *node) {
return res;
}
static
ir_node *gen_be_Copy(ir_node *node)
{
ir_node *result = duplicate_node(node);
ir_mode *mode = get_irn_mode(result);
if (mode_needs_gp_reg(mode)) {
set_irn_mode(result, mode_Iu);
}
return result;
}
#if 0
/**
......@@ -2118,14 +2153,14 @@ static ir_node *gen_Psi(ir_node *node) {
else {
if (is_ia32_Const_1(psi_true) && is_ia32_Const_0(psi_default)) {
/* first case for SETcc: default is 0, set to 1 iff condition is true */
new_op = gen_binop(node, cmp_a, cmp_b, set_func);
new_op = gen_binop(node, cmp_a, cmp_b, set_func, 0);
set_ia32_pncode(new_op, pnc);
set_ia32_am_support(new_op, ia32_am_Source);
}
else if (is_ia32_Const_0(psi_true) && is_ia32_Const_1(psi_default)) {
/* second case for SETcc: default is 1, set to 0 iff condition is true: */
/* we invert condition and set default to 0 */
new_op = gen_binop(node, cmp_a, cmp_b, set_func);
new_op = gen_binop(node, cmp_a, cmp_b, set_func, 0);
set_ia32_pncode(new_op, get_inversed_pnc(pnc));
set_ia32_am_support(new_op, ia32_am_Source);
}
......@@ -2294,6 +2329,12 @@ static ir_node *gen_Conv(ir_node *node) {
if (mode_is_float(src_mode)) {
/* we convert from float ... */
if (mode_is_float(tgt_mode)) {
if(src_mode == mode_E && tgt_mode == mode_D
&& !get_Conv_strict(node)) {
DB((dbg, LEVEL_1, "killed Conv(mode, mode) ..."));
return new_op;
}
/* ... to float */
if (USE_SSE2(env.cg)) {
DB((dbg, LEVEL_1, "create Conv(float, float) ..."));
......@@ -2397,6 +2438,7 @@ int check_immediate_constraint(tarval *tv, char immediate_constraint_type)
return 0;
}
static
ir_node *try_create_Immediate(ir_node *node, char immediate_constraint_type)
{
int minus = 0;
......@@ -2447,8 +2489,8 @@ ir_node *try_create_Immediate(ir_node *node, char immediate_constraint_type)
offset_sign = minus;
}
} else if(is_Sub(node)) {
ir_node *left = get_Add_left(node);
ir_node *right = get_Add_right(node);
ir_node *left = get_Sub_left(node);
ir_node *right = get_Sub_right(node);
if(is_Const(left) && is_SymConst(right)) {
cnst = left;
symconst = right;
......@@ -2485,6 +2527,8 @@ ir_node *try_create_Immediate(ir_node *node, char immediate_constraint_type)
return NULL;
symconst_ent = get_SymConst_entity(symconst);
}
if(cnst == NULL && symconst == NULL)
return NULL;
irg = env.irg;
dbgi = get_irn_dbg_info(node);
......@@ -2614,6 +2658,7 @@ void parse_asm_constraint(ir_node *node, int pos, constraint_t *constraint,
case 'f':
case 't':
case 'u':
/* TODO: mark values so the x87 simulator knows about t and u */
assert(cls == NULL);
cls = &ia32_reg_classes[CLASS_ia32_vfp];
break;
......@@ -3374,12 +3419,12 @@ static ir_node *gen_lowered_Store(ir_node *node, construct_store_func func, char
* @return the created ia32 XXX node
*/
#define GEN_LOWERED_OP(op) \
static ir_node *gen_ia32_l_##op(ir_node *node) {\
static ir_node *gen_ia32_l_##op(ir_node *node) { \
ir_mode *mode = get_irn_mode(node); \
if (mode_is_float(mode)) \
FP_USED(env.cg); \
return gen_binop(node, get_binop_left(node), \
get_binop_right(node), new_rd_ia32_##op); \
get_binop_right(node), new_rd_ia32_##op,0); \
}
#define GEN_LOWERED_x87_OP(op) \
......@@ -4235,6 +4280,7 @@ static void register_transformers(void) {
GEN(be_StackParam);
GEN(be_AddSP);
GEN(be_SubSP);
GEN(be_Copy);
/* set the register for all Unknown nodes */
GEN(Unknown);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment