*** empty log message ***
[mono.git] / mono / jit / emit-x86.c
index ac780a439226eed427fb713b0b5895377986db6c..90930f55b6bc949b8e5ad524c82dd04a6015c984 100644 (file)
@@ -125,13 +125,20 @@ arch_get_argument_info (MonoMethodSignature *csig, int param_count, MonoJitArgum
 {
        int k, frame_size = 0;
        int size, align, pad;
-       
-       if (csig->hasthis)
+       int offset = 8;
+
+       if (MONO_TYPE_ISSTRUCT (csig->ret)) { 
                frame_size += sizeof (gpointer);
+               offset += 4;
+       }
 
-       if (MONO_TYPE_ISSTRUCT (csig->ret)) 
+       arg_info [0].offset = offset;
+
+       if (csig->hasthis) {
                frame_size += sizeof (gpointer);
-       
+               offset += 4;
+       }
+
        arg_info [0].size = frame_size;
 
        for (k = 0; k < param_count; k++) {
@@ -146,6 +153,9 @@ arch_get_argument_info (MonoMethodSignature *csig, int param_count, MonoJitArgum
                frame_size += size;
                arg_info [k + 1].pad = 0;
                arg_info [k + 1].size = size;
+               offset += pad;
+               arg_info [k + 1].offset = offset;
+               offset += size;
        }
 
        align = MONO_FRAME_ALIGNMENT;
@@ -161,6 +171,8 @@ enter_method (MonoMethod *method, char *ebp)
        int i, j;
        MonoClass *class;
        MonoObject *o;
+       MonoJitArgumentInfo *arg_info;
+       MonoMethodSignature *sig;
        char *fname;
 
        fname = mono_method_full_name (method, TRUE);
@@ -171,20 +183,27 @@ enter_method (MonoMethod *method, char *ebp)
                g_error ("unaligned stack detected (%p)", ebp);
        }
 
-       ebp += 8;
+       sig = method->signature;
+
+       if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
+               g_assert (!sig->pinvoke);
+
+       arg_info = alloca (sizeof (MonoJitArgumentInfo) * (sig->param_count + 1));
+
+       arch_get_argument_info (sig, sig->param_count, arg_info);
 
        if (MONO_TYPE_ISSTRUCT (method->signature->ret)) {
                g_assert (!method->signature->ret->byref);
 
-               printf ("VALUERET:%p, ", *((gpointer *)ebp));
-               ebp += sizeof (gpointer);
+               printf ("VALUERET:%p, ", *((gpointer *)(ebp + 8)));
        }
 
        if (method->signature->hasthis) {
+               gpointer *this = (gpointer *)(ebp + arg_info [0].offset);
                if (method->klass->valuetype) {
-                       printf ("value:%p, ", *((gpointer *)ebp));
+                       printf ("value:%p, ", *this);
                } else {
-                       o = *((MonoObject **)ebp);
+                       o = *((MonoObject **)this);
 
                        if (o) {
                                class = o->vtable->klass;
@@ -197,20 +216,16 @@ enter_method (MonoMethod *method, char *ebp)
                        } else 
                                printf ("this:NULL, ");
                }
-               ebp += sizeof (gpointer);
        }
 
        for (i = 0; i < method->signature->param_count; ++i) {
-               int size, align;
-               MonoType *type = method->signature->params [i];
-
-               if (method->signature->pinvoke)
-                       size = mono_type_native_stack_size (type, &align);
-               else
-                       size = mono_type_stack_size (type, &align);
+               gpointer *cpos = (gpointer *)(ebp + arg_info [i + 1].offset);
+               int size = arg_info [i + 1].size;
 
+               MonoType *type = method->signature->params [i];
+               
                if (type->byref) {
-                       printf ("[BYREF:%p], ", *((gpointer *)ebp)); 
+                       printf ("[BYREF:%p], ", *cpos); 
                } else switch (type->type) {
                        
                case MONO_TYPE_BOOLEAN:
@@ -223,10 +238,10 @@ enter_method (MonoMethod *method, char *ebp)
                case MONO_TYPE_U4:
                case MONO_TYPE_I:
                case MONO_TYPE_U:
-                       printf ("%d, ", *((int *)(ebp)));
+                       printf ("%d, ", *((int *)(cpos)));
                        break;
                case MONO_TYPE_STRING: {
-                       MonoString *s = *((MonoString **)ebp);
+                       MonoString *s = *((MonoString **)cpos);
                        if (s) {
                                g_assert (((MonoObject *)s)->vtable->klass == mono_defaults.string_class);
                                printf ("[STRING:%p:%s], ", s, mono_string_to_utf8 (s));
@@ -236,7 +251,7 @@ enter_method (MonoMethod *method, char *ebp)
                }
                case MONO_TYPE_CLASS:
                case MONO_TYPE_OBJECT: {
-                       o = *((MonoObject **)ebp);
+                       o = *((MonoObject **)cpos);
                        if (o) {
                                class = o->vtable->klass;
                    
@@ -247,7 +262,7 @@ enter_method (MonoMethod *method, char *ebp)
                                } else
                                        printf ("[%s.%s:%p], ", class->name_space, class->name, o);
                        } else {
-                               printf ("%p, ", *((gpointer *)(ebp)));                          
+                               printf ("%p, ", *((gpointer *)(cpos)));                         
                        }
                        break;
                }
@@ -255,30 +270,26 @@ enter_method (MonoMethod *method, char *ebp)
                case MONO_TYPE_FNPTR:
                case MONO_TYPE_ARRAY:
                case MONO_TYPE_SZARRAY:
-                       printf ("%p, ", *((gpointer *)(ebp)));
+                       printf ("%p, ", *((gpointer *)(cpos)));
                        break;
                case MONO_TYPE_I8:
-                       printf ("%lld, ", *((gint64 *)(ebp)));
+                       printf ("%lld, ", *((gint64 *)(cpos)));
                        break;
                case MONO_TYPE_R4:
-                       printf ("%f, ", *((float *)(ebp)));
+                       printf ("%f, ", *((float *)(cpos)));
                        break;
                case MONO_TYPE_R8:
-                       printf ("%f, ", *((double *)(ebp)));
+                       printf ("%f, ", *((double *)(cpos)));
                        break;
                case MONO_TYPE_VALUETYPE: 
                        printf ("[");
                        for (j = 0; j < size; j++)
-                               printf ("%02x,", *((guint8*)ebp +j));
+                               printf ("%02x,", *((guint8*)cpos +j));
                        printf ("], ");
                        break;
                default:
                        printf ("XX, ");
                }
-
-               g_assert (align == 4 || align == 8);
-               ebp += size + align - 1;
-               ebp = (gpointer)((unsigned)ebp & ~(align - 1));
        }
 
        printf (")\n");
@@ -400,38 +411,40 @@ arch_emit_prologue (MonoFlowGraph *cfg)
                x86_push_imm (cfg->code, method);
        
                /* get the address of lmf for the current thread */
-               x86_call_code (cfg->code, mono_get_lmf_addr);
+               mono_add_jump_info (cfg, cfg->code, MONO_JUMP_INFO_ABS, mono_get_lmf_addr);
+               x86_call_code (cfg->code, 0);
+
                /* push lmf */
                x86_push_reg (cfg->code, X86_EAX); 
                /* push *lfm (previous_lmf) */
                x86_push_membase (cfg->code, X86_EAX, 0);
                /* *(lmf) = ESP */
                x86_mov_membase_reg (cfg->code, X86_EAX, 0, X86_ESP, 4);
-       }
+       } else {
 
 #if 0
-       /* activation frame alignment check */
-       x86_mov_reg_reg (cfg->code, X86_EAX, X86_ESP, 4);
-       x86_alu_reg_imm (cfg->code, X86_AND, X86_EAX, MONO_FRAME_ALIGNMENT - 1);
-       x86_alu_reg_imm (cfg->code, X86_CMP, X86_EAX, 0);
-       x86_branch32 (cfg->code, X86_CC_EQ, 1, FALSE);
-       x86_breakpoint (cfg->code);
-
+               /* activation frame alignment check */
+               x86_mov_reg_reg (cfg->code, X86_EAX, X86_ESP, 4);
+               x86_alu_reg_imm (cfg->code, X86_AND, X86_EAX, MONO_FRAME_ALIGNMENT - 1);
+               x86_alu_reg_imm (cfg->code, X86_CMP, X86_EAX, 0);
+               x86_branch32 (cfg->code, X86_CC_EQ, 1, FALSE);
+               x86_breakpoint (cfg->code);
 #endif
 
-       if (mono_regset_reg_used (cfg->rs, X86_EBX)) {
-               x86_push_reg (cfg->code, X86_EBX);
-               pos += 4;
-       }
+               if (mono_regset_reg_used (cfg->rs, X86_EBX)) {
+                       x86_push_reg (cfg->code, X86_EBX);
+                       pos += 4;
+               }
 
-       if (mono_regset_reg_used (cfg->rs, X86_EDI)) {
-               x86_push_reg (cfg->code, X86_EDI);
-               pos += 4;
-       }
+               if (mono_regset_reg_used (cfg->rs, X86_EDI)) {
+                       x86_push_reg (cfg->code, X86_EDI);
+                       pos += 4;
+               }
 
-       if (mono_regset_reg_used (cfg->rs, X86_ESI)) {
-               x86_push_reg (cfg->code, X86_ESI);
-               pos += 4;
+               if (mono_regset_reg_used (cfg->rs, X86_ESI)) {
+                       x86_push_reg (cfg->code, X86_ESI);
+                       pos += 4;
+               }
        }
 
        alloc_size -= pos;
@@ -593,29 +606,25 @@ arch_emit_epilogue (MonoFlowGraph *cfg)
                x86_pop_reg (cfg->code, X86_EAX);
        }
 
