2006-06-20 Jb Evain <jbevain@gmail.com>
[mono.git] / mono / mini / mini-ppc.c
index cb9d96cb6ecc5b925fa2ac8aef30b7f7ffce9af4..d467bd333019b19a0bb875bb04ed5bfd126b3dd8 100644 (file)
@@ -237,6 +237,10 @@ is_regsize_var (MonoType *t) {
        case MONO_TYPE_SZARRAY:
        case MONO_TYPE_ARRAY:
                return TRUE;
+       case MONO_TYPE_GENERICINST:
+               if (!mono_type_generic_inst_is_valuetype (t))
+                       return TRUE;
+               return FALSE;
        case MONO_TYPE_VALUETYPE:
                return FALSE;
        }
@@ -466,7 +470,6 @@ calculate_sizes (MonoMethodSignature *sig, gboolean is_pinvoke)
                        continue;
                }
                simpletype = mono_type_get_underlying_type (sig->params [i])->type;
-       enum_calc_size:
                switch (simpletype) {
                case MONO_TYPE_BOOLEAN:
                case MONO_TYPE_I1:
@@ -501,6 +504,14 @@ calculate_sizes (MonoMethodSignature *sig, gboolean is_pinvoke)
                        add_general (&gr, &stack_size, cinfo->args + n, TRUE);
                        n++;
                        break;
+               case MONO_TYPE_GENERICINST:
+                       if (!mono_type_generic_inst_is_valuetype (sig->params [i])) {
+                               cinfo->args [n].size = sizeof (gpointer);
+                               add_general (&gr, &stack_size, cinfo->args + n, TRUE);
+                               n++;
+                               break;
+                       }
+                       /* Fall through */
                case MONO_TYPE_VALUETYPE: {
                        gint size;
                        MonoClass *klass;
@@ -669,6 +680,12 @@ enum_retvalue:
                        cinfo->ret.reg = ppc_f1;
                        cinfo->ret.regtype = RegTypeFP;
                        break;
+               case MONO_TYPE_GENERICINST:
+                       if (!mono_type_generic_inst_is_valuetype (sig->ret)) {
+                               cinfo->ret.reg = ppc_r3;
+                               break;
+                       }
+                       break;
                case MONO_TYPE_VALUETYPE:
                        break;
                case MONO_TYPE_TYPEDBYREF:
@@ -1121,7 +1138,10 @@ handle_enum:
  * going to be perf critical anyway.
  */
 typedef struct {
-       MonoBasicBlock *bb;
+       union {
+               MonoBasicBlock *bb;
+               const char *exception;
+       } data;
        guint32 ip_offset;
        guint16 b0_cond;
        guint16 b1_cond;
@@ -1142,7 +1162,7 @@ if (ins->flags & MONO_INST_BRLABEL) { \
                int br_disp = ins->inst_true_bb->max_offset - offset;   \
                if (!ppc_is_imm16 (br_disp + 1024) || ! ppc_is_imm16 (ppc_is_imm16 (br_disp - 1024))) { \
                        MonoOvfJump *ovfj = mono_mempool_alloc (cfg->mempool, sizeof (MonoOvfJump));    \
-                       ovfj->bb = ins->inst_true_bb;   \
+                       ovfj->data.bb = ins->inst_true_bb;      \
                        ovfj->ip_offset = 0;    \
                        ovfj->b0_cond = (b0);   \
                        ovfj->b1_cond = (b1);   \
@@ -1167,13 +1187,12 @@ if (ins->flags & MONO_INST_BRLABEL) { \
                int br_disp = cfg->bb_exit->max_offset - offset;        \
                if (!ppc_is_imm16 (br_disp + 1024) || ! ppc_is_imm16 (ppc_is_imm16 (br_disp - 1024))) { \
                        MonoOvfJump *ovfj = mono_mempool_alloc (cfg->mempool, sizeof (MonoOvfJump));    \
-                       ovfj->bb = NULL;        \
+                       ovfj->data.exception = (exc_name);      \
                        ovfj->ip_offset = code - cfg->native_code;      \
                        ovfj->b0_cond = (b0);   \
                        ovfj->b1_cond = (b1);   \
-                       /* FIXME: test this code */     \
                        mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_EXC_OVF, ovfj); \
-                       ppc_b (code, 0);        \
+                       ppc_bl (code, 0);       \
                        cfg->bb_exit->max_offset += 24; \
                } else {        \
                        mono_add_patch_info (cfg, code - cfg->native_code,   \
@@ -2607,9 +2626,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                                }
                        }
                        break;
-               case OP_X86_TEST_NULL:
-                       ppc_cmpi (code, 0, 0, ins->sreg1, 0);
-                       break;
                case CEE_BREAK:
                        ppc_break (code);
                        break;
@@ -3034,7 +3050,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        g_assert_not_reached ();
                        break;
                case OP_LOCALLOC: {
-                       guint32 * zero_loop_jump, zero_loop_start;
+                       guint32 * zero_loop_jump, zero_loop_start;
                        /* keep alignment */
                        int alloca_waste = PPC_STACK_PARAM_OFFSET + cfg->param_area + 31;
                        int area_offset = alloca_waste;
@@ -3281,14 +3297,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        ppc_fsub (code, ins->dreg, ins->dreg, ppc_f0);
                        break;
                }
-               case OP_X86_FP_LOAD_I8:
-                       g_assert_not_reached ();
-                       /*x86_fild_membase (code, ins->inst_basereg, ins->inst_offset, TRUE);*/
-                       break;
-               case OP_X86_FP_LOAD_I4:
-                       g_assert_not_reached ();
-                       /*x86_fild_membase (code, ins->inst_basereg, ins->inst_offset, FALSE);*/
-                       break;
                case OP_FCONV_TO_I1:
                        code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 1, TRUE);
                        break;
@@ -3813,8 +3821,13 @@ register.  Should this case include linux/ppc?
                pos++;
        }
 
-       if (method->save_lmf) {
+       if (method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
+               ppc_load (code, ppc_r3, cfg->domain);
+               mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD, (gpointer)"mono_jit_thread_attach");
+               ppc_bl (code, 0);
+       }
 
+       if (method->save_lmf) {
                if (lmf_pthread_key != -1) {
                        emit_tls_access (code, ppc_r3, lmf_pthread_key);
                        if (G_STRUCT_OFFSET (MonoJitTlsData, lmf))
@@ -3986,6 +3999,7 @@ exception_id_by_name (const char *name)
        if (strcmp (name, "ArrayTypeMismatchException") == 0)
                return MONO_EXC_ARRAY_TYPE_MISMATCH;
        g_error ("Unknown intrinsic exception %s\n", name);
+       return 0;
 }
 
 void
@@ -4015,8 +4029,15 @@ mono_arch_emit_exceptions (MonoCompile *cfg)
                        }
                } else if (patch_info->type == MONO_PATCH_INFO_BB_OVF)
                        max_epilog_size += 12;
-               else if (patch_info->type == MONO_PATCH_INFO_EXC_OVF)
-                       max_epilog_size += 12;
+               else if (patch_info->type == MONO_PATCH_INFO_EXC_OVF) {
+                       MonoOvfJump *ovfj = patch_info->data.target;
+                       i = exception_id_by_name (ovfj->data.exception);
+                       if (!exc_throw_found [i]) {
+                               max_epilog_size += 12;
+                               exc_throw_found [i] = TRUE;
+                       }
+                       max_epilog_size += 8;
+               }
        }
 
        while (cfg->code_len + max_epilog_size > (cfg->code_size - 16)) {
@@ -4040,22 +4061,28 @@ mono_arch_emit_exceptions (MonoCompile *cfg)
                        ppc_patch (code - 4, ip + 4); /* jump back after the initiali branch */
                        /* jump back to the true target */
                        ppc_b (code, 0);
-                       ip = ovfj->bb->native_offset + cfg->native_code;
+                       ip = ovfj->data.bb->native_offset + cfg->native_code;
                        ppc_patch (code - 4, ip);
                        break;
                }
                case MONO_PATCH_INFO_EXC_OVF: {
                        MonoOvfJump *ovfj = patch_info->data.target;
+                       MonoJumpInfo *newji;
                        unsigned char *ip = patch_info->ip.i + cfg->native_code;
-                       /* patch the initial jump */
+                       unsigned char *bcl = code;
+                       /* patch the initial jump: we arrived here with a call */
                        ppc_patch (ip, code);
-                       ppc_bc (code, ovfj->b0_cond, ovfj->b1_cond, 2);
+                       ppc_bc (code, ovfj->b0_cond, ovfj->b1_cond, 0);
                        ppc_b (code, 0);
                        ppc_patch (code - 4, ip + 4); /* jump back after the initiali branch */
-                       /* jump back to the true target */
-                       ppc_b (code, 0);
-                       ip = cfg->native_code + ovfj->ip_offset + 4;
-                       ppc_patch (code - 4, ip);
+                       /* patch the conditional jump to the right handler */
+                       /* make it processed next */
+                       newji = mono_mempool_alloc (cfg->mempool, sizeof (MonoJumpInfo));
+                       newji->type = MONO_PATCH_INFO_EXC;
+                       newji->ip.i = bcl - cfg->native_code;
+                       newji->data.target = ovfj->data.exception;
+                       newji->next = patch_info->next;
+                       patch_info->next = newji;
                        break;
                }
                case MONO_PATCH_INFO_EXC: {