Merge pull request #1949 from lewurm/fixtype
[mono.git] / mono / mini / decompose.c
index 5105be86cc15e57b4d9d631a8397bc5c9cce0d7b..a9b7e0a68f1cfa9e8818da89606bb35c01894422 100644 (file)
@@ -307,10 +307,7 @@ mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins)
        gboolean emulate = FALSE;
 
        /* FIXME: Instead of = NOP, don't emit the original ins at all */
-
-#ifdef MONO_ARCH_HAVE_DECOMPOSE_OPTS
        mono_arch_decompose_opts (cfg, ins);
-#endif
 
        /*
         * The code below assumes that we are called immediately after emitting 
@@ -446,7 +443,7 @@ mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins)
                cfg->exception_message = g_strdup_printf ("float conv.ovf.un opcodes not supported.");
                break;
 
-#if defined(MONO_ARCH_EMULATE_DIV) && defined(MONO_ARCH_HAVE_OPCODE_NEEDS_EMULATION)
+#if defined(MONO_ARCH_EMULATE_DIV)
        case OP_IDIV:
        case OP_IREM:
        case OP_IDIV_UN:
@@ -466,11 +463,11 @@ mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins)
                                MONO_EMIT_NEW_UNALU (cfg, OP_ICEQ, reg2, -1);
                                MONO_EMIT_NEW_BIALU (cfg, OP_IAND, reg1, reg1, reg2);
                                MONO_EMIT_NEW_ICOMPARE_IMM (cfg, reg1, 1);
-                               MONO_EMIT_NEW_COND_EXC (cfg, IEQ, "DivideByZeroException");
+                               MONO_EMIT_NEW_COND_EXC (cfg, IEQ, "OverflowException");
                        }
 #endif
                        MONO_EMIT_NEW_BIALU (cfg, ins->opcode, ins->dreg, ins->sreg1, ins->sreg2);
-                       ins->opcode = OP_NOP;
+                       NULLIFY_INS (ins);
                } else {
                        emulate = TRUE;
                }
@@ -486,7 +483,10 @@ mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins)
                        ins->opcode = OP_ICONST;
                        MONO_INST_NULLIFY_SREGS (ins);
                        ins->inst_c0 = 0;
-               } else if ((ins->inst_imm > 0) && (ins->inst_imm < (1L << 32)) && (power != -1)) {
+#if __s390__
+               }
+#else
+               } else if ((ins->inst_imm > 0) && (ins->inst_imm < (1LL << 32)) && (power != -1)) {
                        gboolean is_long = ins->opcode == OP_LREM_IMM;
                        int compensator_reg = alloc_ireg (cfg);
                        int intermediate_reg;
@@ -497,12 +497,12 @@ mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins)
 
                        if (power > 1) {
                                intermediate_reg = compensator_reg;
-                               MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LSHR_IMM : OP_SHR_IMM, intermediate_reg, ins->sreg1, is_long ? 63 : 31);
+                               MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LSHR_IMM : OP_ISHR_IMM, intermediate_reg, ins->sreg1, is_long ? 63 : 31);
                        } else {
                                intermediate_reg = ins->sreg1;
                        }
 
-                       MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LSHR_UN_IMM : OP_SHR_UN_IMM, compensator_reg, intermediate_reg, (is_long ? 64 : 32) - power);
+                       MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LSHR_UN_IMM : OP_ISHR_UN_IMM, compensator_reg, intermediate_reg, (is_long ? 64 : 32) - power);
                        MONO_EMIT_NEW_BIALU (cfg, is_long ? OP_LADD : OP_IADD, ins->dreg, ins->sreg1, compensator_reg);
                        /* Compute remainder */
                        MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LAND_IMM : OP_AND_IMM, ins->dreg, ins->dreg, (1 << power) - 1);
@@ -511,6 +511,7 @@ mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins)
 
                        NULLIFY_INS (ins);
                }
+#endif
                break;
        }
 
@@ -552,7 +553,7 @@ mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins)
                                }
                        }
 
-                       call = mono_emit_native_call (cfg, mono_icall_get_wrapper (info), info->sig, args);
+                       call = mono_emit_jit_icall_by_info (cfg, info, args);
                        call->dreg = ins->dreg;
 
                        NULLIFY_INS (ins);