+       pos = 0;
+       
        if (cfg->method->save_lmf) {
-               pos = -sizeof (MonoLMF) - 4;
-       } else
-               pos = -4;
-
-       if (mono_regset_reg_used (cfg->rs, X86_EBX)) {
-               x86_mov_reg_membase (cfg->code, X86_EBX, X86_EBP, pos, 4);
-               pos -= 4;
-       }
-       if (mono_regset_reg_used (cfg->rs, X86_EDI)) {
-               x86_mov_reg_membase (cfg->code, X86_EDI, X86_EBP, pos, 4);
-               pos -= 4;
+               pos = -sizeof (MonoLMF);
+       } else {
+               if (mono_regset_reg_used (cfg->rs, X86_EBX)) {
+                       pos -= 4;
        }
-       if (mono_regset_reg_used (cfg->rs, X86_ESI)) {
-               x86_mov_reg_membase (cfg->code, X86_ESI, X86_EBP, pos, 4);
-               pos -= 4;
+               if (mono_regset_reg_used (cfg->rs, X86_EDI)) {
+                       pos -= 4;
+               }
+               if (mono_regset_reg_used (cfg->rs, X86_ESI)) {
+                       pos -= 4;
+               }
        }
-
-       if (cfg->method->save_lmf) {
-               pos = -sizeof (MonoLMF);
-
+       if (pos)
                x86_lea_membase (cfg->code, X86_ESP, X86_EBP, pos);
 
+       if (cfg->method->save_lmf) {
                /* ebx = previous_lmf */
                x86_pop_reg (cfg->code, X86_EBX);
                /* edi = lmf */
@@ -632,12 +641,50 @@ arch_emit_epilogue (MonoFlowGraph *cfg)
                x86_pop_reg (cfg->code, X86_EDI);
                x86_pop_reg (cfg->code, X86_EBX);
 
+       } else {
+
+               if (mono_regset_reg_used (cfg->rs, X86_ESI)) {
+                       x86_pop_reg (cfg->code, X86_ESI);
+               }
+               if (mono_regset_reg_used (cfg->rs, X86_EDI)) {
+                       x86_pop_reg (cfg->code, X86_EDI);
+               }
+               if (mono_regset_reg_used (cfg->rs, X86_EBX)) {
+                       x86_pop_reg (cfg->code, X86_EBX);
+               }
        }
 
        x86_leave (cfg->code);
        x86_ret (cfg->code);
 }
 
+static void
+init_varinfo (MonoFlowGraph *cfg, MonoVarInfo *vi)
+{
+       vi->range.last_use.abs_pos = 0;
+       vi->range.first_use.pos.bid = 0xffff;
+       vi->range.first_use.pos.tid = 0;        
+       vi->isvolatile = 0;
+       vi->reg = -1;
+       vi->varnum = cfg->varinfo->len;
+}
+
+int
+arch_allocate_arg (MonoFlowGraph *cfg, MonoJitArgumentInfo *info, MonoValueType type)
+{
+       MonoVarInfo vi;
+
+       mono_jit_stats.allocate_var++;
+
+       init_varinfo (cfg, &vi);
+       vi.isvolatile = 1;
+       
+       SET_VARINFO (vi, type, MONO_ARGVAR, info->offset, info->size);
+       g_array_append_val (cfg->varinfo, vi);
+
+       return cfg->varinfo->len - 1;
+}
+
 int
 arch_allocate_var (MonoFlowGraph *cfg, int size, int align, MonoVarType vartype, MonoValueType type)
 {
@@ -645,43 +692,17 @@ arch_allocate_var (MonoFlowGraph *cfg, int size, int align, MonoVarType vartype,
 
        mono_jit_stats.allocate_var++;
 
-       vi.range.last_use.abs_pos = 0;
-       vi.range.first_use.pos.bid = 0xffff;
-       vi.range.first_use.pos.tid = 0; 
-       vi.isvolatile = 0;
-       vi.reg = -1;
-       vi.varnum = cfg->varinfo->len;
+       init_varinfo (cfg, &vi);
 
        if (size != sizeof (gpointer))
                vi.isvolatile = 1;
        
-       switch (vartype) {
-       case MONO_TEMPVAR:
-       case MONO_LOCALVAR: {
-               cfg->locals_size += size;
-               cfg->locals_size += align - 1;
-               cfg->locals_size &= ~(align - 1);
-
-               SET_VARINFO (vi, type, vartype, - cfg->locals_size, size);
-               g_array_append_val (cfg->varinfo, vi);
-               break;
-       }
-       case MONO_ARGVAR: {
-               int arg_start = 8 + cfg->has_vtarg*4;
-
-               g_assert ((align & 3) == 0);
+       cfg->locals_size += size;
+       cfg->locals_size += align - 1;
+       cfg->locals_size &= ~(align - 1);
 
-               SET_VARINFO (vi, type, vartype, cfg->args_size + arg_start, size);
-               g_array_append_val (cfg->varinfo, vi);
-               
-               cfg->args_size += size;
-               cfg->args_size += 3;
-               cfg->args_size &= ~3;
-               break;
-       }
-       default:
-               g_assert_not_reached ();
-       }
+       SET_VARINFO (vi, type, vartype, - cfg->locals_size, size);
+       g_array_append_val (cfg->varinfo, vi);
 
        return cfg->varinfo->len - 1;
 }
@@ -1213,6 +1234,7 @@ arch_jit_compile_cfg (MonoDomain *target_domain, MonoFlowGraph *cfg)
        MonoJitInfo *ji;
        guint32 ls_used_mask = 0;
        MonoMethod *method = cfg->method;
+       int offset, gap;
 
        ji = mono_mempool_alloc0 (target_domain->mp, sizeof (MonoJitInfo));
                
@@ -1253,6 +1275,21 @@ arch_jit_compile_cfg (MonoDomain *target_domain, MonoFlowGraph *cfg)
        arch_emit_epilogue (cfg);               
        cfg->epilogue_end = cfg->code - cfg->start;
 
+       offset = cfg->code - cfg->start;
+       gap = cfg->code_size - offset;
+       if (gap > 0) {
+               char *org = cfg->start;
+#if 0
+               cfg->start = g_realloc (cfg->start, offset);
+#else
+               cfg->start = mono_mempool_alloc (target_domain->code_mp, offset);
+               memcpy (cfg->start, org, offset);
+               g_free (org);
+#endif
+               cfg->code_size = offset;
+               cfg->code = cfg->start + offset;
+       }
+
        mono_compute_branches (cfg);
 
        ji->code_size = cfg->code - cfg->start;