*
* Copyright (C) Ximian Inc.
*
- * Author: Paolo Molaro (lupus@ximian.com)
+ * Authors:
+ * Paolo Molaro (lupus@ximian.com)
+ * Dietmar Maurer (dietmar@ximian.com)
*
*/
#define ARG_SIZE sizeof (stackval)
MonoPIFunc
-mono_create_trampoline (MonoMethodSignature *sig, gboolean string_ctor)
+mono_arch_create_trampoline (MonoMethodSignature *sig, gboolean string_ctor)
{
unsigned char *p, *code_buffer;
- guint32 local_size = 0, stack_size = 0, code_size = 50;
+ guint32 stack_size = 0, code_size = 50;
guint32 arg_pos, simpletype;
int i, stringp;
static GHashTable *cache = NULL;
if (sig->hasthis) {
stack_size += sizeof (gpointer);
- code_size += 5;
+ code_size += 10;
}
+ if (sig->ret->type == MONO_TYPE_VALUETYPE && !sig->ret->byref && !sig->ret->data.klass->enumtype) {
+ stack_size += sizeof (gpointer);
+ code_size += 5;
+ }
+
for (i = 0; i < sig->param_count; ++i) {
if (sig->params [i]->byref) {
stack_size += sizeof (gpointer);
code_size += 20;
- local_size++;
continue;
}
simpletype = sig->params [i]->type;
case MONO_TYPE_I:
case MONO_TYPE_U:
case MONO_TYPE_PTR:
- case MONO_TYPE_R4:
case MONO_TYPE_SZARRAY:
case MONO_TYPE_CLASS:
case MONO_TYPE_OBJECT:
+ case MONO_TYPE_STRING:
stack_size += 4;
code_size += i < 10 ? 5 : 8;
break;
simpletype = sig->params [i]->data.klass->enum_basetype->type;
goto enum_calc_size;
}
- if ((size = mono_class_value_size (sig->params [i]->data.klass, NULL)) != 4) {
+ if ((size = mono_class_native_size (sig->params [i]->data.klass, NULL)) != 4) {
stack_size += size + 3;
stack_size &= ~3;
code_size += 32;
}
break;
}
- case MONO_TYPE_STRING:
- stack_size += 4;
- code_size += 20;
- local_size++;
- break;
case MONO_TYPE_I8:
stack_size += 8;
code_size += i < 10 ? 5 : 8;
break;
+ case MONO_TYPE_R4:
+ stack_size += 4;
+ code_size += i < 10 ? 10 : 13;
+ break;
case MONO_TYPE_R8:
stack_size += 8;
code_size += i < 10 ? 7 : 10;
x86_push_reg (p, X86_EBP);
x86_mov_reg_reg (p, X86_EBP, X86_ESP, 4);
/*
- * We store some local vars here to handle string pointers.
* and align to 16 byte boundary...
*/
- if (local_size) {
- x86_alu_reg_imm (p, X86_SUB, X86_ESP, local_size * 4);
- stack_size = (stack_size * local_size * 4) % 16;
- } else {
- stack_size = stack_size % 16;
- }
+ stack_size += 15;
+ stack_size &= ~15;
+
if (stack_size)
x86_alu_reg_imm (p, X86_SUB, X86_ESP, stack_size);
case MONO_TYPE_U:
case MONO_TYPE_PTR:
case MONO_TYPE_OBJECT:
+ case MONO_TYPE_STRING:
x86_push_membase (p, X86_EDX, arg_pos);
break;
case MONO_TYPE_R4:
break;
case MONO_TYPE_VALUETYPE:
if (!sig->params [i - 1]->data.klass->enumtype) {
- int size = mono_class_value_size (sig->params [i - 1]->data.klass, NULL);
+ int size = mono_class_native_size (sig->params [i - 1]->data.klass, NULL);
if (size == 4) {
/* it's a structure that fits in 4 bytes, need to push the value pointed to */
x86_mov_reg_membase (p, X86_EAX, X86_EDX, arg_pos, 4);
x86_mov_reg_imm (p, X86_EAX, memcpy);
x86_call_reg (p, X86_EAX);
x86_alu_reg_imm (p, X86_ADD, X86_ESP, 12);
+ /* memcpy might clobber EDX so restore it */
+ x86_mov_reg_membase (p, X86_EDX, X86_EBP, ARGP_POS, 4);
}
} else {
/* it's an enum value */
goto enum_marshal;
}
break;
- case MONO_TYPE_STRING:
- x86_push_membase (p, X86_EDX, arg_pos);
- break;
case MONO_TYPE_I8:
case MONO_TYPE_U8:
case MONO_TYPE_R8:
}
}
+ if (sig->ret->type == MONO_TYPE_VALUETYPE && !sig->ret->byref) {
+ MonoClass *klass = sig->ret->data.klass;
+ if (!klass->enumtype) {
+ x86_mov_reg_membase (p, X86_ECX, X86_EBP, RETVAL_POS, 4);
+ x86_push_membase (p, X86_ECX, 0);
+ }
+ }
+
/*
* Insert call to function
*/
#define MINV_POS (- sizeof (MonoInvocation))
#define STACK_POS (MINV_POS - sizeof (stackval) * sig->param_count)
-#define OBJ_POS 8
#define TYPE_OFFSET (G_STRUCT_OFFSET (stackval, type))
/*
* across the managed/unmanaged boundary.
*/
void *
-mono_create_method_pointer (MonoMethod *method)
+mono_arch_create_method_pointer (MonoMethod *method)
{
MonoMethodSignature *sig;
MonoJitInfo *ji;
gint32 local_size;
gint32 stackval_pos, arg_pos = 8;
int i, size, align, cpos;
- int vtbuf [sig->param_count];
-
- /*
- * If it is a static P/Invoke method, we can just return the pointer
- * to the method implementation.
- */
- if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL && method->addr) {
- ji = g_new0 (MonoJitInfo, 1);
- ji->method = method;
- ji->code_size = 1;
- ji->code_start = method->addr;
-
- mono_jit_info_table_add (mono_root_domain, ji);
- return method->addr;
- }
+ int *vtbuf;
sig = method->signature;
code_buffer = p = alloca (512); /* FIXME: check for overflows... */
+ vtbuf = alloca (sizeof(int)*sig->param_count);
local_size = sizeof (MonoInvocation) + sizeof (stackval) * (sig->param_count + 1);
x86_mov_reg_imm (p, X86_EAX, 0);
x86_mov_membase_reg (p, X86_EBP, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, ex)), X86_EAX, 4);
x86_mov_membase_reg (p, X86_EBP, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, ex_handler)), X86_EAX, 4);
- x86_mov_membase_reg (p, X86_EBP, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, child)), X86_EAX, 4);
x86_mov_membase_reg (p, X86_EBP, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, parent)), X86_EAX, 4);
/*
* Set the method pointer.
*/
x86_mov_membase_imm (p, X86_EBP, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, method)), (int)method, 4);
+
+ if (sig->ret->type == MONO_TYPE_VALUETYPE && !sig->ret->byref && !sig->ret->data.klass->enumtype)
+ arg_pos += 4;
+
/*
* Handle this.
*/
/*
* Grab it from the stack, otherwise it's already in ECX.
*/
- x86_mov_reg_membase (p, X86_ECX, X86_EBP, OBJ_POS, 4);
+ x86_mov_reg_membase (p, X86_ECX, X86_EBP, arg_pos, 4);
arg_pos += 4;
}
x86_mov_membase_reg (p, X86_EBP, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, obj)), X86_ECX, 4);
x86_call_reg (p, X86_ECX);
x86_alu_reg_imm (p, X86_SUB, X86_ESP, 16);
stackval_pos += sizeof (stackval);
+ /* fixme: alignment */
if (sig->pinvoke)
arg_pos += mono_type_native_stack_size (sig->params [i], &align);
else
*/
x86_lea_membase (p, X86_EAX, X86_EBP, stackval_pos);
x86_mov_membase_reg (p, X86_EBP, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, retval)), X86_EAX, 4);
+ if (sig->ret->type == MONO_TYPE_VALUETYPE && !sig->ret->byref) {
+ MonoClass *klass = sig->ret->data.klass;
+ if (!klass->enumtype) {
+ x86_mov_reg_membase (p, X86_ECX, X86_EBP, 8, 4);
+ x86_mov_membase_reg (p, X86_EBP, stackval_pos, X86_ECX, 4);
+ }
+ }
/*
* Call the method.
x86_push_reg (p, X86_EAX);
x86_mov_reg_imm (p, X86_EDX, ves_exec_method);
x86_call_reg (p, X86_EDX);
-
+
/*
* Move the return value to the proper place.
*/
case MONO_TYPE_VOID:
break;
case MONO_TYPE_BOOLEAN:
+ case MONO_TYPE_I1:
+ case MONO_TYPE_U1:
x86_mov_reg_membase (p, X86_EAX, X86_EAX, 0, 1);
break;
+ case MONO_TYPE_CHAR:
+ case MONO_TYPE_I2:
+ case MONO_TYPE_U2:
+ x86_mov_reg_membase (p, X86_EAX, X86_EAX, 0, 2);
+ break;
case MONO_TYPE_I4:
case MONO_TYPE_U4:
case MONO_TYPE_I:
simpletype = sig->ret->data.klass->enum_basetype->type;
goto enum_retvalue;
}
- /* do nothing ? */
+
+ x86_push_imm (p, sig->pinvoke);
+ x86_push_membase (p, X86_EBP, stackval_pos);
+ x86_push_reg (p, X86_EAX);
+ x86_push_imm (p, sig->ret);
+ x86_mov_reg_imm (p, X86_ECX, stackval_to_data);
+ x86_call_reg (p, X86_ECX);
+ x86_alu_reg_imm (p, X86_SUB, X86_ESP, 16);
+
break;
default:
g_error ("Type 0x%x not handled yet in thunk creation", sig->ret->type);
ji->code_size = p - code_buffer;
ji->code_start = g_memdup (code_buffer, p - code_buffer);
- mono_jit_info_table_add (mono_root_domain, ji);
+ mono_jit_info_table_add (mono_get_root_domain (), ji);
return ji->code_start;
}