@@ -625,21 +626,17 @@ mono_decompose_long_opts (MonoCompile *cfg)
        first_bb = cfg->cbb;
 
        for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
-               MonoInst *tree = bb->code;      
+               MonoInst *tree = mono_bb_first_inst(bb, FILTER_IL_SEQ_POINT);
                MonoInst *prev = NULL;
 
                   /*
                mono_print_bb (bb, "BEFORE LOWER_LONG_OPTS");
                */
 
-               tree = bb->code;
                cfg->cbb->code = cfg->cbb->last_ins = NULL;
 
                while (tree) {
-
-#ifdef MONO_ARCH_HAVE_DECOMPOSE_LONG_OPTS
                        mono_arch_decompose_long_opts (cfg, tree);
-#endif
 
                        switch (tree->opcode) {
                        case OP_I8CONST:
@@ -963,7 +960,7 @@ mono_decompose_long_opts (MonoCompile *cfg)
                                break;
 
                        case OP_LCOMPARE: {
-                               MonoInst *next = tree->next;
+                               MonoInst *next = mono_inst_next (tree, FILTER_IL_SEQ_POINT);
 
                                g_assert (next);
 
@@ -980,7 +977,7 @@ mono_decompose_long_opts (MonoCompile *cfg)
                                        MONO_EMIT_NEW_BIALU (cfg, OP_IOR, d1, d1, d2);
                                        MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0);
                                        MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, next->opcode == OP_LBEQ ? OP_IBEQ : OP_IBNE_UN, next->inst_true_bb, next->inst_false_bb);
-                                       next->opcode = OP_NOP;
+                                       NULLIFY_INS (next);
                                        break;
                                }
                                case OP_LBGE:
@@ -998,7 +995,7 @@ mono_decompose_long_opts (MonoCompile *cfg)
                                        MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, next->inst_false_bb);
                                        MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, tree->sreg1 + 1, tree->sreg2 + 1);
                                        MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, lbr_decomp [next->opcode - OP_LBEQ][1], next->inst_true_bb, next->inst_false_bb);
-                                       next->opcode = OP_NOP;
+                                       NULLIFY_INS (next);
                                        break;
                                case OP_LCEQ: {
                                        int d1, d2;
@@ -1012,7 +1009,7 @@ mono_decompose_long_opts (MonoCompile *cfg)
 
                                        MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0);
                                        MONO_EMIT_NEW_UNALU (cfg, OP_ICEQ, next->dreg, -1);
-                                       next->opcode = OP_NOP;
+                                       NULLIFY_INS (next);
                                        break;
                                }
                                case OP_LCLT:
@@ -1034,7 +1031,7 @@ mono_decompose_long_opts (MonoCompile *cfg)
                                        MONO_START_BB (cfg, set_to_1);
                                        MONO_EMIT_NEW_ICONST (cfg, next->dreg, 1);
                                        MONO_START_BB (cfg, set_to_0);
-                                       next->opcode = OP_NOP;
+                                       NULLIFY_INS (next);
                                        break;  
                                }
                                default:
@@ -1045,7 +1042,7 @@ mono_decompose_long_opts (MonoCompile *cfg)
 
                        /* Not yet used, since lcompare is decomposed before local cprop */
                        case OP_LCOMPARE_IMM: {
-                               MonoInst *next = tree->next;
+                               MonoInst *next = mono_inst_next (tree, FILTER_IL_SEQ_POINT);
                                guint32 low_imm = tree->inst_ls_word;
                                guint32 high_imm = tree->inst_ms_word;
                                int low_reg = tree->sreg1 + 1;
@@ -1066,7 +1063,7 @@ mono_decompose_long_opts (MonoCompile *cfg)
                                        MONO_EMIT_NEW_BIALU (cfg, OP_IOR, d1, d1, d2);
                                        MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0);
                                        MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, next->opcode == OP_LBEQ ? OP_IBEQ : OP_IBNE_UN, next->inst_true_bb, next->inst_false_bb);
-                                       next->opcode = OP_NOP;
+                                       NULLIFY_INS (next);
                                        break;
                                }
 
