#include "jit.h"
#include "helpers.h"
#include "codegen.h"
-#include "debug.h"
//#define DEBUG_REGALLOC
static int
cpuid (int id, int* p_eax, int* p_ebx, int* p_ecx, int* p_edx)
{
+#ifdef PIC
+ return 0;
+#else
int have_cpuid = 0;
__asm__ __volatile__ (
"pushfl\n"
return 1;
}
return 0;
+#endif
}
void
}
}
+/*
+ * arch_get_argument_info:
+ * @csig: a method signature
+ * @param_count: the number of parameters to consider
+ * @arg_info: an array to store the result infos
+ *
+ * Gathers information on parameters such as size, alignment and
+ * padding. arg_info should be large enought to hold param_count + 1 entries.
+ *
+ * Returns the size of the activation frame.
+ */
+int
+arch_get_argument_info (MonoMethodSignature *csig, int param_count, MonoJitArgumentInfo *arg_info)
+{
+ int k, frame_size = 0;
+ int size, align, pad;
+ int offset = 8;
+
+ if (MONO_TYPE_ISSTRUCT (csig->ret)) {
+ frame_size += sizeof (gpointer);
+ offset += 4;
+ }
+
+ 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++) {
+
+ if (csig->pinvoke)
+ size = mono_type_native_stack_size (csig->params [k], &align);
+ else
+ size = mono_type_stack_size (csig->params [k], &align);
+
+ frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1);
+ arg_info [k].pad = pad;
+ 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;
+ frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1);
+ arg_info [k].pad = pad;
+
+ return frame_size;
+}
+
static void
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);
printf ("ENTER: %s\n(", fname);
g_free (fname);
- if (((int)ebp & 3) != 0) {
+ if (((int)ebp & (MONO_FRAME_ALIGNMENT - 1)) != 0) {
g_error ("unaligned stack detected (%p)", ebp);
}
- ebp += 8;
+ sig = method->signature;
- if (ISSTRUCT (method->signature->ret)) {
- int size, align;
-
- g_assert (!method->signature->ret->byref);
+ if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
+ g_assert (!sig->pinvoke);
+
+ arg_info = alloca (sizeof (MonoJitArgumentInfo) * (sig->param_count + 1));
- size = mono_type_stack_size (method->signature->ret, &align);
+ arch_get_argument_info (sig, sig->param_count, arg_info);
- printf ("VALUERET:%p, ", *((gpointer *)ebp));
- ebp += sizeof (gpointer);
+ if (MONO_TYPE_ISSTRUCT (method->signature->ret)) {
+ g_assert (!method->signature->ret->byref);
+
+ 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;
} else
printf ("this:NULL, ");
}
- ebp += sizeof (gpointer);
}
for (i = 0; i < method->signature->param_count; ++i) {
- MonoType *type = method->signature->params [i];
- int size, align;
- 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:
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));
}
case MONO_TYPE_CLASS:
case MONO_TYPE_OBJECT: {
- o = *((MonoObject **)ebp);
+ o = *((MonoObject **)cpos);
if (o) {
class = o->vtable->klass;
} else
printf ("[%s.%s:%p], ", class->name_space, class->name, o);
} else {
- printf ("%p, ", *((gpointer *)(ebp)));
+ printf ("%p, ", *((gpointer *)(cpos)));
}
break;
}
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");
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);
+#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;
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 */
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)
{
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;
+ cfg->locals_size += size;
+ cfg->locals_size += align - 1;
+ cfg->locals_size &= ~(align - 1);
- g_assert ((align & 3) == 0);
-
- 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;
}
mbstate = mono_burg_label (t1, cfg);
if (!mbstate) {
- if (mono_debug_format != MONO_DEBUG_FORMAT_NONE)
- return FALSE;
- g_warning ("tree does not match in %s",
- mono_method_full_name (cfg->method, TRUE));
+ g_warning ("tree does not match in %s: 0x%04x",
+ mono_method_full_name (cfg->method, TRUE), t1->cli_addr);
mono_print_ctree (cfg, t1); printf ("\n\n");
mono_print_forest (cfg, forest);
MonoJitInfo *ji;
guint32 ls_used_mask = 0;
MonoMethod *method = cfg->method;
+ int offset, gap;
ji = mono_mempool_alloc0 (target_domain->mp, sizeof (MonoJitInfo));
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;