@@ -1085,7 +1082,7 @@ mono_decompose_long_opts (MonoCompile *cfg)
                                        MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, next->inst_false_bb);
                                        MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, low_reg, low_imm);
                                        MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, lbr_decomp [next->opcode - OP_LBEQ][1], next->inst_true_bb, next->inst_false_bb);
-                                       next->opcode = OP_NOP;
+                                       NULLIFY_INS (next);
                                        break;
                                case OP_LCEQ: {
                                        int d1, d2;
@@ -1099,7 +1096,7 @@ mono_decompose_long_opts (MonoCompile *cfg)
 
                                        MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, d1, 0);
                                        MONO_EMIT_NEW_UNALU (cfg, OP_ICEQ, next->dreg, -1);
-                                       next->opcode = OP_NOP;
+                                       NULLIFY_INS (next);
                                        break;
                                }
                                case OP_LCLT:
@@ -1121,7 +1118,7 @@ mono_decompose_long_opts (MonoCompile *cfg)
                                        MONO_START_BB (cfg, set_to_1);
                                        MONO_EMIT_NEW_ICONST (cfg, next->dreg, 1);
                                        MONO_START_BB (cfg, set_to_0);
-                                       next->opcode = OP_NOP;
+                                       NULLIFY_INS (next);
                                        break;  
                                }
                                default:
@@ -1145,9 +1142,9 @@ mono_decompose_long_opts (MonoCompile *cfg)
 
                                /* Process the newly added ops again since they can be long ops too */
                                if (prev)
-                                       tree = prev->next;
+                                       tree = mono_inst_next (prev, FILTER_IL_SEQ_POINT);
                                else
-                                       tree = bb->code;
+                                       tree = mono_bb_first_inst (bb, FILTER_IL_SEQ_POINT);
 
                                first_bb->code = first_bb->last_ins = NULL;
                                first_bb->in_count = first_bb->out_count = 0;
@@ -1155,7 +1152,7 @@ mono_decompose_long_opts (MonoCompile *cfg)
                        }
                        else {
                                prev = tree;
-                               tree = tree->next;
+                               tree = mono_inst_next (tree, FILTER_IL_SEQ_POINT);
                        }
                }
        }
@@ -1330,18 +1327,18 @@ mono_decompose_vtype_opts (MonoCompile *cfg)
                                        if (call->vret_in_reg) {
                                                MonoCallInst *call2;
 
-                                               /* Replace the vcall with an integer call */
+                                               /* Replace the vcall with a scalar call */
                                                MONO_INST_NEW_CALL (cfg, call2, OP_NOP);
                                                memcpy (call2, call, sizeof (MonoCallInst));
                                                switch (ins->opcode) {
                                                case OP_VCALL:
-                                                       call2->inst.opcode = OP_CALL;
+                                                       call2->inst.opcode = call->vret_in_reg_fp ? OP_FCALL : OP_CALL;
                                                        break;
                                                case OP_VCALL_REG:
-                                                       call2->inst.opcode = OP_CALL_REG;
+                                                       call2->inst.opcode = call->vret_in_reg_fp ? OP_FCALL_REG : OP_CALL_REG;
                                                        break;
                                                case OP_VCALL_MEMBASE:
-                                                       call2->inst.opcode = OP_CALL_MEMBASE;
+                                                       call2->inst.opcode = call->vret_in_reg_fp ? OP_FCALL_MEMBASE : OP_CALL_MEMBASE;
                                                        break;
                                                }
                                                call2->inst.dreg = alloc_preg (cfg);
@@ -1367,12 +1364,19 @@ mono_decompose_vtype_opts (MonoCompile *cfg)
                                                        break;
                                                case 3:
                                                case 4:
-                                                       MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
+                                                       if (call->vret_in_reg_fp)
+                                                               MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
+                                                       else
+                                                               MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
                                                        break;
                                                case 5:
                                                case 6:
                                                case 7:
                                                case 8:
+                                                       if (call->vret_in_reg_fp) {
+                                                               MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
+                                                               break;
+                                                       }
 #if SIZEOF_REGISTER == 4
                                                        /*
                                                        FIXME Other ABIs might return in different regs than the ones used for LCALL.